Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpmyadmin/phpmyadmin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Foellmann <foellmann@foe-services.de>2015-09-24 13:19:45 +0300
committerChristian Foellmann <foellmann@foe-services.de>2015-09-24 13:19:45 +0300
commit718ef314e378018e60a869cc92507bfc489c0a7b (patch)
tree1e3583bbe1123155a4f2e3f7a691ed944652e8c6
parent05e6990420b33a70a4915153289793a22837c0f9 (diff)
UPDATE 4.5.0.14.5.0.1
-rw-r--r--CONTRIBUTING.md9
-rw-r--r--ChangeLog114
-rw-r--r--LICENSE39
-rw-r--r--README2
-rw-r--r--browse_foreigners.php1
-rw-r--r--changelog.php5
-rw-r--r--chk_rel.php11
-rw-r--r--config.sample.inc.php37
-rw-r--r--db_central_columns.php37
-rw-r--r--db_create.php6
-rw-r--r--db_datadict.php39
-rw-r--r--db_designer.php50
-rw-r--r--db_events.php2
-rw-r--r--db_export.php115
-rw-r--r--db_import.php25
-rw-r--r--db_operations.php42
-rw-r--r--db_printview.php175
-rw-r--r--db_qbe.php41
-rw-r--r--db_routines.php3
-rw-r--r--db_search.php17
-rw-r--r--db_sql.php5
-rw-r--r--db_sql_autocomplete.php22
-rw-r--r--db_sql_format.php10
-rw-r--r--db_structure.php373
-rw-r--r--db_tracking.php248
-rw-r--r--db_triggers.php2
-rw-r--r--error_report.php1
-rw-r--r--export.php174
-rw-r--r--favicon.icobin18902 -> 22486 bytes
-rw-r--r--file_echo.php1
-rw-r--r--gis_data_editor.php13
-rw-r--r--import.php135
-rw-r--r--import_status.php1
-rw-r--r--index.php104
-rw-r--r--js/ajax.js576
-rw-r--r--js/codemirror/LICENSE2
-rw-r--r--js/codemirror/addon/hint/show-hint.css38
-rw-r--r--js/codemirror/addon/hint/show-hint.js133
-rw-r--r--js/codemirror/addon/hint/sql-hint.js30
-rw-r--r--js/codemirror/addon/lint/lint.css77
-rw-r--r--js/codemirror/addon/lint/lint.js209
-rw-r--r--js/codemirror/addon/lint/sql-lint.js39
-rw-r--r--js/codemirror/lib/codemirror.css325
-rw-r--r--js/codemirror/lib/codemirror.js390
-rw-r--r--js/codemirror/mode/javascript/javascript.js18
-rw-r--r--js/codemirror/mode/sql/sql.js12
-rw-r--r--js/common.js17
-rw-r--r--js/config.js158
-rw-r--r--js/console.js729
-rw-r--r--js/db_central_columns.js80
-rw-r--r--js/db_qbe.js19
-rw-r--r--js/db_structure.js67
-rw-r--r--js/db_tracking.js18
-rw-r--r--js/error_report.js44
-rw-r--r--js/export.js542
-rw-r--r--js/functions.js698
-rw-r--r--js/get_image.js.php12
-rw-r--r--js/get_scripts.js.php11
-rw-r--r--js/gis_data_editor.js6
-rw-r--r--js/import.js6
-rw-r--r--js/indexes.js164
-rw-r--r--js/jquery/additional-methods.js940
-rw-r--r--js/jquery/jquery.validate.js1365
-rw-r--r--js/line_counts.php100
-rw-r--r--js/makegrid.js316
-rw-r--r--js/menu-resizer.js5
-rw-r--r--js/messages.php213
-rw-r--r--js/microhistory.js331
-rw-r--r--js/navigation.js138
-rw-r--r--js/normalization.js99
-rw-r--r--js/page_settings.js59
-rw-r--r--js/pmd/designer_page.js18
-rw-r--r--js/pmd/history.js220
-rw-r--r--js/pmd/iecanvas.js6
-rw-r--r--js/pmd/init.js3
-rw-r--r--js/pmd/move.js144
-rw-r--r--js/replication.js5
-rw-r--r--js/rte.js175
-rw-r--r--js/server_databases.js4
-rw-r--r--js/server_plugins.js18
-rw-r--r--js/server_privileges.js54
-rw-r--r--js/server_status_advisor.js6
-rw-r--r--js/server_status_monitor.js213
-rw-r--r--js/server_status_processes.js7
-rw-r--r--js/server_status_sorter.js6
-rw-r--r--js/server_status_variables.js8
-rw-r--r--js/server_variables.js2
-rw-r--r--js/sql.js61
-rw-r--r--js/tbl_change.js394
-rw-r--r--js/tbl_chart.js158
-rw-r--r--js/tbl_gis_visualization.js23
-rw-r--r--js/tbl_operations.js76
-rw-r--r--js/tbl_relation.js10
-rw-r--r--js/tbl_select.js14
-rw-r--r--js/tbl_structure.js173
-rw-r--r--js/tbl_tracking.js4
-rw-r--r--js/tbl_zoom_plot_jqplot.js46
-rw-r--r--js/transformations/json_editor.js4
-rw-r--r--js/transformations/sql_editor.js22
-rw-r--r--js/transformations/xml_editor.js4
-rw-r--r--js/whitelist.php9
-rw-r--r--libraries/Advisor.class.php4
-rw-r--r--libraries/Config.class.php245
-rw-r--r--libraries/Console.class.php142
-rw-r--r--libraries/DBQbe.class.php588
-rw-r--r--libraries/DatabaseInterface.class.php539
-rw-r--r--libraries/DbSearch.class.php8
-rw-r--r--libraries/DisplayResults.class.php1772
-rw-r--r--libraries/Error.class.php13
-rw-r--r--libraries/Error_Handler.class.php31
-rw-r--r--libraries/File.class.php29
-rw-r--r--libraries/Font.class.php1
-rw-r--r--libraries/Footer.class.php65
-rw-r--r--libraries/Header.class.php53
-rw-r--r--libraries/Index.class.php64
-rw-r--r--libraries/Linter.class.php177
-rw-r--r--libraries/List.class.php1
-rw-r--r--libraries/List_Database.class.php1
-rw-r--r--libraries/Menu.class.php35
-rw-r--r--libraries/Message.class.php1
-rw-r--r--libraries/OutputBuffering.class.php1
-rw-r--r--libraries/PDF.class.php10
-rw-r--r--libraries/PMA.php1
-rw-r--r--libraries/Partition.class.php366
-rw-r--r--libraries/RecentFavoriteTable.class.php1
-rw-r--r--libraries/Response.class.php12
-rw-r--r--libraries/Scripts.class.php19
-rw-r--r--libraries/ServerStatusData.class.php282
-rw-r--r--libraries/StorageEngine.class.php16
-rw-r--r--libraries/String.class.php1
-rw-r--r--libraries/StringAbstractType.class.php1
-rw-r--r--libraries/StringByte.int.php8
-rw-r--r--libraries/StringCType.class.php1
-rw-r--r--libraries/StringNativeType.class.php1
-rw-r--r--libraries/StringType.int.php7
-rw-r--r--libraries/SystemDatabase.class.php130
-rw-r--r--libraries/Table.class.php2067
-rw-r--r--libraries/TableSearch.class.php1587
-rw-r--r--libraries/Template.class.php98
-rw-r--r--libraries/Theme.class.php1
-rw-r--r--libraries/Theme_Manager.class.php49
-rw-r--r--libraries/Tracker.class.php16
-rw-r--r--libraries/Types.class.php238
-rw-r--r--libraries/Util.class.php1124
-rw-r--r--libraries/advisory_rules.txt4
-rw-r--r--libraries/bfShapeFiles/ShapeFile.lib.php1
-rw-r--r--libraries/bookmark.lib.php135
-rw-r--r--libraries/browse_foreigners.lib.php178
-rw-r--r--libraries/build_html_for_db.lib.php7
-rw-r--r--libraries/central_columns.lib.php597
-rw-r--r--libraries/charset_conversion.lib.php5
-rw-r--r--libraries/check_user_privileges.lib.php227
-rw-r--r--libraries/cleanup.lib.php32
-rw-r--r--libraries/common.inc.php78
-rw-r--r--libraries/config.default.php233
-rw-r--r--libraries/config.values.php74
-rw-r--r--libraries/config/ConfigFile.class.php3
-rw-r--r--libraries/config/Form.class.php1
-rw-r--r--libraries/config/FormDisplay.class.php156
-rw-r--r--libraries/config/FormDisplay.tpl.php234
-rw-r--r--libraries/config/ServerConfigChecks.class.php144
-rw-r--r--libraries/config/Validator.class.php24
-rw-r--r--libraries/config/config_functions.lib.php1
-rw-r--r--libraries/config/messages.inc.php324
-rw-r--r--libraries/config/page_settings.class.php230
-rw-r--r--libraries/config/page_settings.forms.php29
-rw-r--r--libraries/config/setup.forms.php41
-rw-r--r--libraries/config/user_preferences.forms.php54
-rw-r--r--libraries/controllers/Controller.class.php55
-rw-r--r--libraries/controllers/DatabaseController.class.php39
-rw-r--r--libraries/controllers/DatabaseStructureController.class.php1062
-rw-r--r--libraries/controllers/TableChartController.class.php248
-rw-r--r--libraries/controllers/TableController.class.php45
-rw-r--r--libraries/controllers/TableGisVisualizationController.class.php216
-rw-r--r--libraries/controllers/TableIndexesController.class.php180
-rw-r--r--libraries/controllers/TableRelationController.class.php384
-rw-r--r--libraries/controllers/TableSearchController.class.php1225
-rw-r--r--libraries/controllers/TableStructureController.class.php1252
-rw-r--r--libraries/core.lib.php31
-rw-r--r--libraries/create_addfield.lib.php25
-rw-r--r--libraries/data_dictionary_relations.lib.php1
-rw-r--r--libraries/database_interface.inc.php48
-rw-r--r--libraries/db_common.inc.php11
-rw-r--r--libraries/db_designer.lib.php1291
-rw-r--r--libraries/db_info.inc.php248
-rw-r--r--libraries/db_printview.lib.php30
-rw-r--r--libraries/db_table_exists.lib.php3
-rw-r--r--libraries/dbi/DBIDrizzle.class.php77
-rw-r--r--libraries/dbi/DBIDummy.class.php180
-rw-r--r--libraries/dbi/DBIExtension.int.php33
-rw-r--r--libraries/dbi/DBIMysql.class.php5
-rw-r--r--libraries/dbi/DBIMysqli.class.php4
-rw-r--r--libraries/dbi/drizzle-wrappers.lib.php5
-rw-r--r--libraries/di/AliasItem.class.php49
-rw-r--r--libraries/di/Container.class.php174
-rw-r--r--libraries/di/FactoryItem.class.php43
-rw-r--r--libraries/di/Item.int.php26
-rw-r--r--libraries/di/ReflectorItem.class.php127
-rw-r--r--libraries/di/ServiceItem.class.php48
-rw-r--r--libraries/di/ValueItem.class.php44
-rw-r--r--libraries/display_change_password.lib.php79
-rw-r--r--libraries/display_create_database.lib.php1
-rw-r--r--libraries/display_create_table.lib.php41
-rw-r--r--libraries/display_export.inc.php10
-rw-r--r--libraries/display_export.lib.php223
-rw-r--r--libraries/display_import.inc.php64
-rw-r--r--libraries/display_import.lib.php125
-rw-r--r--libraries/display_import_ajax.lib.php1
-rw-r--r--libraries/display_select_lang.lib.php1
-rw-r--r--libraries/display_structure.inc.php272
-rw-r--r--libraries/engines/bdb.lib.php1
-rw-r--r--libraries/engines/berkeleydb.lib.php1
-rw-r--r--libraries/engines/binlog.lib.php1
-rw-r--r--libraries/engines/innobase.lib.php1
-rw-r--r--libraries/engines/innodb.lib.php24
-rw-r--r--libraries/engines/memory.lib.php1
-rw-r--r--libraries/engines/merge.lib.php1
-rw-r--r--libraries/engines/mrg_myisam.lib.php1
-rw-r--r--libraries/engines/myisam.lib.php41
-rw-r--r--libraries/engines/ndbcluster.lib.php1
-rw-r--r--libraries/engines/pbxt.lib.php66
-rw-r--r--libraries/engines/performance_schema.lib.php1
-rw-r--r--libraries/error_report.lib.php55
-rw-r--r--libraries/export.lib.php364
-rw-r--r--libraries/gis/GIS_Factory.class.php1
-rw-r--r--libraries/gis/GIS_Geometry.class.php1
-rw-r--r--libraries/gis/GIS_Geometrycollection.class.php1
-rw-r--r--libraries/gis/GIS_Linestring.class.php1
-rw-r--r--libraries/gis/GIS_Multilinestring.class.php1
-rw-r--r--libraries/gis/GIS_Multipoint.class.php1
-rw-r--r--libraries/gis/GIS_Multipolygon.class.php1
-rw-r--r--libraries/gis/GIS_Point.class.php1
-rw-r--r--libraries/gis/GIS_Polygon.class.php1
-rw-r--r--libraries/gis/GIS_Visualization.class.php184
-rw-r--r--libraries/iconv_wrapper.lib.php1
-rw-r--r--libraries/import.lib.php447
-rw-r--r--libraries/index.lib.php12
-rw-r--r--libraries/information_schema_relations.lib.php1
-rw-r--r--libraries/insert_edit.lib.php196
-rw-r--r--libraries/ip_allow_deny.lib.php1
-rw-r--r--libraries/js_escape.lib.php43
-rw-r--r--libraries/kanji-encoding.lib.php1
-rw-r--r--libraries/language_stats.inc.php126
-rw-r--r--libraries/logging.lib.php1
-rw-r--r--libraries/mime.lib.php1
-rw-r--r--libraries/mult_submits.inc.php198
-rw-r--r--libraries/mult_submits.lib.php138
-rw-r--r--libraries/mysql_charsets.inc.php1
-rw-r--r--libraries/mysql_charsets.lib.php16
-rw-r--r--libraries/mysql_relations.lib.php1
-rw-r--r--libraries/navigation/Navigation.class.php7
-rw-r--r--libraries/navigation/NavigationHeader.class.php100
-rw-r--r--libraries/navigation/NavigationTree.class.php177
-rw-r--r--libraries/navigation/NodeFactory.class.php1
-rw-r--r--libraries/navigation/Nodes/Node.class.php41
-rw-r--r--libraries/navigation/Nodes/Node_Column.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Column_Container.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Database.class.php125
-rw-r--r--libraries/navigation/Nodes/Node_DatabaseChild.class.php25
-rw-r--r--libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php47
-rw-r--r--libraries/navigation/Nodes/Node_Database_Container.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Event.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Event_Container.class.php7
-rw-r--r--libraries/navigation/Nodes/Node_Function.class.php7
-rw-r--r--libraries/navigation/Nodes/Node_Function_Container.class.php5
-rw-r--r--libraries/navigation/Nodes/Node_Index.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Index_Container.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Procedure.class.php7
-rw-r--r--libraries/navigation/Nodes/Node_Procedure_Container.class.php7
-rw-r--r--libraries/navigation/Nodes/Node_Table.class.php76
-rw-r--r--libraries/navigation/Nodes/Node_Table_Container.class.php13
-rw-r--r--libraries/navigation/Nodes/Node_Trigger.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_Trigger_Container.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_View.class.php3
-rw-r--r--libraries/navigation/Nodes/Node_View_Container.class.php13
-rw-r--r--libraries/normalization.lib.php137
-rw-r--r--libraries/opendocument.lib.php1
-rw-r--r--libraries/operations.lib.php883
-rw-r--r--libraries/parse_analyze.inc.php155
-rw-r--r--libraries/php-gettext/gettext.php1
-rw-r--r--libraries/php-gettext/streams.php1
-rw-r--r--libraries/phpseclib/Crypt/Base.php2
-rw-r--r--libraries/plugin_interface.lib.php4
-rw-r--r--libraries/plugins/AuthenticationPlugin.class.php5
-rw-r--r--libraries/plugins/ExportPlugin.class.php42
-rw-r--r--libraries/plugins/IOTransformationsPlugin.class.php7
-rw-r--r--libraries/plugins/ImportPlugin.class.php3
-rw-r--r--libraries/plugins/SchemaPlugin.class.php3
-rw-r--r--libraries/plugins/TransformationsInterface.int.php1
-rw-r--r--libraries/plugins/TransformationsPlugin.class.php3
-rw-r--r--libraries/plugins/UploadInterface.int.php1
-rw-r--r--libraries/plugins/auth/AuthenticationConfig.class.php4
-rw-r--r--libraries/plugins/auth/AuthenticationCookie.class.php20
-rw-r--r--libraries/plugins/auth/AuthenticationHttp.class.php9
-rw-r--r--libraries/plugins/auth/swekey/swekey.auth.lib.php25
-rw-r--r--libraries/plugins/export/ExportCodegen.class.php17
-rw-r--r--libraries/plugins/export/ExportCsv.class.php16
-rw-r--r--libraries/plugins/export/ExportExcel.class.php1
-rw-r--r--libraries/plugins/export/ExportHtmlword.class.php20
-rw-r--r--libraries/plugins/export/ExportJson.class.php39
-rw-r--r--libraries/plugins/export/ExportLatex.class.php16
-rw-r--r--libraries/plugins/export/ExportMediawiki.class.php18
-rw-r--r--libraries/plugins/export/ExportOds.class.php16
-rw-r--r--libraries/plugins/export/ExportOdt.class.php16
-rw-r--r--libraries/plugins/export/ExportPdf.class.php140
-rw-r--r--libraries/plugins/export/ExportPhparray.class.php18
-rw-r--r--libraries/plugins/export/ExportSql.class.php1136
-rw-r--r--libraries/plugins/export/ExportTexytext.class.php24
-rw-r--r--libraries/plugins/export/ExportXml.class.php20
-rw-r--r--libraries/plugins/export/ExportYaml.class.php16
-rw-r--r--libraries/plugins/export/PMA_ExportPdf.class.php387
-rw-r--r--libraries/plugins/export/TableProperty.class.php25
-rw-r--r--libraries/plugins/import/AbstractImportCsv.class.php8
-rw-r--r--libraries/plugins/import/ImportCsv.class.php32
-rw-r--r--libraries/plugins/import/ImportLdi.class.php4
-rw-r--r--libraries/plugins/import/ImportMediawiki.class.php10
-rw-r--r--libraries/plugins/import/ImportOds.class.php11
-rw-r--r--libraries/plugins/import/ImportShp.class.php1
-rw-r--r--libraries/plugins/import/ImportSql.class.php485
-rw-r--r--libraries/plugins/import/ImportXml.class.php15
-rw-r--r--libraries/plugins/import/ShapeFile.class.php9
-rw-r--r--libraries/plugins/import/ShapeRecord.class.php11
-rw-r--r--libraries/plugins/import/upload/UploadApc.class.php1
-rw-r--r--libraries/plugins/import/upload/UploadNoplugin.class.php1
-rw-r--r--libraries/plugins/import/upload/UploadProgress.class.php1
-rw-r--r--libraries/plugins/import/upload/UploadSession.class.php1
-rw-r--r--libraries/plugins/schema/Export_Relation_Schema.class.php23
-rw-r--r--libraries/plugins/schema/RelationStats.class.php9
-rw-r--r--libraries/plugins/schema/SchemaDia.class.php3
-rw-r--r--libraries/plugins/schema/SchemaEps.class.php3
-rw-r--r--libraries/plugins/schema/SchemaPdf.class.php17
-rw-r--r--libraries/plugins/schema/SchemaSvg.class.php3
-rw-r--r--libraries/plugins/schema/TableStats.class.php1
-rw-r--r--libraries/plugins/schema/dia/Dia_Relation_Schema.class.php47
-rw-r--r--libraries/plugins/schema/dia/RelationStatsDia.class.php18
-rw-r--r--libraries/plugins/schema/dia/TableStatsDia.class.php40
-rw-r--r--libraries/plugins/schema/eps/Eps_Relation_Schema.class.php133
-rw-r--r--libraries/plugins/schema/eps/RelationStatsEps.class.php27
-rw-r--r--libraries/plugins/schema/eps/TableStatsEps.class.php27
-rw-r--r--libraries/plugins/schema/pdf/Pdf_Relation_Schema.class.php416
-rw-r--r--libraries/plugins/schema/pdf/RelationStatsPdf.class.php35
-rw-r--r--libraries/plugins/schema/pdf/TableStatsPdf.class.php69
-rw-r--r--libraries/plugins/schema/svg/RelationStatsSvg.class.php56
-rw-r--r--libraries/plugins/schema/svg/Svg_Relation_Schema.class.php132
-rw-r--r--libraries/plugins/schema/svg/TableStatsSvg.class.php39
-rw-r--r--libraries/plugins/transformations/Text_Plain_Link.class.php1
-rw-r--r--libraries/plugins/transformations/Text_Plain_Longtoipv4.class.php1
-rw-r--r--libraries/plugins/transformations/Text_Plain_Preappend.class.php1
-rw-r--r--libraries/plugins/transformations/Text_Plain_Substring.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/Bool2TextTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/CodeMirrorEditorTransformationPlugin.class.php7
-rw-r--r--libraries/plugins/transformations/abstract/DateFormatTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/DownloadTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/ExternalTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/FormattedTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/HexTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/ImageLinkTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/ImageUploadTransformationsPlugin.class.php7
-rw-r--r--libraries/plugins/transformations/abstract/InlineTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/LongToIPv4TransformationsPlugin.class.php5
-rw-r--r--libraries/plugins/transformations/abstract/PreApPendTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/RegexValidationTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/SQLTransformationsPlugin.class.php3
-rw-r--r--libraries/plugins/transformations/abstract/SubstringTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/TextFileUploadTransformationsPlugin.class.php7
-rw-r--r--libraries/plugins/transformations/abstract/TextImageLinkTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/abstract/TextLinkTransformationsPlugin.class.php1
-rw-r--r--libraries/plugins/transformations/input/Image_JPEG_Upload.class.php1
-rw-r--r--libraries/plugins/transformations/input/Text_Plain_Fileupload.class.php1
-rw-r--r--libraries/plugins/transformations/input/Text_Plain_Iptobinary.class.php133
-rw-r--r--libraries/plugins/transformations/input/Text_Plain_JsonEditor.class.php1
-rw-r--r--libraries/plugins/transformations/input/Text_Plain_Regexvalidation.class.php1
-rw-r--r--libraries/plugins/transformations/input/Text_Plain_SqlEditor.class.php1
-rw-r--r--libraries/plugins/transformations/input/Text_Plain_XmlEditor.class.php1
-rw-r--r--libraries/plugins/transformations/output/Application_Octetstream_Download.class.php1
-rw-r--r--libraries/plugins/transformations/output/Application_Octetstream_Hex.class.php1
-rw-r--r--libraries/plugins/transformations/output/Image_JPEG_Inline.class.php1
-rw-r--r--libraries/plugins/transformations/output/Image_JPEG_Link.class.php1
-rw-r--r--libraries/plugins/transformations/output/Image_PNG_Inline.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Octetstream_Sql.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Binarytoip.class.php93
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Bool2text.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Dateformat.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_External.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Formatted.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Imagelink.class.php1
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Json.class.php4
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Sql.class.php4
-rw-r--r--libraries/plugins/transformations/output/Text_Plain_Xml.class.php4
-rw-r--r--libraries/pmd_common.php141
-rw-r--r--libraries/properties/PropertyItem.class.php1
-rw-r--r--libraries/properties/options/OptionsPropertyGroup.class.php1
-rw-r--r--libraries/properties/options/OptionsPropertyItem.class.php1
-rw-r--r--libraries/properties/options/OptionsPropertyOneItem.class.php1
-rw-r--r--libraries/properties/options/groups/OptionsPropertyMainGroup.class.php1
-rw-r--r--libraries/properties/options/groups/OptionsPropertyRootGroup.class.php1
-rw-r--r--libraries/properties/options/groups/OptionsPropertySubgroup.class.php1
-rw-r--r--libraries/properties/options/items/BoolPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/DocPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/HiddenPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/MessageOnlyPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/NumberPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/RadioPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/SelectPropertyItem.class.php1
-rw-r--r--libraries/properties/options/items/TextPropertyItem.class.php1
-rw-r--r--libraries/properties/plugins/ExportPluginProperties.class.php1
-rw-r--r--libraries/properties/plugins/PluginPropertyItem.class.php1
-rw-r--r--libraries/properties/plugins/SchemaPluginProperties.class.php1
-rw-r--r--libraries/relation.lib.php304
-rw-r--r--libraries/relation_cleanup.lib.php87
-rw-r--r--libraries/replication.inc.php28
-rw-r--r--libraries/replication_gui.lib.php53
-rw-r--r--libraries/rte/rte_events.lib.php22
-rw-r--r--libraries/rte/rte_export.lib.php8
-rw-r--r--libraries/rte/rte_footer.lib.php1
-rw-r--r--libraries/rte/rte_list.lib.php125
-rw-r--r--libraries/rte/rte_main.inc.php14
-rw-r--r--libraries/rte/rte_routines.lib.php785
-rw-r--r--libraries/rte/rte_triggers.lib.php1
-rw-r--r--libraries/rte/rte_words.lib.php1
-rw-r--r--libraries/sanitizing.lib.php1
-rw-r--r--libraries/select_lang.lib.php4
-rw-r--r--libraries/select_server.lib.php15
-rw-r--r--libraries/server_bin_log.lib.php19
-rw-r--r--libraries/server_collations.lib.php1
-rw-r--r--libraries/server_common.inc.php1
-rw-r--r--libraries/server_common.lib.php1
-rw-r--r--libraries/server_databases.lib.php41
-rw-r--r--libraries/server_engines.lib.php1
-rw-r--r--libraries/server_plugins.lib.php105
-rw-r--r--libraries/server_privileges.lib.php798
-rw-r--r--libraries/server_status.lib.php86
-rw-r--r--libraries/server_status_advisor.lib.php1
-rw-r--r--libraries/server_status_monitor.lib.php5
-rw-r--r--libraries/server_status_processes.lib.php31
-rw-r--r--libraries/server_status_queries.lib.php1
-rw-r--r--libraries/server_status_variables.lib.php5
-rw-r--r--libraries/server_user_groups.lib.php5
-rw-r--r--libraries/server_users.lib.php3
-rw-r--r--libraries/server_variables.lib.php810
-rw-r--r--libraries/session.inc.php8
-rw-r--r--libraries/special_schema_links.lib.php61
-rw-r--r--libraries/sql-formatter/LICENSE.txt21
-rw-r--r--libraries/sql-formatter/README.md185
-rw-r--r--libraries/sql-formatter/lib/SqlFormatter.php1085
-rw-r--r--libraries/sql-parser/ClassLoader.php250
-rw-r--r--libraries/sql-parser/autoload.php68
-rw-r--r--libraries/sql-parser/src/Component.php98
-rw-r--r--libraries/sql-parser/src/Components/AlterOperation.php226
-rw-r--r--libraries/sql-parser/src/Components/Array2d.php135
-rw-r--r--libraries/sql-parser/src/Components/ArrayObj.php160
-rw-r--r--libraries/sql-parser/src/Components/Condition.php212
-rw-r--r--libraries/sql-parser/src/Components/CreateDefinition.php314
-rw-r--r--libraries/sql-parser/src/Components/DataType.php170
-rw-r--r--libraries/sql-parser/src/Components/Expression.php386
-rw-r--r--libraries/sql-parser/src/Components/ExpressionArray.php121
-rw-r--r--libraries/sql-parser/src/Components/FunctionCall.php126
-rw-r--r--libraries/sql-parser/src/Components/IntoKeyword.php150
-rw-r--r--libraries/sql-parser/src/Components/JoinKeyword.php167
-rw-r--r--libraries/sql-parser/src/Components/Key.php170
-rw-r--r--libraries/sql-parser/src/Components/Limit.php137
-rw-r--r--libraries/sql-parser/src/Components/OptionsArray.php344
-rw-r--r--libraries/sql-parser/src/Components/OrderKeyword.php142
-rw-r--r--libraries/sql-parser/src/Components/ParameterDefinition.php162
-rw-r--r--libraries/sql-parser/src/Components/PartitionDefinition.php215
-rw-r--r--libraries/sql-parser/src/Components/Reference.php152
-rw-r--r--libraries/sql-parser/src/Components/RenameOperation.php177
-rw-r--r--libraries/sql-parser/src/Components/SetOperation.php137
-rw-r--r--libraries/sql-parser/src/Components/UnionKeyword.php36
-rw-r--r--libraries/sql-parser/src/Context.php524
-rw-r--r--libraries/sql-parser/src/Contexts/ContextMySql50000.php281
-rw-r--r--libraries/sql-parser/src/Contexts/ContextMySql50100.php305
-rw-r--r--libraries/sql-parser/src/Contexts/ContextMySql50500.php309
-rw-r--r--libraries/sql-parser/src/Contexts/ContextMySql50600.php339
-rw-r--r--libraries/sql-parser/src/Contexts/ContextMySql50700.php351
-rw-r--r--libraries/sql-parser/src/Exceptions/LexerException.php51
-rw-r--r--libraries/sql-parser/src/Exceptions/ParserException.php44
-rw-r--r--libraries/sql-parser/src/Lexer.php881
-rw-r--r--libraries/sql-parser/src/Parser.php547
-rw-r--r--libraries/sql-parser/src/Statement.php355
-rw-r--r--libraries/sql-parser/src/Statements/AlterStatement.php140
-rw-r--r--libraries/sql-parser/src/Statements/AnalyzeStatement.php48
-rw-r--r--libraries/sql-parser/src/Statements/BackupStatement.php39
-rw-r--r--libraries/sql-parser/src/Statements/CallStatement.php38
-rw-r--r--libraries/sql-parser/src/Statements/CheckStatement.php41
-rw-r--r--libraries/sql-parser/src/Statements/ChecksumStatement.php37
-rw-r--r--libraries/sql-parser/src/Statements/CreateStatement.php554
-rw-r--r--libraries/sql-parser/src/Statements/DeleteStatement.php99
-rw-r--r--libraries/sql-parser/src/Statements/DropStatement.php70
-rw-r--r--libraries/sql-parser/src/Statements/ExplainStatement.php23
-rw-r--r--libraries/sql-parser/src/Statements/InsertStatement.php82
-rw-r--r--libraries/sql-parser/src/Statements/MaintenanceStatement.php68
-rw-r--r--libraries/sql-parser/src/Statements/NotImplementedStatement.php68
-rw-r--r--libraries/sql-parser/src/Statements/OptimizeStatement.php48
-rw-r--r--libraries/sql-parser/src/Statements/RenameStatement.php57
-rw-r--r--libraries/sql-parser/src/Statements/RepairStatement.php43
-rw-r--r--libraries/sql-parser/src/Statements/ReplaceStatement.php84
-rw-r--r--libraries/sql-parser/src/Statements/RestoreStatement.php36
-rw-r--r--libraries/sql-parser/src/Statements/SelectStatement.php190
-rw-r--r--libraries/sql-parser/src/Statements/SetStatement.php43
-rw-r--r--libraries/sql-parser/src/Statements/ShowStatement.php71
-rw-r--r--libraries/sql-parser/src/Statements/TransactionStatement.php120
-rw-r--r--libraries/sql-parser/src/Statements/TruncateStatement.php41
-rw-r--r--libraries/sql-parser/src/Statements/UpdateStatement.php105
-rw-r--r--libraries/sql-parser/src/Token.php292
-rw-r--r--libraries/sql-parser/src/TokensList.php208
-rw-r--r--libraries/sql-parser/src/UtfString.php218
-rw-r--r--libraries/sql-parser/src/Utils/BufferedQuery.php399
-rw-r--r--libraries/sql-parser/src/Utils/Error.php94
-rw-r--r--libraries/sql-parser/src/Utils/Formatter.php536
-rw-r--r--libraries/sql-parser/src/Utils/Misc.php114
-rw-r--r--libraries/sql-parser/src/Utils/Query.php788
-rw-r--r--libraries/sql-parser/src/Utils/Routine.php136
-rw-r--r--libraries/sql-parser/src/Utils/Table.php136
-rw-r--r--libraries/sql.lib.php760
-rw-r--r--libraries/sql_query_form.lib.php212
-rw-r--r--libraries/sqlparser.data.php999
-rw-r--r--libraries/sqlparser.lib.php2997
-rw-r--r--libraries/structure.lib.php3297
-rw-r--r--libraries/sysinfo.lib.php3
-rw-r--r--libraries/tbl_chart.lib.php384
-rw-r--r--libraries/tbl_columns_definition_form.inc.php383
-rw-r--r--libraries/tbl_columns_definition_form.lib.php1458
-rw-r--r--libraries/tbl_common.inc.php11
-rw-r--r--libraries/tbl_gis_visualization.lib.php281
-rw-r--r--libraries/tbl_indexes.lib.php480
-rw-r--r--libraries/tbl_info.inc.php16
-rw-r--r--libraries/tbl_printview.lib.php602
-rw-r--r--libraries/tbl_relation.lib.php1224
-rw-r--r--libraries/tbl_views.lib.php161
-rw-r--r--libraries/tcpdf/README.TXT8
-rw-r--r--libraries/tcpdf/include/tcpdf_images.php8
-rw-r--r--libraries/tcpdf/include/tcpdf_static.php18
-rw-r--r--libraries/tcpdf/tcpdf.php32
-rw-r--r--libraries/tracking.lib.php316
-rw-r--r--libraries/transformations.lib.php26
-rw-r--r--libraries/url_generating.lib.php1
-rw-r--r--libraries/user_preferences.inc.php25
-rw-r--r--libraries/user_preferences.lib.php41
-rw-r--r--libraries/util.lib.php38
-rw-r--r--libraries/vendor_config.php9
-rw-r--r--libraries/zip.lib.php5
-rw-r--r--libraries/zip_extension.lib.php3
-rw-r--r--license.php9
-rw-r--r--lint.php37
-rw-r--r--locale/az/LC_MESSAGES/phpmyadmin.mobin144502 -> 139815 bytes
-rw-r--r--locale/bg/LC_MESSAGES/phpmyadmin.mobin211807 -> 206186 bytes
-rw-r--r--locale/bn/LC_MESSAGES/phpmyadmin.mobin387925 -> 374337 bytes
-rw-r--r--locale/ca/LC_MESSAGES/phpmyadmin.mobin347236 -> 353131 bytes
-rw-r--r--locale/cs/LC_MESSAGES/phpmyadmin.mobin334401 -> 338949 bytes
-rw-r--r--locale/da/LC_MESSAGES/phpmyadmin.mobin336589 -> 327472 bytes
-rw-r--r--locale/de/LC_MESSAGES/phpmyadmin.mobin351671 -> 370348 bytes
-rw-r--r--locale/el/LC_MESSAGES/phpmyadmin.mobin471451 -> 496642 bytes
-rw-r--r--locale/en_GB/LC_MESSAGES/phpmyadmin.mobin281407 -> 272061 bytes
-rw-r--r--locale/es/LC_MESSAGES/phpmyadmin.mobin355336 -> 369573 bytes
-rw-r--r--locale/et/LC_MESSAGES/phpmyadmin.mobin331084 -> 348275 bytes
-rw-r--r--locale/fi/LC_MESSAGES/phpmyadmin.mobin184895 -> 177741 bytes
-rw-r--r--locale/fr/LC_MESSAGES/phpmyadmin.mobin355852 -> 375016 bytes
-rw-r--r--locale/gl/LC_MESSAGES/phpmyadmin.mobin292342 -> 280568 bytes
-rw-r--r--locale/hi/LC_MESSAGES/phpmyadmin.mobin137635 -> 0 bytes
-rw-r--r--locale/hu/LC_MESSAGES/phpmyadmin.mobin358033 -> 368845 bytes
-rw-r--r--locale/hy/LC_MESSAGES/phpmyadmin.mobin209702 -> 199495 bytes
-rw-r--r--locale/ia/LC_MESSAGES/phpmyadmin.mobin208893 -> 221898 bytes
-rw-r--r--locale/id/LC_MESSAGES/phpmyadmin.mobin213668 -> 207286 bytes
-rw-r--r--locale/it/LC_MESSAGES/phpmyadmin.mobin351103 -> 369471 bytes
-rw-r--r--locale/ja/LC_MESSAGES/phpmyadmin.mobin269228 -> 260453 bytes
-rw-r--r--locale/ko/LC_MESSAGES/phpmyadmin.mobin259727 -> 258701 bytes
-rw-r--r--locale/lt/LC_MESSAGES/phpmyadmin.mobin120266 -> 113602 bytes
-rw-r--r--locale/nb/LC_MESSAGES/phpmyadmin.mobin184925 -> 179558 bytes
-rw-r--r--locale/nl/LC_MESSAGES/phpmyadmin.mobin345748 -> 363980 bytes
-rw-r--r--locale/pl/LC_MESSAGES/phpmyadmin.mobin279772 -> 271052 bytes
-rw-r--r--locale/pt/LC_MESSAGES/phpmyadmin.mobin179643 -> 172081 bytes
-rw-r--r--locale/pt_BR/LC_MESSAGES/phpmyadmin.mobin348785 -> 340548 bytes
-rw-r--r--locale/ro/LC_MESSAGES/phpmyadmin.mobin167736 -> 161377 bytes
-rw-r--r--locale/ru/LC_MESSAGES/phpmyadmin.mobin449312 -> 464331 bytes
-rw-r--r--locale/si/LC_MESSAGES/phpmyadmin.mobin264229 -> 258386 bytes
-rw-r--r--locale/sk/LC_MESSAGES/phpmyadmin.mobin258747 -> 256316 bytes
-rw-r--r--locale/sl/LC_MESSAGES/phpmyadmin.mobin338671 -> 356566 bytes
-rw-r--r--locale/sq/LC_MESSAGES/phpmyadmin.mobin354140 -> 372354 bytes
-rw-r--r--locale/sr@latin/LC_MESSAGES/phpmyadmin.mobin132742 -> 127419 bytes
-rw-r--r--locale/sv/LC_MESSAGES/phpmyadmin.mobin289924 -> 280128 bytes
-rw-r--r--locale/tr/LC_MESSAGES/phpmyadmin.mobin349622 -> 368189 bytes
-rw-r--r--locale/uk/LC_MESSAGES/phpmyadmin.mobin375965 -> 363366 bytes
-rw-r--r--locale/zh_CN/LC_MESSAGES/phpmyadmin.mobin246088 -> 243043 bytes
-rw-r--r--locale/zh_TW/LC_MESSAGES/phpmyadmin.mobin318074 -> 330724 bytes
-rw-r--r--navigation.php8
-rw-r--r--normalization.php1
-rw-r--r--phpinfo.php1
-rw-r--r--phpmyadmin.css.php9
-rw-r--r--prefs_forms.php20
-rw-r--r--prefs_manage.php21
-rw-r--r--schema_export.php15
-rw-r--r--server_binlog.php2
-rw-r--r--server_collations.php2
-rw-r--r--server_databases.php2
-rw-r--r--server_engines.php2
-rw-r--r--server_export.php5
-rw-r--r--server_import.php14
-rw-r--r--server_modules.php31
-rw-r--r--server_plugins.php30
-rw-r--r--server_privileges.php18
-rw-r--r--server_replication.php1
-rw-r--r--server_sql.php5
-rw-r--r--server_status.php18
-rw-r--r--server_status_advisor.php16
-rw-r--r--server_status_monitor.php2
-rw-r--r--server_status_processes.php4
-rw-r--r--server_status_queries.php16
-rw-r--r--server_status_variables.php20
-rw-r--r--server_user_groups.php1
-rw-r--r--server_variables.php50
-rw-r--r--show_config_errors.php1
-rw-r--r--sql.php62
-rw-r--r--sql/create_tables.sql36
-rw-r--r--sql/create_tables_drizzle.sql32
-rw-r--r--tbl_addfield.php3
-rw-r--r--tbl_change.php15
-rw-r--r--tbl_chart.php153
-rw-r--r--tbl_create.php2
-rw-r--r--tbl_export.php192
-rw-r--r--tbl_find_replace.php70
-rw-r--r--tbl_get_field.php5
-rw-r--r--tbl_gis_visualization.php130
-rw-r--r--tbl_import.php16
-rw-r--r--tbl_indexes.php79
-rw-r--r--tbl_operations.php35
-rw-r--r--tbl_printview.php74
-rw-r--r--tbl_recent_favorite.php1
-rw-r--r--tbl_relation.php170
-rw-r--r--tbl_replace.php13
-rw-r--r--tbl_row_action.php32
-rw-r--r--tbl_select.php91
-rw-r--r--tbl_sql.php5
-rw-r--r--tbl_structure.php230
-rw-r--r--tbl_tracking.php5
-rw-r--r--tbl_triggers.php1
-rw-r--r--tbl_zoom_select.php176
-rw-r--r--templates/columns_definitions/column_adjust_privileges.phtml18
-rw-r--r--templates/columns_definitions/column_attribute.phtml28
-rw-r--r--templates/columns_definitions/column_attributes.phtml232
-rw-r--r--templates/columns_definitions/column_auto_increment.phtml8
-rw-r--r--templates/columns_definitions/column_comment.phtml10
-rw-r--r--templates/columns_definitions/column_default.phtml51
-rw-r--r--templates/columns_definitions/column_definitions_form.phtml169
-rw-r--r--templates/columns_definitions/column_extra.phtml7
-rw-r--r--templates/columns_definitions/column_indexes.phtml32
-rw-r--r--templates/columns_definitions/column_length.phtml11
-rw-r--r--templates/columns_definitions/column_name.phtml47
-rw-r--r--templates/columns_definitions/column_null.phtml8
-rw-r--r--templates/columns_definitions/column_type.phtml7
-rw-r--r--templates/columns_definitions/column_virtuality.phtml48
-rw-r--r--templates/columns_definitions/mime_type.phtml17
-rw-r--r--templates/columns_definitions/move_column.phtml15
-rw-r--r--templates/columns_definitions/table_fields_definitions.phtml133
-rw-r--r--templates/columns_definitions/transformation.phtml27
-rw-r--r--templates/columns_definitions/transformation_option.phtml12
-rw-r--r--templates/components/error_message.phtml4
-rw-r--r--templates/database/create_table.phtml23
-rw-r--r--templates/database/designer/aggregate_query_panel.phtml84
-rw-r--r--templates/database/designer/canvas.phtml3
-rw-r--r--templates/database/designer/database_tables.phtml140
-rw-r--r--templates/database/designer/delete_relation_panel.phtml47
-rw-r--r--templates/database/designer/edit_delete_pages.phtml11
-rw-r--r--templates/database/designer/having_query_panel.phtml138
-rw-r--r--templates/database/designer/js_fields.phtml10
-rw-r--r--templates/database/designer/new_relation_panel.phtml108
-rw-r--r--templates/database/designer/options_panel.phtml273
-rw-r--r--templates/database/designer/page_save_as.phtml33
-rw-r--r--templates/database/designer/page_selector.phtml10
-rw-r--r--templates/database/designer/query_details.phtml19
-rw-r--r--templates/database/designer/rename_to_panel.phtml66
-rw-r--r--templates/database/designer/schema_export.phtml11
-rw-r--r--templates/database/designer/side_menu.phtml189
-rw-r--r--templates/database/designer/table_list.phtml69
-rw-r--r--templates/database/designer/where_query_panel.phtml103
-rw-r--r--templates/database/structure/body_for_table_summary.phtml93
-rw-r--r--templates/database/structure/browse_table.phtml3
-rw-r--r--templates/database/structure/browse_table_label.phtml3
-rw-r--r--templates/database/structure/check_all_tables.phtml43
-rw-r--r--templates/database/structure/empty_table.phtml3
-rw-r--r--templates/database/structure/favorite_anchor.phtml15
-rw-r--r--templates/database/structure/print_view_data_dictionary_link.phtml7
-rw-r--r--templates/database/structure/search_table.phtml3
-rw-r--r--templates/database/structure/show_create.phtml37
-rw-r--r--templates/database/structure/show_create_row.phtml22
-rw-r--r--templates/database/structure/sortable_header.phtml66
-rw-r--r--templates/database/structure/structure_table_row.phtml187
-rw-r--r--templates/database/structure/table_header.phtml127
-rw-r--r--templates/database/structure/tracking_icon.phtml11
-rw-r--r--templates/error/report_form.phtml35
-rw-r--r--templates/header_location.phtml32
-rw-r--r--templates/javascript/display.phtml7
-rw-r--r--templates/list/item.phtml49
-rw-r--r--templates/list/unordered.phtml29
-rw-r--r--templates/navigation/logo.phtml44
-rw-r--r--templates/prefs_autoload.phtml17
-rw-r--r--templates/preview_sql.phtml11
-rw-r--r--templates/secondary_tabs.phtml6
-rw-r--r--templates/startAndNumberOfRowsPanel.phtml20
-rw-r--r--templates/table/chart/tbl_chart.phtml158
-rw-r--r--templates/table/gis_visualization/gis_visualization.phtml84
-rw-r--r--templates/table/index_form.phtml240
-rw-r--r--templates/table/relation/common_form.phtml111
-rw-r--r--templates/table/relation/dropdown_generate.phtml12
-rw-r--r--templates/table/relation/foreign_key_row.phtml214
-rw-r--r--templates/table/relation/internal_relational_row.phtml77
-rw-r--r--templates/table/relation/relational_dropdown.phtml18
-rw-r--r--templates/table/search/column_comparison_operators.phtml7
-rw-r--r--templates/table/search/fields_table.phtml24
-rw-r--r--templates/table/search/form_tag.phtml22
-rw-r--r--templates/table/search/geom_func.phtml39
-rw-r--r--templates/table/search/input_box.phtml135
-rw-r--r--templates/table/search/options.phtml78
-rw-r--r--templates/table/search/options_zoom.phtml48
-rw-r--r--templates/table/search/replace_preview.phtml42
-rw-r--r--templates/table/search/rows_normal.phtml52
-rw-r--r--templates/table/search/rows_zoom.phtml88
-rw-r--r--templates/table/search/search_and_replace.phtml26
-rw-r--r--templates/table/search/selection_form.phtml78
-rw-r--r--templates/table/search/table_header.phtml12
-rw-r--r--templates/table/search/zoom_result_form.phtml100
-rw-r--r--templates/table/secondary_tabs.phtml19
-rw-r--r--templates/table/structure/action_row_in_structure_table.phtml28
-rw-r--r--templates/table/structure/actions_in_table_structure.phtml143
-rw-r--r--templates/table/structure/add_column.phtml26
-rw-r--r--templates/table/structure/check_all_table_column.phtml57
-rw-r--r--templates/table/structure/display_partitions.phtml125
-rw-r--r--templates/table/structure/display_structure.phtml222
-rw-r--r--templates/table/structure/display_table_stats.phtml77
-rw-r--r--templates/table/structure/move_columns_dialog.phtml8
-rw-r--r--templates/table/structure/optional_action_links.phtml34
-rw-r--r--templates/table/structure/row_stats_table.phtml99
-rw-r--r--templates/table/structure/table_structure_header.phtml26
-rw-r--r--templates/table/structure/table_structure_row.phtml50
-rw-r--r--templates/test/echo.phtml2
-rw-r--r--templates/test/static.phtml1
-rw-r--r--templates/test/trim.phtml1
-rw-r--r--themes.php2
-rw-r--r--themes/original/css/common.css.php283
-rw-r--r--themes/original/css/navigation.css.php6
-rw-r--r--themes/original/css/printview.css168
-rw-r--r--themes/original/img/b_selboard.pngbin175 -> 0 bytes
-rw-r--r--themes/original/img/s_okay.pngbin0 -> 772 bytes
-rw-r--r--themes/original/info.inc.php1
-rw-r--r--themes/original/layout.inc.php26
-rw-r--r--themes/original/sprites.lib.php1
-rw-r--r--themes/pmahomme/css/codemirror.css.php311
-rw-r--r--themes/pmahomme/css/common.css.php199
-rw-r--r--themes/pmahomme/css/jqplot.css.php12
-rw-r--r--themes/pmahomme/css/navigation.css.php12
-rw-r--r--themes/pmahomme/css/pmd.css.php118
-rw-r--r--themes/pmahomme/css/printview.css168
-rw-r--r--themes/pmahomme/css/rte.css.php6
-rw-r--r--themes/pmahomme/img/b_selboard.pngbin676 -> 0 bytes
-rw-r--r--themes/pmahomme/info.inc.php1
-rw-r--r--themes/pmahomme/layout.inc.php27
-rw-r--r--themes/pmahomme/sprites.lib.php1
-rw-r--r--themes/sprites.css.php2
-rw-r--r--transformation_overview.php1
-rw-r--r--transformation_wrapper.php1
-rw-r--r--url.php11
-rw-r--r--user_password.php71
-rw-r--r--version_check.php2
-rw-r--r--view_create.php109
-rw-r--r--view_operations.php5
-rw-r--r--webapp.php1
766 files changed, 51033 insertions, 30381 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4e97988a2c..e13da81278 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,6 +4,15 @@ As an open source project, phpMyAdmin welcomes contributions of many forms.
## Bug reporting
+We appreciate your effort to improve phpMyAdmin by submitting a bug report. Before doing so, please check the following things:
+
+1. Check whether the bug you face **hasn't been already reported**. Duplicate reports takes us time, that we could be used to fix other bugs or make improvements.
+2. Specify the phpMyAdmin, server, PHP, MySQL and browser information that may be helpful to fix the problem, especially exact **version numbers**.
+3. If you got some error, please **describe what happened** and add error message. Reports like "I get error when I clicked on some link." are useless.
+4. Provide easy steps to reproduce and if possible include your table structure (``SHOW CREATE TABLE `tbl_name```); if your problem implies specific data, attach a small export file for sample rows.
+5. **Security problems** should not be reported here. See [our security page](https://www.phpmyadmin.net/security/).
+Thanks for your help!
+
Please report [bugs on GitHub][1].
[1]: https://github.com/phpmyadmin/phpmyadmin/issues/new
diff --git a/ChangeLog b/ChangeLog
index dc4a3f07de..40b8ba6fd0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,110 @@
phpMyAdmin - ChangeLog
======================
-4.4.15.0 (2015-09-20)
+4.5.0.1 (2015-09-24)
+- issue #11492 AUTO_INCREMENT statements are partly missing from exports
+
+4.5.0.0 (2015-09-23)
++ rfe Pagination for GIS visualization
++ issue #6207 Usability improvements for console
++ issue #6310 Access to Add columns text-box and Go button when creating table
++ issue #6007 Add lock tables, disable keys options
++ issue #6306 Additional page locking
++ issue #6314 Support MySQL 5.7 syntax for password change
++ issue #6319 Display/edit index name
++ issue #6318 Toggle autocomplete of table and column names
++ issue #5633 Manage multiple variable in bookmarked query
++ issue #5642 Show edit/delete also when there is calculated column
++ issue #6313 Show databases as list instead of as dropdown when no database is selected
++ rfe Optional dark theme for the console
++ issue #5053 PDF schema sort options
++ issue #5543 Structure in PDF export
++ issue #6327 Have ZeroConf create phpmyadmin DB if possible
++ issue #5462 Warning before silent data conversion/truncation
++ issue #6338 Support a default page in designer
++ issue #6339 Allow copying mutiple rows
++ issue #6334 No SQL query for loading data
++ issue #6341 New data validation feature and datetime type
++ issue #6324 Importing and exporting pMA meta-data
++ issue #6330 Add grouping to stored procedures in the navigation tree
++ issue #6275 Support IPv6 browser transformation
++ rfe Option groups for 'With selected' dropdown in database structure page
++ issue #6347 Support CHECKSUM TABLE operation
++ issue #6088 Support for Paramaters with raw SQL
++ issue #5844 Show original size of truncated columns
++ issue #6114 Explain analyzer
++ issue #6186 Add "Drop partition" option to partition tools
++ issue #6354 Procedures window shift-click should select multiple rows
++ issue #6355 Designer: "Sticky" menu option
++ issue #6357 Directly show table comments in structure view
++ issue #6259 Page-related settings
++ issue #5356 Alter privileges when renaming or copying a database
+- issue #11256 Slowness due to large number of routines
+- issue #11258 GROUP_CONCAT shown as GROUPBY_CONCAT in CodeMirror autocomplete
++ issue #5946 Work with --skip-grant-tables
+- issue #11266 "Sort by key" drop-down value is lost
++ issue #6287 Browse: improve display of right-aligned data
+- issue #11265 Textarea rows settings ignored Features > Text fields
++ issue #6358 MIME types should be lower case
+- issue #11226 Drop table doesn't remove the table name from navigation bar
++ issue #6360 MySQL and MariaDB functions INET6_ATON and INET6_NTOA
+- bug Link to get real row counts of all the views in a db, at once
+- issue #11275 Drizzle version numbers
++ issue #5400 Rewrite print view using CSS; fixes print view failures on multi-query statements
++ issue #6362 Support spatial indexes in table create form
++ issue #6068 Use CTRL or ALT plus arrow keys for navigation in grid editor
++ rfe Remove support for Shift + Click on function name to apply to all rows in insert/edit page
++ issue #6326 Don't group tables in tree if the result has only one group
+- issue #11287 When hide table structure actions is false, action should be in a row
++ issue #5425 Batch changing the collation of each column in a table
+- issue #10918 QBE generates wrong query
++ issue #6292 Use plain English descriptors instead of script names for icon link destinations
++ issue #6239 Disable foreign key checks for some operations
+- issue #11296 "With selected" links doesn't work in table browse
+- issue #11166 Query builder: missing joint for the intermediary table
++ issue #6251 Integrate SQL debugging into console
+- issue #11061 Improve/restore non-unique index row editing
+- issue #11301 MySQL errors are not shown when DebugSQL is enabled
++ issue #5037 One file per table and one file per database export option
++ issue #5759 Designer settings should be part of saved state
++ issue #6257 Option to remove functions, procedures, etc., from navigation tree
++ issue #5388 Column privileges and update
++ issue #6231 Cant use external config file
++ issue #6252 CSV import: Allow "Columns escaped with" to be optional
++ issue #6262 Being able to use multiple servers at the same time when using cookie auth
++ issue #6301 select structure or data for each table when exporting
+- issue #11261 Autocomplete completes the original table name when joining multiple aliased tables
++ rfe Remove configuration storage data related to a user upon deleting the user
++ issue #6298 Improved processlist for mariadb
++ issue #6300 Warn about "Any user" potential problem
++ issue #6368 Hide/disable edit links for read-only variables
++ issue #6365 Human readable/writable URLs (html5 api)
++ rfe Support virtual columns in MySQL 5.7.5+
++ issue #6215 Support for virtual/persistent columns in MariaDB
+- issue #11314 Undefined <feature>work upon upgrade to new version
+- issue #1817 Creating configuration storage tables fail in MySQL 5.7
+- issue #6118 Parser does not handle nested selects
+- issue #5437 Support SELECT ... FROM DUAL
+- issue #4962 Support UNION
+- issue #11322 Missing null checkbox when grid editing a null cell
++ Upgrade TCPDF to version 6.2.9
++ issue #6102 Add SHA256 security password support
+- issue #10250 Displayed git revision info is not set
++ Improved schema SVG export
+- issue #10726 Do not try to set port 80 for https requests
++ issue #11394 Export/import Designer view
++ Partition support in table Structure
++ issue #11414 Unclear export options / organization / hierarchy
+ Set minimum required PHP version to 5.5 (older versions are EOL)
+- issue #11407 ALTER TABLE failing on import when table exists
+- issue Do not export `sys` database when exporting server
+- issue #11436 CREATE DATABASE should be enabled by default on server exports
+- issue #11442 MySQL 5.7 and SHOW VARIABLES
+- issue #11445 MySQL 5.7 and Status page for an unprivileged user
+- issue #11448 Clarify doc about the MemoryLimit directive
+- issue #11489 Cannot copy a database under certain conditions
+
+4.4.15.0 (not yet released)
- issue #11411 Undefined "replace" function on numeric scalar
- issue #11421 Stored-proc / routine - broken parameter parsing
- issue Missing name for configuration read_as_multibytes
@@ -12,8 +115,6 @@ phpMyAdmin - ChangeLog
- issue #11458 Invalid UTF-8 sequence in argument
- issue #11457 Request URI too large
- issue Invalid argument supplied for foreach()
-- issue #11461 Foreign key constraints for InnoDB tables with upper-case letters disabled
-- issue #11487 Warning when entering Query page
4.4.14.1 (2015-09-08)
- issue [security] reCaptcha bypass
@@ -149,8 +250,8 @@ phpMyAdmin - ChangeLog
4.4.3.0 (2015-04-20)
- bug #4851 PHP errors in login dialogue
-- bug #4845 White screen (Cloudflare)
- bug #4207 json_encode error due to strftime returning non utf8 chars in Windows 8.1 Chinese version
+- bug #4845 White screen (Cloudflare)
- bug #4794 Server error viewing table content
- bug Fix issues related to number of decimal places in time
- bug #4853 Relation view between 1600 and 1780 px
@@ -289,10 +390,7 @@ explanation
4.3.11.1 (2015-03-04)
- bug [security] Risk of BREACH attack, see PMASA-2015-1
-4.3.11.1 (not yet released)
-- bug [security] Risk of BREACH attack, see PMASA-2015-1
-
-4.3.11.0 (not yet released)
+4.3.11.0 (2015-03-02)
- bug #4774 SQL links are completely wrong
- bug #4768 MariaDB: version mismatch
- bug #4777 Some images are missing in Designer for original theme
diff --git a/LICENSE b/LICENSE
index 3912109b5c..d159169d10 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,12 +1,12 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
+the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
-
- GNU GENERAL PUBLIC LICENSE
+
+ GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
-
+
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
-
+
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
-
+
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
+library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
diff --git a/README b/README
index f939e7fbf3..cbbc7b842c 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
phpMyAdmin - Readme
===================
-Version 4.4.15
+Version 4.5.0.1
A set of PHP-scripts to manage MySQL over the web.
diff --git a/browse_foreigners.php b/browse_foreigners.php
index 444d01f5d0..793c00b7e5 100644
--- a/browse_foreigners.php
+++ b/browse_foreigners.php
@@ -58,4 +58,3 @@ $html = PMA_getHtmlForRelationalFieldSelection(
);
$response->addHtml($html);
-?>
diff --git a/changelog.php b/changelog.php
index c5a9d68b43..6dbd495059 100644
--- a/changelog.php
+++ b/changelog.php
@@ -33,7 +33,10 @@ if (is_readable($filename)) {
}
} else {
printf(
- __('The %s file is not available on this system, please visit www.phpmyadmin.net for more information.'),
+ __(
+ 'The %s file is not available on this system, please visit '
+ . 'www.phpmyadmin.net for more information.'
+ ),
$filename
);
exit;
diff --git a/chk_rel.php b/chk_rel.php
index 3a55d73399..e62288401e 100644
--- a/chk_rel.php
+++ b/chk_rel.php
@@ -8,8 +8,15 @@
require_once 'libraries/common.inc.php';
-// If request for creating all PMA tables.
+// If request for creating the pmadb
if (isset($_REQUEST['create_pmadb'])) {
+ if (PMA_createPMADatabase()) {
+ PMA_fixPMATables('phpmyadmin');
+ }
+}
+
+// If request for creating all PMA tables.
+if (isset($_REQUEST['fixall_pmadb'])) {
PMA_fixPMATables($GLOBALS['db']);
}
@@ -23,5 +30,3 @@ $response = PMA_Response::getInstance();
$response->addHTML(
PMA_getRelationsParamDiagnostic($cfgRelation)
);
-
-?>
diff --git a/config.sample.inc.php b/config.sample.inc.php
index 035ebb80db..5c73c2e1b9 100644
--- a/config.sample.inc.php
+++ b/config.sample.inc.php
@@ -10,18 +10,18 @@
* @package PhpMyAdmin
*/
-/*
+/**
* This is needed for cookie based authentication to encrypt password in
* cookie
*/
$cfg['blowfish_secret'] = ''; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
-/*
+/**
* Servers configuration
*/
$i = 0;
-/*
+/**
* First server
*/
$i++;
@@ -33,7 +33,7 @@ $cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
-/*
+/**
* phpMyAdmin configuration storage settings.
*/
@@ -62,14 +62,16 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false;
// $cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
// $cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
// $cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
+// $cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
+// $cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';
/* Contrib / Swekey authentication */
// $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
-/*
+/**
* End of servers configuration
*/
-/*
+/**
* Directories for saving/loading files from server
*/
$cfg['UploadDir'] = '';
@@ -78,8 +80,9 @@ $cfg['SaveDir'] = '';
/**
* Whether to display icons or text or both icons and text in table row
* action segment. Value can be either of 'icons', 'text' or 'both'.
+ * default = 'both'
*/
-//$cfg['RowActionType'] = 'both';
+//$cfg['RowActionType'] = 'icons';
/**
* Defines whether a user should be displayed a "show all (records)"
@@ -91,20 +94,21 @@ $cfg['SaveDir'] = '';
/**
* Number of rows displayed when browsing a result set. If the result
* set contains more rows, "Previous" and "Next".
- * default = 30
+ * Possible values: 25, 50, 100, 250, 500
+ * default = 25
*/
//$cfg['MaxRows'] = 50;
/**
- * disallow editing of binary fields
+ * Disallow editing of binary fields
* valid values are:
* false allow editing
* 'blob' allow editing except for BLOB fields
* 'noblob' disallow editing except for BLOB fields
* 'all' disallow editing
- * default = blob
+ * default = 'blob'
*/
-//$cfg['ProtectBinary'] = 'false';
+//$cfg['ProtectBinary'] = false;
/**
* Default language to use, if not browser-defined or user-defined
@@ -133,20 +137,21 @@ $cfg['SaveDir'] = '';
/**
* When using DB-based query history, how many entries should be kept?
- *
* default = 25
*/
//$cfg['QueryHistoryMax'] = 100;
/**
- * Should error reporting be enabled for JavaScript errors
+ * Whether or not to query the user before sending the error report to
+ * the phpMyAdmin team when a JavaScript error occurs
*
+ * Available options
+ * ('ask' | 'always' | 'never')
* default = 'ask'
*/
-//$cfg['SendErrorReports'] = 'ask';
+//$cfg['SendErrorReports'] = 'always';
-/*
+/**
* You can find more configuration options in the documentation
* in the doc/ folder or at <http://docs.phpmyadmin.net/>.
*/
-?>
diff --git a/db_central_columns.php b/db_central_columns.php
index 997cffca18..2e9aac73bb 100644
--- a/db_central_columns.php
+++ b/db_central_columns.php
@@ -10,7 +10,6 @@
* Gets some core libraries
*/
require_once 'libraries/common.inc.php';
-require_once 'libraries/tbl_columns_definition_form.lib.php';
require_once 'libraries/central_columns.lib.php';
if (isset($_POST['edit_save']) || isset($_POST['add_new_column'])) {
@@ -22,7 +21,7 @@ if (isset($_POST['edit_save']) || isset($_POST['add_new_column'])) {
if ($col_default == 'NONE' && $_POST['col_default_sel'] != 'USER_DEFINED') {
$col_default = "";
}
- $col_extra = $_POST['col_extra'];
+ $col_extra = isset($_POST['col_extra']) ? $_POST['col_extra'] : '';
$col_isNull = isset($_POST['col_isNull'])?1:0;
$col_length = $_POST['col_length'];
$col_attribute = $_POST['col_attribute'];
@@ -30,13 +29,13 @@ if (isset($_POST['edit_save']) || isset($_POST['add_new_column'])) {
$collation = $_POST['collation'];
if (isset($orig_col_name) && $orig_col_name) {
echo PMA_updateOneColumn(
- $db, $orig_col_name, $col_name, $col_type,$col_attribute,
+ $db, $orig_col_name, $col_name, $col_type, $col_attribute,
$col_length, $col_isNull, $collation, $col_extra, $col_default
);
exit;
} else {
$tmp_msg = PMA_updateOneColumn(
- $db, "", $col_name, $col_type,$col_attribute,
+ $db, "", $col_name, $col_type, $col_attribute,
$col_length, $col_isNull, $collation, $col_extra, $col_default
);
}
@@ -66,10 +65,27 @@ $cfgCentralColumns = PMA_centralColumnsGetParams();
$pmadb = $cfgCentralColumns['db'];
$pmatable = $cfgCentralColumns['table'];
$max_rows = $GLOBALS['cfg']['MaxRows'];
+
+if (isset($_REQUEST['edit_central_columns_page'])) {
+ $selected_fld = $_REQUEST['selected_fld'];
+ $selected_db = $_REQUEST['db'];
+ $edit_central_column_page = PMA_getHTMLforEditingPage(
+ $selected_fld, $selected_db
+ );
+ $response->addHTML($edit_central_column_page);
+ exit;
+}
+if (isset($_POST['multi_edit_central_column_save'])) {
+ $message = PMA_updateMultipleColumn();
+ if (!is_bool($message)) {
+ $response->isSuccess(false);
+ $response->addJSON('message', $message);
+ }
+}
if (isset($_POST['delete_save'])) {
$col_name = array();
- $col_name[] = $_REQUEST['col_name'];
- $tmp_msg = PMA_deleteColumnsFromList($col_name, false);
+ parse_str($_POST['col_name'], $col_name);
+ $tmp_msg = PMA_deleteColumnsFromList($col_name['selected_fld'], false);
}
if (isset($_REQUEST['total_rows']) && $_REQUEST['total_rows']) {
$total_rows = $_REQUEST['total_rows'];
@@ -106,6 +122,7 @@ $deleteRowForm = '<form method="post" id="del_form" action="db_central_columns.p
. '<input type="hidden" name="delete_save" value="delete"></form>';
$response->addHTML($deleteRowForm);
$table_struct = '<div id="tableslistcontainer">'
+ . '<form name="tableslistcontainer">'
. '<table id="table_columns" class="tablesorter" '
. 'style="min-width:100%" class="data">';
$response->addHTML($table_struct);
@@ -115,7 +132,7 @@ $tableheader = PMA_getCentralColumnsTableHeader(
$response->addHTML($tableheader);
$result = PMA_getColumnsList($db, $pos, $max_rows);
$odd_row = true;
-$row_num=0;
+$row_num = 0;
foreach ($result as $row) {
$tableHtmlRow = PMA_getHTMLforCentralColumnsTableRow(
$row, $odd_row, $row_num, $db
@@ -124,11 +141,13 @@ foreach ($result as $row) {
$odd_row = !$odd_row;
$row_num++;
}
-$response->addHTML('</table></div>');
+$response->addHTML('</table>');
+$tablefooter = PMA_getCentralColumnsTableFooter($pmaThemeImage, $text_dir);
+$response->addHTML($tablefooter);
+$response->addHTML('</form></div>');
$message = PMA_Message::success(
sprintf(__('Showing rows %1$s - %2$s.'), ($pos + 1), ($pos + count($result)))
);
if (isset($tmp_msg) && $tmp_msg !== true) {
$message = $tmp_msg;
}
-?>
diff --git a/db_create.php b/db_create.php
index 9bdcb0e303..86cdf4bafd 100644
--- a/db_create.php
+++ b/db_create.php
@@ -130,7 +130,10 @@ if (! $result) {
)
);
$response->addJSON(
- 'url_query', $GLOBALS['cfg']['DefaultTabDatabase']
+ 'url_query',
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ )
. $url_query . '&amp;db='
. urlencode($current['SCHEMA_NAME'])
);
@@ -138,4 +141,3 @@ if (! $result) {
include_once '' . $cfg['DefaultTabDatabase'];
}
}
-?>
diff --git a/db_datadict.php b/db_datadict.php
index 555063e7d3..6367087152 100644
--- a/db_datadict.php
+++ b/db_datadict.php
@@ -13,7 +13,17 @@ require_once 'libraries/common.inc.php';
if (! isset($selected_tbl)) {
include 'libraries/db_common.inc.php';
- include 'libraries/db_info.inc.php';
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
}
$response = PMA_Response::getInstance();
@@ -45,8 +55,8 @@ if ($cfgRelation['commwork']) {
* Displays DB comment
*/
if ($comment) {
- echo '<p>' . __('Database comment:')
- . ' <i>' . htmlspecialchars($comment) . '</i></p>';
+ echo '<p>' . __('Database comment')
+ . '<br /><i>' . htmlspecialchars($comment) . '</i></p>';
} // end if
}
@@ -65,9 +75,10 @@ foreach ($tables as $table) {
echo '<h2>' . htmlspecialchars($table) . '</h2>' . "\n";
/**
- * Gets table informations
+ * Gets table information
*/
- $show_comment = PMA_Table::sGetStatusInfo($db, $table, 'TABLE_COMMENT');
+ $show_comment = $GLOBALS['dbi']->getTable($db, $table)
+ ->getStatusInfo('TABLE_COMMENT');
/**
* Gets table keys and retains them
@@ -123,14 +134,7 @@ foreach ($tables as $table) {
// reformat mysql query output
// set or enum types: slashes single quotes inside options
- if ('set' == $extracted_columnspec['type']
- || 'enum' == $extracted_columnspec['type']
- ) {
- $type_nowrap = '';
- } else {
- $type_nowrap = ' class="nowrap"';
- }
$type = htmlspecialchars($extracted_columnspec['print_type']);
$attribute = $extracted_columnspec['attribute'];
if (! isset($row['Default'])) {
@@ -152,7 +156,12 @@ foreach ($tables as $table) {
echo ' <em>(' . __('Primary') . ')</em>';
}
echo '</td>';
- echo '<td' . $type_nowrap . ' lang="en" dir="ltr">' . $type . '</td>';
+ echo '<td'
+ . PMA_Util::getClassForType(
+ $extracted_columnspec['type']
+ )
+ . ' lang="en" dir="ltr">' . $type . '</td>';
+
echo '<td>';
echo (($row['Null'] == 'NO') ? __('No') : __('Yes'));
echo '</td>';
@@ -195,7 +204,7 @@ foreach ($tables as $table) {
echo '</table>';
// display indexes information
if (count(PMA_Index::getFromTable($table, $db)) > 0) {
- echo PMA_Index::getView($table, $db, true);
+ echo PMA_Index::getHtmlForIndexes($table, $db, true);
}
echo '</div>';
} //ends main while
@@ -204,5 +213,3 @@ foreach ($tables as $table) {
* Displays the footer
*/
echo PMA_Util::getButton();
-
-?>
diff --git a/db_designer.php b/db_designer.php
index 2582048285..8acc99e69c 100644
--- a/db_designer.php
+++ b/db_designer.php
@@ -36,12 +36,8 @@ if (isset($_REQUEST['dialog'])) {
if (isset($_REQUEST['operation'])) {
if ($_REQUEST['operation'] == 'deletePage') {
- $result = PMA_deletePage($_REQUEST['selected_page']);
- if ($result) {
- $response->isSuccess(true);
- } else {
- $response->isSuccess(false);
- }
+ $success = PMA_deletePage($_REQUEST['selected_page']);
+ $response->isSuccess($success);
} elseif ($_REQUEST['operation'] == 'savePage') {
if ($_REQUEST['save_page'] == 'same') {
$page = $_REQUEST['selected_page'];
@@ -49,11 +45,8 @@ if (isset($_REQUEST['operation'])) {
$page = PMA_createNewPage($_REQUEST['selected_value'], $GLOBALS['db']);
$response->addJSON('id', $page);
}
- if (PMA_saveTablePositions($page)) {
- $response->isSuccess(true);
- } else {
- $response->isSuccess(false);
- }
+ $success = PMA_saveTablePositions($page);
+ $response->isSuccess($success);
} elseif ($_REQUEST['operation'] == 'setDisplayField') {
PMA_saveDisplayField(
$_REQUEST['db'], $_REQUEST['table'], $_REQUEST['field']
@@ -80,7 +73,11 @@ if (isset($_REQUEST['operation'])) {
);
$response->isSuccess($success);
$response->addJSON('message', $message);
+ } elseif ($_REQUEST['operation'] == 'save_setting_value') {
+ $success = PMA_saveDesignerSetting($_REQUEST['index'], $_REQUEST['value']);
+ $response->isSuccess($success);
}
+
return;
}
@@ -89,15 +86,18 @@ $tab_column = PMA_getColumnsInfo();
$script_tables = PMA_getScriptTabs();
$tables_pk_or_unique_keys = PMA_getPKOrUniqueKeys();
$tables_all_keys = PMA_getAllKeys();
+$classes_side_menu = PMA_returnClassNamesFromMenuButtons();
$display_page = -1;
$selected_page = null;
-if (! isset($_REQUEST['query'])) {
+if (isset($_REQUEST['query'])) {
+ $display_page = PMA_getDefaultPage($_REQUEST['db']);
+} else {
if (! empty($_REQUEST['page'])) {
$display_page = $_REQUEST['page'];
} else {
- $display_page = PMA_getFirstPage($_REQUEST['db']);
+ $display_page = PMA_getLoadingPage($_REQUEST['db']);
}
}
if ($display_page != -1) {
@@ -127,7 +127,18 @@ $scripts->addFile('pmd/iecanvas.js', true);
$scripts->addFile('pmd/init.js');
require 'libraries/db_common.inc.php';
-require 'libraries/db_info.inc.php';
+
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
// Embed some data into HTML, later it will be read
// by pmd/init.js and converted to JS variables.
@@ -137,11 +148,15 @@ $response->addHTML(
)
);
$response->addHTML(
- PMA_getDesignerPageMenu(isset($_REQUEST['query']), $selected_page)
+ PMA_getDesignerPageMenu(isset($_REQUEST['query']), $selected_page, $classes_side_menu)
);
+
+
$response->addHTML('<div id="canvas_outer">');
-$response->addHTML('<form action="" id="container-form" method="post" name="form1">');
+$response->addHTML(
+ '<form action="" id="container-form" method="post" name="form1">'
+);
$response->addHTML(PMA_getHTMLCanvas());
$response->addHTML(PMA_getHTMLTableList($tab_pos, $display_page));
@@ -169,5 +184,4 @@ if (isset($_REQUEST['query'])) {
$response->addHTML(PMA_getQueryDetails());
}
-$response->addHTML(PMA_getCacheImages());
-?>
+$response->addHTML('<div id="PMA_disable_floating_menubar"></div>');
diff --git a/db_events.php b/db_events.php
index 917778bc35..224f806dea 100644
--- a/db_events.php
+++ b/db_events.php
@@ -22,5 +22,3 @@ require_once 'libraries/rte/rte_events.lib.php';
*/
$_PMA_RTE = 'EVN';
require_once 'libraries/rte/rte_main.inc.php';
-
-?>
diff --git a/db_export.php b/db_export.php
index 5313e0e022..6cf1be8b5e 100644
--- a/db_export.php
+++ b/db_export.php
@@ -10,18 +10,33 @@
* Gets some core libraries
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+require_once 'libraries/export.lib.php';
+
+PMA_PageSettings::showGroup('Export');
$response = PMA_Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('export.js');
-// $sub_part is also used in db_info.inc.php to see if we are coming from
+// $sub_part is used in PMA_Util::getDbInfo() to see if we are coming from
// db_export.php, in which case we don't obey $cfg['MaxTableList']
$sub_part = '_export';
require_once 'libraries/db_common.inc.php';
$url_query .= '&amp;goto=db_export.php';
-require_once 'libraries/db_info.inc.php';
+
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
/**
* Displays the form
@@ -34,21 +49,28 @@ if ($num_tables < 1) {
exit;
} // end if
-$multi_values = '<div>';
-$multi_values .= '<a href="#"';
-$multi_values .= ' onclick="setSelectOptions(\'dump\', \'table_select[]\', true);'
- . ' return false;">';
-$multi_values .= __('Select All');
-$multi_values .= '</a>';
-$multi_values .= ' / ';
-$multi_values .= '<a href="#"';
-$multi_values .= ' onclick="setSelectOptions(\'dump\', \'table_select[]\', false);'
- . ' return false;">';
-$multi_values .= __('Unselect All');
-$multi_values .= '</a><br />';
-
-$multi_values .= '<select name="table_select[]" id="table_select" size="10"'
- . ' multiple="multiple">';
+$multi_values = '<div class="export_table_list_container">';
+if (isset($_GET['structure_or_data_forced'])) {
+ $force_val = htmlspecialchars($_GET['structure_or_data_forced']);
+} else {
+ $force_val = 0;
+}
+$multi_values .= '<input type="hidden" name="structure_or_data_forced" value="'
+ . $force_val . '">';
+$multi_values .= '<table class="export_table_select">'
+ . '<thead><tr><th></th>'
+ . '<th>' . __('Tables') . '</th>'
+ . '<th class="export_structure">' . __('Structure') . '</th>'
+ . '<th class="export_data">' . __('Data') . '</th>'
+ . '</tr><tr>'
+ . '<td></td>'
+ . '<td class="export_table_name all">' . __('Select all') . '</td>'
+ . '<td class="export_structure all">'
+ . '<input type="checkbox" id="table_structure_all" /></td>'
+ . '<td class="export_data all"><input type="checkbox" id="table_data_all" />'
+ . '</td>'
+ . '</tr></thead>'
+ . '<tbody>';
$multi_values .= "\n";
// when called by libraries/mult_submits.inc.php
@@ -58,37 +80,56 @@ if (!empty($_POST['selected_tbl']) && empty($table_select)) {
// Check if the selected tables are defined in $_GET
// (from clicking Back button on export.php)
-if (isset($_GET['table_select'])) {
- $_GET['table_select'] = urldecode($_GET['table_select']);
- $_GET['table_select'] = explode(",", $_GET['table_select']);
+foreach (array('table_select', 'table_structure', 'table_data') as $one_key) {
+ if (isset($_GET[$one_key])) {
+ $_GET[$one_key] = urldecode($_GET[$one_key]);
+ $_GET[$one_key] = explode(",", $_GET[$one_key]);
+ }
}
foreach ($tables as $each_table) {
if (isset($_GET['table_select'])) {
- if (in_array($each_table['Name'], $_GET['table_select'])) {
- $is_selected = ' selected="selected"';
- } else {
- $is_selected = '';
- }
+ $is_checked = PMA_getCheckedClause(
+ $each_table['Name'], $_GET['table_select']
+ );
} elseif (isset($table_select)) {
- if (in_array($each_table['Name'], $table_select)) {
- $is_selected = ' selected="selected"';
- } else {
- $is_selected = '';
- }
+ $is_checked = PMA_getCheckedClause(
+ $each_table['Name'], $table_select
+ );
} else {
- $is_selected = ' selected="selected"';
+ $is_checked = ' checked="checked"';
+ }
+ if (isset($_GET['table_structure'])) {
+ $structure_checked = PMA_getCheckedClause(
+ $each_table['Name'], $_GET['table_structure']
+ );
+ } else {
+ $structure_checked = $is_checked;
+ }
+ if (isset($_GET['table_data'])) {
+ $data_checked = PMA_getCheckedClause(
+ $each_table['Name'], $_GET['table_data']
+ );
+ } else {
+ $data_checked = $is_checked;
}
$table_html = htmlspecialchars($each_table['Name']);
- $multi_values .= ' <option value="' . $table_html . '"'
- . $is_selected . '>'
- . str_replace(' ', '&nbsp;', $table_html) . '</option>' . "\n";
+ $multi_values .= '<tr>';
+ $multi_values .= '<td><input type="checkbox" name="table_select[]"'
+ . ' value="' . $table_html . '"' . $is_checked . ' /></td>';
+ $multi_values .= '<td class="export_table_name">'
+ . str_replace(' ', '&nbsp;', $table_html) . '</td>';
+ $multi_values .= '<td class="export_structure">'
+ . '<input type="checkbox" name="table_structure[]"'
+ . ' value="' . $table_html . '"' . $structure_checked . ' /></td>';
+ $multi_values .= '<td class="export_data">'
+ . '<input type="checkbox" name="table_data[]"'
+ . ' value="' . $table_html . '"' . $data_checked . ' /></td>';
+ $multi_values .= '</tr>';
} // end for
$multi_values .= "\n";
-$multi_values .= '</select></div>';
+$multi_values .= '</tbody></table></div>';
$export_type = 'database';
require_once 'libraries/display_export.inc.php';
-
-?>
diff --git a/db_import.php b/db_import.php
index 668be6773f..2dccfa94a6 100644
--- a/db_import.php
+++ b/db_import.php
@@ -7,6 +7,9 @@
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Import');
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -17,9 +20,23 @@ $scripts->addFile('import.js');
* Gets tables information and displays top links
*/
require 'libraries/db_common.inc.php';
-require 'libraries/db_info.inc.php';
-$import_type = 'database';
-require 'libraries/display_import.inc.php';
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
-?>
+require 'libraries/display_import.lib.php';
+$response = PMA_Response::getInstance();
+$response->addHTML(
+ PMA_getImportDisplay(
+ 'database', $db, $table, $max_upload_size
+ )
+);
diff --git a/db_operations.php b/db_operations.php
index c2e2b4b3df..7f0e2b9df5 100644
--- a/db_operations.php
+++ b/db_operations.php
@@ -17,10 +17,12 @@
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/mysql_charsets.inc.php';
+require_once 'libraries/display_create_table.lib.php';
/**
* functions implementation for this script
*/
+require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/operations.lib.php';
// add a javascript file for jQuery functions to handle Ajax actions
@@ -70,6 +72,7 @@ if (/*overload*/mb_strlen($GLOBALS['db'])
include_once "libraries/plugin_interface.lib.php";
// remove all foreign key constraints, otherwise we can get errors
+ /* @var $export_sql_plugin ExportSql */
$export_sql_plugin = PMA_getPlugin(
"export",
"sql",
@@ -116,6 +119,12 @@ if (/*overload*/mb_strlen($GLOBALS['db'])
PMA_duplicateBookmarks($_error, $GLOBALS['db']);
if (! $_error && $move) {
+ if (isset($_REQUEST['adjust_privileges'])
+ && ! empty($_REQUEST['adjust_privileges'])
+ ) {
+ PMA_AdjustPrivileges_moveDB($GLOBALS['db'], $_REQUEST['newname']);
+ }
+
/**
* cleanup pmadb stuff for this db
*/
@@ -134,6 +143,12 @@ if (/*overload*/mb_strlen($GLOBALS['db'])
$message->addParam($GLOBALS['db']);
$message->addParam($_REQUEST['newname']);
} elseif (! $_error) {
+ if (isset($_REQUEST['adjust_privileges'])
+ && ! empty($_REQUEST['adjust_privileges'])
+ ) {
+ PMA_AdjustPrivileges_copyDB($GLOBALS['db'], $_REQUEST['newname']);
+ }
+
$message = PMA_Message::success(
__('Database %1$s has been copied to %2$s.')
);
@@ -196,7 +211,19 @@ $url_query .= '&amp;goto=db_operations.php';
// Gets the database structure
$sub_part = '_structure';
-require 'libraries/db_info.inc.php';
+
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
+
echo "\n";
if (isset($message)) {
@@ -218,11 +245,7 @@ if (!$is_information_schema) {
}
$response->addHTML('<div class="operations_half_width">');
- ob_start();
- include 'libraries/display_create_table.lib.php';
- $content = ob_get_contents();
- ob_end_clean();
- $response->addHTML($content);
+ $response->addHTML(PMA_getHtmlForCreateTable($db));
$response->addHTML('</div>');
/**
@@ -256,7 +279,10 @@ if (!$is_information_schema) {
&& $cfg['PmaNoRelation_DisableWarning'] == false
) {
$message = PMA_Message::notice(
- __('The phpMyAdmin configuration storage has been deactivated. %sFind out why%s.')
+ __(
+ 'The phpMyAdmin configuration storage has been deactivated. ' .
+ '%sFind out why%s.'
+ )
);
$message->addParam(
'<a href="' . $cfg['PmaAbsoluteUri']
@@ -287,5 +313,3 @@ if ($cfgRelation['pdfwork'] && $num_tables > 0) {
PMA_DatabaseInterface::QUERY_STORE
);
} // end if
-
-?>
diff --git a/db_printview.php b/db_printview.php
deleted file mode 100644
index 61676d686f..0000000000
--- a/db_printview.php
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Print view of a database
- *
- * @package PhpMyAdmin
- */
-
-/**
- *
- */
-require_once 'libraries/common.inc.php';
-require_once 'libraries/db_printview.lib.php';
-
-$response = PMA_Response::getInstance();
-$header = $response->getHeader();
-$header->enablePrintView();
-
-PMA_Util::checkParameters(array('db'));
-
-/**
- * Defines the url to return to in case of error in a sql statement
- */
-$err_url = 'db_sql.php' . PMA_URL_getCommon(array('db' => $db));
-
-/**
- * Settings for relations stuff
- */
-$cfgRelation = PMA_getRelationsParam();
-
-/**
- * If there is at least one table, displays the printer friendly view, else
- * an error message
- */
-$tables = $GLOBALS['dbi']->getTablesFull($db);
-$num_tables = count($tables);
-
-echo '<br />';
-
-// 1. No table
-if ($num_tables == 0) {
- echo __('No tables found in database.');
-} else {
- // 2. Shows table information
- echo '<table>';
- echo '<thead>';
- echo '<tr>';
- echo '<th>' . __('Table') . '</th>';
- echo '<th>' . __('Rows') . '</th>';
- echo '<th>' . __('Type') . '</th>';
- if ($cfg['ShowStats']) {
- echo '<th>' . __('Size') . '</th>';
- }
- echo '<th>' . __('Comments') . '</th>';
- echo '</tr>';
- echo '</thead>';
- echo '<tbody>';
- $sum_entries = $sum_size = 0;
- $odd_row = true;
- foreach ($tables as $sts_data) {
- if (PMA_Table::isMerge($db, $sts_data['TABLE_NAME'])
- || /*overload*/mb_strtoupper($sts_data['ENGINE']) == 'FEDERATED'
- ) {
- $merged_size = true;
- } else {
- $merged_size = false;
- }
- $sum_entries += $sts_data['TABLE_ROWS'];
- echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">';
- echo '<th>';
- echo htmlspecialchars($sts_data['TABLE_NAME']);
- echo '</th>';
-
- if (isset($sts_data['TABLE_ROWS'])) {
- echo '<td class="right">';
- if ($merged_size) {
- echo '<i>';
- echo PMA_Util::formatNumber($sts_data['TABLE_ROWS'], 0);
- echo '</i>';
- } else {
- echo PMA_Util::formatNumber($sts_data['TABLE_ROWS'], 0);
- }
- echo '</td>';
- echo '<td class="nowrap">';
- echo $sts_data['ENGINE'];
- echo '</td>';
- if ($cfg['ShowStats']) {
- $tblsize = $sts_data['Data_length'] + $sts_data['Index_length'];
- $sum_size += $tblsize;
- list($formated_size, $unit)
- = PMA_Util::formatByteDown($tblsize, 3, 1);
- echo '<td class="right nowrap">';
- echo $formated_size . ' ' . $unit;
- echo '</td>';
- } // end if
- } else {
- echo '<td colspan="3" class="center">';
- if (! PMA_Table::isView($db, $sts_data['TABLE_NAME'])) {
- echo __('in use');
- }
- echo '</td>';
- }
- echo '<td>';
- if (! empty($sts_data['Comment'])) {
- echo htmlspecialchars($sts_data['Comment']);
- $needs_break = '<br />';
- } else {
- $needs_break = '';
- }
-
- if (! empty($sts_data['Create_time'])
- || ! empty($sts_data['Update_time'])
- || ! empty($sts_data['Check_time'])
- ) {
- echo $needs_break;
- echo '<table width="100%">';
-
- if (! empty($sts_data['Create_time'])) {
- echo PMA_getHtmlForOneDate(
- __('Creation:'),
- $sts_data['Create_time']
- );
- }
-
- if (! empty($sts_data['Update_time'])) {
- echo PMA_getHtmlForOneDate(
- __('Last update:'),
- $sts_data['Update_time']
- );
- }
-
- if (! empty($sts_data['Check_time'])) {
- echo PMA_getHtmlForOneDate(
- __('Last check:'),
- $sts_data['Check_time']
- );
- }
- echo '</table>';
- }
- echo '</td>';
- echo '</tr>';
- }
- echo '<tr>';
- echo '<th class="center">';
- printf(
- _ngettext('%s table', '%s tables', $num_tables),
- PMA_Util::formatNumber($num_tables, 0)
- );
- echo '</th>';
- echo '<th class="right nowrap">';
- echo PMA_Util::formatNumber($sum_entries, 0);
- echo '</th>';
- echo '<th class="center">';
- echo '--';
- echo '</th>';
- if ($cfg['ShowStats']) {
- list($sum_formated, $unit)
- = PMA_Util::formatByteDown($sum_size, 3, 1);
- echo '<th class="right nowrap">';
- echo $sum_formated . ' ' . $unit;
- echo '</th>';
- }
- echo '<th></th>';
- echo '</tr>';
- echo '</tbody>';
- echo '</table>';
-}
-
-/**
- * Displays the footer
- */
-echo PMA_Util::getButton();
-
-echo "<div id='PMA_disable_floating_menubar'></div>\n";
-?>
diff --git a/db_qbe.php b/db_qbe.php
index f499efd348..842d46b402 100644
--- a/db_qbe.php
+++ b/db_qbe.php
@@ -22,7 +22,7 @@ $cfgRelation = PMA_getRelationsParam();
$savedSearchList = array();
$savedSearch = null;
$currentSearchId = null;
-if (isset($cfgRelation['savedsearcheswork']) && $cfgRelation['savedsearcheswork']) {
+if ($cfgRelation['savedsearcheswork']) {
include 'libraries/SavedSearches.class.php';
$header = $response->getHeader();
$scripts = $header->getScripts();
@@ -80,15 +80,30 @@ if (isset($_REQUEST['submit_sql']) && ! empty($sql_query)) {
if (! preg_match('@^SELECT@i', $sql_query)) {
$message_to_display = true;
} else {
- $goto = 'db_sql.php';
+ $goto = 'db_sql.php';
// Parse and analyze the query
include_once 'libraries/parse_analyze.inc.php';
PMA_executeQueryAndSendQueryResponse(
- $analyzed_sql_results, false, $_REQUEST['db'], null, false, null, null,
- false, null, null, null, $goto, $pmaThemeImage, null, null, null,
- $sql_query, null, null
+ $analyzed_sql_results, // analyzed_sql_results
+ false, // is_gotofile
+ $_REQUEST['db'], // db
+ null, // table
+ false, // find_real_end
+ null, // sql_query_for_bookmark
+ null, // extra_data
+ null, // message_to_show
+ null, // message
+ null, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ null, // disp_query
+ null, // disp_message
+ null, // query_type
+ $sql_query, // sql_query
+ null, // selectedTables
+ null // complete_query
);
}
}
@@ -97,7 +112,18 @@ $sub_part = '_qbe';
require 'libraries/db_common.inc.php';
$url_query .= '&amp;goto=db_qbe.php';
$url_params['goto'] = 'db_qbe.php';
-require 'libraries/db_info.inc.php';
+
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
if ($message_to_display) {
PMA_Message::error(__('You have to choose at least one column to display!'))
@@ -106,7 +132,7 @@ if ($message_to_display) {
unset($message_to_display);
// create new qbe search instance
-$db_qbe = new PMA_DBQbe($GLOBALS['db'], $savedSearchList, $savedSearch);
+$db_qbe = new PMA_DbQbe($GLOBALS['db'], $savedSearchList, $savedSearch);
$url = 'db_designer.php' . PMA_URL_getCommon(
array_merge(
@@ -128,4 +154,3 @@ $response->addHTML(
* Displays the Query by example form
*/
$response->addHTML($db_qbe->getSelectionForm());
-?>
diff --git a/db_routines.php b/db_routines.php
index a58d4c0a21..be7791c649 100644
--- a/db_routines.php
+++ b/db_routines.php
@@ -16,6 +16,7 @@ require_once 'libraries/mysql_charsets.inc.php';
/**
* Include all other files
*/
+require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/rte/rte_routines.lib.php';
/**
@@ -23,5 +24,3 @@ require_once 'libraries/rte/rte_routines.lib.php';
*/
$_PMA_RTE = 'RTN';
require_once 'libraries/rte/rte_main.inc.php';
-
-?>
diff --git a/db_search.php b/db_search.php
index 349f720a3a..3789ed9e78 100644
--- a/db_search.php
+++ b/db_search.php
@@ -24,7 +24,7 @@ $scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
require 'libraries/db_common.inc.php';
-// If config variable $GLOBALS['cfg']['Usedbsearch'] is on false : exit.
+// If config variable $GLOBALS['cfg']['UseDbSearch'] is on false : exit.
if (! $GLOBALS['cfg']['UseDbSearch']) {
PMA_Util::mysqlDie(
__('Access denied!'), '', false, $err_url
@@ -37,8 +37,18 @@ $url_params['goto'] = 'db_search.php';
$db_search = new PMA_DbSearch($GLOBALS['db']);
// Display top links if we are not in an Ajax request
-if ( $GLOBALS['is_ajax_request'] != true) {
- include 'libraries/db_info.inc.php';
+if ($GLOBALS['is_ajax_request'] != true) {
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
}
// Main search form has been submitted, get results
@@ -60,4 +70,3 @@ $response->addHTML(
);
$response->addHTML($db_search->getSelectionForm());
$response->addHTML($db_search->getResultDivs());
-?>
diff --git a/db_sql.php b/db_sql.php
index 987dbaff5f..fc140a8ef0 100644
--- a/db_sql.php
+++ b/db_sql.php
@@ -10,6 +10,9 @@
*
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Sql_queries');
/**
* Runs common work
@@ -41,5 +44,3 @@ $response->addHTML(
: ';'
)
);
-
-?>
diff --git a/db_sql_autocomplete.php b/db_sql_autocomplete.php
index 4897f0058a..3be88c43ca 100644
--- a/db_sql_autocomplete.php
+++ b/db_sql_autocomplete.php
@@ -8,17 +8,19 @@
require_once 'libraries/common.inc.php';
-$db = isset($_POST['db']) ? $_POST['db'] : $GLOBALS['db'];
-$sql_autocomplete = array();
-
-if ($db) {
- $tableNames = $GLOBALS['dbi']->getTables($db);
- foreach ($tableNames as $tableName) {
- $sql_autocomplete[$tableName] = $GLOBALS['dbi']->getColumns(
- $db, $tableName
- );
+if ($GLOBALS['cfg']['EnableAutocompleteForTablesAndColumns']) {
+ $db = isset($_POST['db']) ? $_POST['db'] : $GLOBALS['db'];
+ $sql_autocomplete = array();
+ if ($db) {
+ $tableNames = $GLOBALS['dbi']->getTables($db);
+ foreach ($tableNames as $tableName) {
+ $sql_autocomplete[$tableName] = $GLOBALS['dbi']->getColumns(
+ $db, $tableName
+ );
+ }
}
+} else {
+ $sql_autocomplete = true;
}
-
$response = PMA_Response::getInstance();
$response->addJSON("tables", json_encode($sql_autocomplete));
diff --git a/db_sql_format.php b/db_sql_format.php
index a83e5273ee..610b3e22aa 100644
--- a/db_sql_format.php
+++ b/db_sql_format.php
@@ -6,13 +6,15 @@
* @package PhpMyAdmin
*/
+/**
+ * Loading common files. Used to check for authorization, localization and to
+ * load the parsing library.
+ */
require_once 'libraries/common.inc.php';
-require_once 'libraries/sql-formatter/lib/SqlFormatter.php';
-$query = isset($_POST['sql']) ? $_POST['sql'] : '';
+$query = !empty($_POST['sql']) ? $_POST['sql'] : '';
-SqlFormatter::$tab = "\t";
-$query = SqlFormatter::format($query, false);
+$query = SqlParser\Utils\Formatter::format($query);
$response = PMA_Response::getInstance();
$response->addJSON("sql", $query);
diff --git a/db_structure.php b/db_structure.php
index 9773a94a38..14ab8b8e58 100644
--- a/db_structure.php
+++ b/db_structure.php
@@ -6,340 +6,49 @@
* @package PhpMyAdmin
*/
-/**
- *
- */
-require_once 'libraries/common.inc.php';
-
-/**
- * Function implementations for this script
- */
-require_once 'libraries/structure.lib.php';
-
-// Add/Remove favorite tables using Ajax request.
-if ($GLOBALS['is_ajax_request'] && ! empty($_REQUEST['favorite_table'])) {
- PMA_addRemoveFavoriteTables($db);
- exit;
-}
-
-$response = PMA_Response::getInstance();
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('db_structure.js');
-$scripts->addFile('tbl_change.js');
-$scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
-
-// Drops/deletes/etc. multiple tables if required
-if ((!empty($_POST['submit_mult']) && isset($_POST['selected_tbl']))
- || isset($_POST['mult_btn'])
-) {
- $action = 'db_structure.php';
- $err_url = 'db_structure.php' . PMA_URL_getCommon(array('db' => $db));
-
- // see bug #2794840; in this case, code path is:
- // db_structure.php -> libraries/mult_submits.inc.php -> sql.php
- // -> db_structure.php and if we got an error on the multi submit,
- // we must display it here and not call again mult_submits.inc.php
- if (! isset($_POST['error']) || false === $_POST['error']) {
- include 'libraries/mult_submits.inc.php';
- }
- if (empty($_POST['message'])) {
- $_POST['message'] = PMA_Message::success();
- }
-}
-
-require 'libraries/db_common.inc.php';
-$url_query .= '&amp;goto=db_structure.php';
-
-// Gets the database structure
-$sub_part = '_structure';
-require 'libraries/db_info.inc.php';
-
-// If there is an Ajax request for real row count of a table.
-if ($GLOBALS['is_ajax_request']
- && isset($_REQUEST['real_row_count'])
- && $_REQUEST['real_row_count'] == true
-) {
- PMA_handleRealRowCountRequest();
- exit;
-}
-
-if (!PMA_DRIZZLE) {
- include_once 'libraries/replication.inc.php';
-} else {
- $GLOBALS['replication_info']['slave']['status'] = false;
-}
-
-require_once 'libraries/bookmark.lib.php';
-
-require_once 'libraries/mysql_charsets.inc.php';
-$db_collation = PMA_getDbCollation($db);
-
-$titles = PMA_Util::buildActionTitles();
-
-// 1. No tables
-
-if ($num_tables == 0) {
- $response->addHTML(
- PMA_message::notice(__('No tables found in database.'))
- );
- PMA_possiblyShowCreateTableDialog($db, $db_is_system_schema, $response);
- exit;
-}
-
-// else
-// 2. Shows table informations
-
-/**
- * Displays the tables list
- */
-$response->addHTML('<div id="tableslistcontainer">');
-$_url_params = array(
- 'pos' => $pos,
- 'db' => $db);
-
-// Add the sort options if they exists
-if (isset($_REQUEST['sort'])) {
- $_url_params['sort'] = $_REQUEST['sort'];
-}
-
-if (isset($_REQUEST['sort_order'])) {
- $_url_params['sort_order'] = $_REQUEST['sort_order'];
-}
-
-$response->addHTML(
- PMA_Util::getListNavigator(
- $total_num_tables, $pos, $_url_params, 'db_structure.php',
- 'frame_content', $GLOBALS['cfg']['MaxTableList']
- )
-);
-
-// tables form
-$response->addHTML(
- '<form method="post" action="db_structure.php" '
- . 'name="tablesForm" id="tablesForm">'
-);
-
-$response->addHTML(PMA_URL_getHiddenInputs($db));
-
-$response->addHTML(
- PMA_tableHeader(
- $db_is_system_schema, $GLOBALS['replication_info']['slave']['status']
- )
-);
+namespace PMA;
-$i = $sum_entries = 0;
-$overhead_check = '';
-$create_time_all = '';
-$update_time_all = '';
-$check_time_all = '';
-$num_columns = $cfg['PropertiesNumColumns'] > 1
- ? ceil($num_tables / $cfg['PropertiesNumColumns']) + 1
- : 0;
-$row_count = 0;
-$sum_size = (double) 0;
-$overhead_size = (double) 0;
+use PMA_Response;
-$hidden_fields = array();
-$odd_row = true;
-// Instance of PMA_RecentFavoriteTable class.
-$fav_instance = PMA_RecentFavoriteTable::getInstance('favorite');
-foreach ($tables as $keyname => $current_table) {
- // Get valid statistics whatever is the table type
-
- $drop_query = '';
- $drop_message = '';
- $already_favorite = false;
- $overhead = '';
-
- $table_is_view = false;
- $table_encoded = urlencode($current_table['TABLE_NAME']);
- // Sets parameters for links
- $tbl_url_query = $url_query . '&amp;table=' . $table_encoded;
- // do not list the previous table's size info for a view
-
- list($current_table, $formatted_size, $unit, $formatted_overhead,
- $overhead_unit, $overhead_size, $table_is_view, $sum_size)
- = PMA_getStuffForEngineTypeTable(
- $current_table, $db_is_system_schema,
- $is_show_stats, $table_is_view, $sum_size, $overhead_size
- );
-
- if (! PMA_Table::isMerge($db, $current_table['TABLE_NAME'])) {
- $sum_entries += $current_table['TABLE_ROWS'];
- }
-
- if (isset($current_table['Collation'])) {
- $collation = '<dfn title="'
- . PMA_getCollationDescr($current_table['Collation']) . '">'
- . $current_table['Collation'] . '</dfn>';
- } else {
- $collation = '---';
- }
-
- if ($is_show_stats) {
- if ($formatted_overhead != '') {
- $overhead = '<a href="tbl_structure.php'
- . $tbl_url_query . '#showusage">'
- . '<span>' . $formatted_overhead . '</span>&nbsp;'
- . '<span class="unit">' . $overhead_unit . '</span>'
- . '</a>' . "\n";
- $overhead_check .=
- "markAllRows('row_tbl_" . ($i + 1) . "');";
- } else {
- $overhead = '-';
- }
- } // end if
-
- unset($showtable);
-
- if ($GLOBALS['cfg']['ShowDbStructureCreation']) {
- list($create_time, $create_time_all) = PMA_getTimeForCreateUpdateCheck(
- $current_table, 'Create_time', $create_time_all
- );
- }
-
- if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) {
- // $showtable might already be set from ShowDbStructureCreation, see above
- list($update_time, $update_time_all) = PMA_getTimeForCreateUpdateCheck(
- $current_table, 'Update_time', $update_time_all
- );
- }
-
- if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) {
- // $showtable might already be set from ShowDbStructureCreation, see above
- list($check_time, $check_time_all) = PMA_getTimeForCreateUpdateCheck(
- $current_table, 'Check_time', $check_time_all
- );
- }
-
- list($alias, $truename) = PMA_getAliasAndTrueName(
- $tooltip_aliasname, $current_table, $tooltip_truename
- );
-
- $i++;
-
- $row_count++;
- if ($table_is_view) {
- $hidden_fields[] = '<input type="hidden" name="views[]" value="'
- . htmlspecialchars($current_table['TABLE_NAME']) . '" />';
- }
-
- /*
- * Always activate links for Browse, Search and Empty, even if
- * the icons are greyed, because
- * 1. for views, we don't know the number of rows at this point
- * 2. for tables, another source could have populated them since the
- * page was generated
- *
- * I could have used the PHP ternary conditional operator but I find
- * the code easier to read without this operator.
- */
- list($browse_table, $search_table, $browse_table_label, $empty_table,
- $tracking_icon) = PMA_getHtmlForActionLinks(
- $current_table, $table_is_view, $tbl_url_query,
- $titles, $truename, $db_is_system_schema, $url_query
- );
-
- if (! $db_is_system_schema) {
- list($drop_query, $drop_message)
- = PMA_getTableDropQueryAndMessage($table_is_view, $current_table);
- }
-
- if ($num_columns > 0
- && $num_tables > $num_columns
- && ($row_count % $num_columns) == 0
- ) {
- $row_count = 1;
- $odd_row = true;
-
- $response->addHTML(
- '</tr></tbody></table>'
- );
-
- $response->addHTML(
- PMA_tableHeader(false, $GLOBALS['replication_info']['slave']['status'])
- );
- }
-
- list($do, $ignored) = PMA_getServerSlaveStatus(
- $GLOBALS['replication_info']['slave']['status'], $truename
- );
- // Handle favorite table list. ----START----
- $already_favorite = PMA_checkFavoriteTable($db, $current_table['TABLE_NAME']);
-
- if (isset($_REQUEST['remove_favorite'])) {
- if ($already_favorite) {
- // If already in favorite list, remove it.
- $favorite_table = $_REQUEST['favorite_table'];
- $fav_instance->remove($db, $favorite_table);
- }
- }
-
- if (isset($_REQUEST['add_favorite'])) {
- if (!$already_favorite) {
- // Otherwise add to favorite list.
- $favorite_table = $_REQUEST['favorite_table'];
- $fav_instance->add($db, $favorite_table);
- }
- } // Handle favorite table list. ----ENDS----
-
- list($html_output, $odd_row, $approx_rows) = PMA_getHtmlForStructureTableRow(
- $i, $odd_row, $table_is_view, $current_table,
- $browse_table_label, $tracking_icon,
- $GLOBALS['replication_info']['slave']['status'],
- $browse_table, $tbl_url_query, $search_table, $db_is_system_schema,
- $titles, $empty_table, $drop_query, $drop_message, $collation,
- $formatted_size, $unit, $overhead,
- (isset ($create_time) ? $create_time : ''),
- (isset ($update_time) ? $update_time : ''),
- (isset ($check_time) ? $check_time : ''),
- $is_show_stats, $ignored, $do, $colspan_for_structure
- );
- $response->addHTML($html_output);
-
-} // end foreach
-
-// Show Summary
-$response->addHTML('</tbody>');
-$response->addHTML(
- PMA_getHtmlBodyForTableSummary(
- $num_tables, $GLOBALS['replication_info']['slave']['status'],
- $db_is_system_schema, $sum_entries, $db_collation, $is_show_stats, $sum_size,
- $overhead_size, $create_time_all, $update_time_all, $check_time_all,
- isset($approx_rows) ? $approx_rows : false
- )
-);
-$response->addHTML('</table>');
-//check all
-$response->addHTML(
- PMA_getHtmlForCheckAllTables(
- $pmaThemeImage, $text_dir, $overhead_check,
- $db_is_system_schema, $hidden_fields
- )
-);
-$response->addHTML('</form>'); //end of form
-
-// display again the table list navigator
-$response->addHTML(
- PMA_Util::getListNavigator(
- $total_num_tables, $pos, $_url_params, 'db_structure.php',
- 'frame_content', $GLOBALS['cfg']['MaxTableList']
- )
+require_once 'libraries/common.inc.php';
+require_once 'libraries/db_common.inc.php';
+
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = \PMA_Util::getDbInfo($GLOBALS['db'], isset($sub_part) ? $sub_part : '');
+
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/controllers/DatabaseStructureController.class.php';
+require_once 'libraries/Response.class.php';
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\DatabaseStructureController');
+$container->alias(
+ 'DatabaseStructureController', 'PMA\Controllers\DatabaseStructureController'
);
-
-$response->addHTML('</div><hr />');
-
-/**
- * Work on the database
- */
-/* DATABASE WORK */
-/* Printable view of a table */
-$response->addHTML(
- PMA_getHtmlForTablePrintViewLink($url_query)
- . PMA_getHtmlForDataDictionaryLink($url_query)
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+
+global $db, $pos, $db_is_system_schema, $total_num_tables, $tables, $num_tables;
+/* Define dependencies for the concerned controller */
+$dependency_definitions = array(
+ 'db' => $db,
+ 'url_query' => &$GLOBALS['url_query'],
+ 'pos' => $pos,
+ 'db_is_system_schema' => $db_is_system_schema,
+ 'num_tables' => $num_tables,
+ 'total_num_tables' => $total_num_tables,
+ 'tables' => $tables,
);
-PMA_possiblyShowCreateTableDialog($db, $db_is_system_schema, $response);
-
-?>
+/** @var Controllers\DatabaseStructureController $controller */
+$controller = $container->get('DatabaseStructureController', $dependency_definitions);
+$controller->indexAction();
diff --git a/db_tracking.php b/db_tracking.php
index 8a5028d7e4..e451ccd574 100644
--- a/db_tracking.php
+++ b/db_tracking.php
@@ -12,6 +12,7 @@
require_once 'libraries/common.inc.php';
require_once './libraries/tracking.lib.php';
+require_once 'libraries/display_create_table.lib.php';
//Get some js files needed for Ajax requests
$response = PMA_Response::getInstance();
@@ -28,7 +29,18 @@ $url_query .= '&amp;goto=tbl_tracking.php&amp;back=db_tracking.php';
// Get the database structure
$sub_part = '_structure';
-require 'libraries/db_info.inc.php';
+
+list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
// Work to do?
// (here, do not use $_REQUEST['db] as it can be crafted)
@@ -89,7 +101,7 @@ if ($num_tables == 0 && count($data['ddlog']) == 0) {
echo '<p>' . __('No tables found in database.') . '</p>' . "\n";
if (empty($db_is_system_schema)) {
- include 'libraries/display_create_table.lib.php';
+ echo PMA_getHtmlForCreateTable($db);
}
exit;
}
@@ -108,234 +120,20 @@ $all_tables_query = ' SELECT table_name, MAX(version) as version FROM ' .
$all_tables_result = PMA_queryAsControlUser($all_tables_query);
// If a HEAD version exists
-if ($GLOBALS['dbi']->numRows($all_tables_result) > 0) {
- ?>
- <div id="tracked_tables">
- <h3><?php echo __('Tracked tables');?></h3>
-
- <form method="post" action="db_tracking.php" name="trackedForm"
- id="trackedForm" class="ajax">
- <?php
- echo PMA_URL_getHiddenInputs($GLOBALS['db'])
- ?>
- <table id="versions" class="data">
- <thead>
- <tr>
- <th></th>
- <th><?php echo __('Table');?></th>
- <th><?php echo __('Last version');?></th>
- <th><?php echo __('Created');?></th>
- <th><?php echo __('Updated');?></th>
- <th><?php echo __('Status');?></th>
- <th><?php echo __('Action');?></th>
- <th><?php echo __('Show');?></th>
- </tr>
- </thead>
- <tbody>
- <?php
-
- // Print out information about versions
-
- $delete = PMA_Util::getIcon('b_drop.png', __('Delete tracking'));
- $versions = PMA_Util::getIcon('b_versions.png', __('Versions'));
- $report = PMA_Util::getIcon('b_report.png', __('Tracking report'));
- $structure = PMA_Util::getIcon('b_props.png', __('Structure snapshot'));
-
- $style = 'odd';
- while ($one_result = $GLOBALS['dbi']->fetchArray($all_tables_result)) {
- list($table_name, $version_number) = $one_result;
- $table_query = ' SELECT * FROM ' .
- PMA_Util::backquote($cfgRelation['db']) . '.' .
- PMA_Util::backquote($cfgRelation['tracking']) .
- ' WHERE `db_name` = \'' . PMA_Util::sqlAddSlashes($_REQUEST['db'])
- . '\' AND `table_name` = \'' . PMA_Util::sqlAddSlashes($table_name)
- . '\' AND `version` = \'' . $version_number . '\'';
-
- $table_result = PMA_queryAsControlUser($table_query);
- $version_data = $GLOBALS['dbi']->fetchArray($table_result);
-
- $tmp_link = 'tbl_tracking.php' . $url_query . '&amp;table='
- . htmlspecialchars($version_data['table_name']);
- $delete_link = 'db_tracking.php' . $url_query . '&amp;table='
- . htmlspecialchars($version_data['table_name'])
- . '&amp;delete_tracking=true&amp';
- $checkbox_id = "selected_tbl_"
- . htmlspecialchars($version_data['table_name']);
- ?>
- <tr class="noclick <?php echo $style;?>">
- <td class="center">
- <input type="checkbox" name="selected_tbl[]"
- class="checkall" id="<?php echo $checkbox_id;?>"
- value="<?php echo htmlspecialchars($version_data['table_name']);?>"/>
- </td>
- <th>
- <label for="<?php echo $checkbox_id;?>">
- <?php echo htmlspecialchars($version_data['table_name']);?>
- </label>
- </th>
- <td class="right"><?php echo $version_data['version'];?></td>
- <td><?php echo $version_data['date_created'];?></td>
- <td><?php echo $version_data['date_updated'];?></td>
- <td>
- <?php
- $state = PMA_getVersionStatus($version_data);
- $options = array(
- 0 => array(
- 'label' => __('not active'),
- 'value' => 'deactivate_now',
- 'selected' => ($state != 'active')
- ),
- 1 => array(
- 'label' => __('active'),
- 'value' => 'activate_now',
- 'selected' => ($state == 'active')
- )
- );
- echo PMA_Util::toggleButton(
- $tmp_link . '&amp;version=' . $version_data['version'],
- 'toggle_activation',
- $options,
- null
- );
- ?>
- </td>
- <td>
- <a class="delete_tracking_anchor ajax" href="<?php echo $delete_link;?>" >
- <?php echo $delete; ?></a>
- <?php
- echo '</td>'
- . '<td>'
- . '<a href="' . $tmp_link . '">' . $versions . '</a>'
- . '&nbsp;&nbsp;'
- . '<a href="' . $tmp_link . '&amp;report=true&amp;version='
- . $version_data['version'] . '">' . $report . '</a>'
- . '&nbsp;&nbsp;'
- . '<a href="' . $tmp_link . '&amp;snapshot=true&amp;version='
- . $version_data['version'] . '">' . $structure . '</a>'
- . '</td>'
- . '</tr>';
- if ($style == 'even') {
- $style = 'odd';
- } else {
- $style = 'even';
- }
- }
- unset($tmp_link);
- ?>
- </tbody>
- </table>
- <?php
- echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "trackedForm");
- echo PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_delete_tracking',
- __('Delete tracking'), 'b_drop.png', 'delete_tracking'
+if (is_object($all_tables_result) && $GLOBALS['dbi']->numRows($all_tables_result) > 0) {
+ PMA_displayTrackedTables(
+ $GLOBALS['db'], $all_tables_result, $url_query, $pmaThemeImage,
+ $text_dir, $cfgRelation
);
- ?>
- </form>
- </div>
- <?php
}
-$sep = $GLOBALS['cfg']['NavigationTreeTableSeparator'];
-
-// Get list of tables
-$table_list = PMA_Util::getTableList($GLOBALS['db']);
-
-$my_tables = array();
-
-// For each table try to get the tracking version
-foreach ($table_list as $key => $value) {
- // If $value is a table group.
- if (array_key_exists(('is' . $sep . 'group'), $value)
- && $value['is' . $sep . 'group']
- ) {
- foreach ($value as $temp_table) {
- // If $temp_table is a table with the value for 'Name' is set,
- // rather than a property of the table group.
- if (is_array($temp_table)
- && array_key_exists('Name', $temp_table)
- ) {
- $tracking_version = PMA_Tracker::getVersion(
- $GLOBALS['db'],
- $temp_table['Name']
- );
- if ($tracking_version == -1) {
- $my_tables[] = $temp_table['Name'];
- }
- }
- }
- } else { // If $value is a table.
- if (PMA_Tracker::getVersion($GLOBALS['db'], $value['Name']) == -1) {
- $my_tables[] = $value['Name'];
- }
- }
-}
+$untracked_tables = PMA_getUntrackedTables($GLOBALS['db']);
// If untracked tables exist
-if (count($my_tables) > 0) {
- ?>
- <h3><?php echo __('Untracked tables');?></h3>
- <form method="post" action="db_tracking.php" name="untrackedForm"
- id="untrackedForm" class="ajax">
- <?php
- echo PMA_URL_getHiddenInputs($GLOBALS['db'])
- ?>
- <table id="noversions" class="data">
- <thead>
- <tr>
- <th></th>
- <th style="width: 300px"><?php echo __('Table');?></th>
- <th><?php echo __('Action');?></th>
- </tr>
- </thead>
- <tbody>
- <?php
- // Print out list of untracked tables
-
- $style = 'odd';
-
- foreach ($my_tables as $key => $tablename) {
- $checkbox_id = "selected_tbl_"
- . htmlspecialchars($tablename);
- if (PMA_Tracker::getVersion($GLOBALS['db'], $tablename) == -1) {
- $my_link = '<a href="tbl_tracking.php' . $url_query
- . '&amp;table=' . htmlspecialchars($tablename) . '">';
- $my_link .= PMA_Util::getIcon('eye.png', __('Track table'));
- $my_link .= '</a>';
- ?>
- <tr class="noclick <?php echo $style;?>">
- <td class="center">
- <input type="checkbox" name="selected_tbl[]"
- class="checkall" id="<?php echo $checkbox_id;?>"
- value="<?php echo htmlspecialchars($tablename);?>"/>
- </td>
- <th>
- <label for="<?php echo $checkbox_id;?>">
- <?php echo htmlspecialchars($tablename);?>
- </label>
- </th>
- <td><?php echo $my_link;?></td>
- </tr>
- <?php
- if ($style == 'even') {
- $style = 'odd';
- } else {
- $style = 'even';
- }
- }
- }
- ?>
- </tbody>
- </table>
- <?php
- echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "untrackedForm");
- echo PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_track',
- __('Track table'), 'eye.png', 'track'
+if (count($untracked_tables) > 0) {
+ PMA_displayUntrackedTables(
+ $GLOBALS['db'], $untracked_tables, $url_query, $pmaThemeImage, $text_dir
);
- ?>
- </form>
- <?php
}
// If available print out database log
if (count($data['ddlog']) > 0) {
@@ -346,5 +144,3 @@ if (count($data['ddlog']) > 0) {
}
echo PMA_Util::getMessage(__('Database Log'), $log);
}
-
-?>
diff --git a/db_triggers.php b/db_triggers.php
index d1a2a8c6b2..a415fb43d0 100644
--- a/db_triggers.php
+++ b/db_triggers.php
@@ -21,5 +21,3 @@ require_once 'libraries/rte/rte_triggers.lib.php';
*/
$_PMA_RTE = 'TRI';
require_once 'libraries/rte/rte_main.inc.php';
-
-?>
diff --git a/error_report.php b/error_report.php
index d86add56cc..4510f1ad51 100644
--- a/error_report.php
+++ b/error_report.php
@@ -127,4 +127,3 @@ if (isset($_REQUEST['send_error_report'])
$GLOBALS['error_handler']->savePreviousErrors();
}
}
-?>
diff --git a/export.php b/export.php
index 5e9765990b..1bef625b5e 100644
--- a/export.php
+++ b/export.php
@@ -49,15 +49,19 @@ if (!defined('TESTSUITE')) {
'quick_or_custom',
'db_select',
'table_select',
+ 'table_structure',
+ 'table_data',
'limit_to',
'limit_from',
'allrows',
+ 'lock_tables',
'output_format',
'filename_template',
'maxsize',
'remember_template',
- 'charset_of_file',
+ 'charset',
'compression',
+ 'as_separate_files',
'knjenc',
'xkana',
'htmlword_structure_or_data',
@@ -85,6 +89,7 @@ if (!defined('TESTSUITE')) {
'ods_structure_or_data',
'ods_columns',
'json_structure_or_data',
+ 'json_pretty_print',
'xml_structure_or_data',
'xml_export_events',
'xml_export_functions',
@@ -109,7 +114,6 @@ if (!defined('TESTSUITE')) {
'sql_create_database',
'sql_drop_table',
'sql_procedure_function',
- 'sql_create_table_statements',
'sql_create_table',
'sql_create_view',
'sql_create_trigger',
@@ -126,6 +130,7 @@ if (!defined('TESTSUITE')) {
'sql_utc_time',
'sql_drop_database',
'sql_views_as_tables',
+ 'sql_metadata',
'csv_separator',
'csv_enclosed',
'csv_escaped',
@@ -164,6 +169,7 @@ if (!defined('TESTSUITE')) {
PMA_Util::checkParameters(array('what', 'export_type'));
// export class instance, not array of properties, as before
+ /* @var $export_plugin ExportPlugin */
$export_plugin = PMA_getPlugin(
"export",
$what,
@@ -178,15 +184,10 @@ if (!defined('TESTSUITE')) {
$type = $what;
// Check export type
- if (! isset($export_plugin)) {
+ if (empty($export_plugin)) {
PMA_fatalError(__('Bad type!'));
}
- // Avoid warning from PHP Analyzer
- if (is_null($export_plugin)) {
- $export_plugin = new stdClass();
- }
-
/**
* valid compression methods
*/
@@ -207,6 +208,7 @@ if (!defined('TESTSUITE')) {
$file_handle = '';
$err_url = '';
$filename = '';
+ $separate_files = '';
// Is it a quick or custom export?
if ($_REQUEST['quick_or_custom'] == 'quick') {
@@ -219,6 +221,16 @@ if (!defined('TESTSUITE')) {
$asfile = false;
} else {
$asfile = true;
+ if (isset($_REQUEST['as_separate_files'])
+ && ! empty($_REQUEST['as_separate_files'])
+ ) {
+ if (isset($_REQUEST['compression'])
+ && ! empty($_REQUEST['compression'])
+ && $_REQUEST['compression'] == 'zip'
+ ) {
+ $separate_files = $_REQUEST['as_separate_files'];
+ }
+ }
if (in_array($_REQUEST['compression'], $compression_methods)) {
$compression = $_REQUEST['compression'];
$buffer_needed = true;
@@ -266,14 +278,20 @@ if (!defined('TESTSUITE')) {
// Merge SQL Query aliases with Export aliases from
// export page, Export page aliases are given more
// preference over SQL Query aliases.
- if (!empty($_REQUEST['aliases'])) {
- $aliases = PMA_mergeAliases(
- PMA_SQP_getAliasesFromQuery($sql_query, $db),
- $_REQUEST['aliases']
- );
- $_SESSION['tmpval']['aliases'] = $_REQUEST['aliases'];
- } else {
- $aliases = PMA_SQP_getAliasesFromQuery($sql_query, $db);
+ $parser = new SqlParser\Parser($sql_query);
+ $aliases = array();
+ if ((!empty($parser->statements[0]))
+ && ($parser->statements[0] instanceof SqlParser\Statements\SelectStatement)
+ ) {
+ if (!empty($_REQUEST['aliases'])) {
+ $aliases = PMA_mergeAliases(
+ SqlParser\Utils\Misc::getAliases($parser->statements[0], $db),
+ $_REQUEST['aliases']
+ );
+ $_SESSION['tmpval']['aliases'] = $_REQUEST['aliases'];
+ } else {
+ $aliases = SqlParser\Utils\Misc::getAliases($parser->statements[0], $db);
+ }
}
/**
@@ -288,6 +306,9 @@ if (!defined('TESTSUITE')) {
$dump_buffer = '';
$dump_buffer_len = 0;
+ // Array of dump_buffers - used in separate file exports
+ $dump_buffer_objects = array();
+
// We send fake headers to avoid browser timeout when buffering
$time_start = time();
@@ -305,7 +326,7 @@ if (!defined('TESTSUITE')) {
// Do we need to convert charset?
$output_charset_conversion = $asfile
&& $GLOBALS['PMA_recoding_engine'] != PMA_CHARSET_NONE
- && isset($charset_of_file) && $charset_of_file != 'utf-8'
+ && isset($charset) && $charset != 'utf-8'
&& $type != 'xls';
// Use on the fly compression?
@@ -377,9 +398,12 @@ if (!defined('TESTSUITE')) {
do {
// Add possibly some comments to export
- if (! $export_plugin->exportHeader($db)) {
+ if (! $export_plugin->exportHeader()) {
break;
}
+ // Re - initialize
+ $dump_buffer = '';
+ $dump_buffer_len = 0;
// Will we need relation & co. setup?
$do_relation = isset($GLOBALS[$what . '_relation']);
@@ -408,14 +432,40 @@ if (!defined('TESTSUITE')) {
PMA_exportServer(
$db_select, $whatStrucOrData, $export_plugin, $crlf, $err_url,
$export_type, $do_relation, $do_comments, $do_mime, $do_dates,
- $aliases
+ $aliases, $separate_files
);
} elseif ($export_type == 'database') {
- PMA_exportDatabase(
- $db, $tables, $whatStrucOrData, $export_plugin, $crlf, $err_url,
- $export_type, $do_relation, $do_comments, $do_mime, $do_dates,
- $aliases
- );
+ if (!isset($table_structure) || !is_array($table_structure)) {
+ $table_structure = array();
+ }
+ if (!isset($table_data) || !is_array($table_data)) {
+ $table_data = array();
+ }
+ if (!empty($_REQUEST['structure_or_data_forced'])) {
+ $table_structure = $tables;
+ $table_data = $tables;
+ }
+ if (isset($lock_tables)) {
+ PMA_lockTables($db, $tables, "READ");
+ try {
+ PMA_exportDatabase(
+ $db, $tables, $whatStrucOrData, $table_structure,
+ $table_data, $export_plugin, $crlf, $err_url, $export_type,
+ $do_relation, $do_comments, $do_mime, $do_dates, $aliases,
+ $separate_files
+ );
+ PMA_unlockTables();
+ } catch (Exception $e) { // TODO use finally when PHP version is 5.5
+ PMA_unlockTables();
+ throw $e;
+ }
+ } else {
+ PMA_exportDatabase(
+ $db, $tables, $whatStrucOrData, $table_structure, $table_data,
+ $export_plugin, $crlf, $err_url, $export_type, $do_relation,
+ $do_comments, $do_mime, $do_dates, $aliases, $separate_files
+ );
+ }
} else {
// We export just one table
// $allrows comes from the form when "Dump all rows" has been selected
@@ -428,11 +478,27 @@ if (!defined('TESTSUITE')) {
if (! isset($limit_from)) {
$limit_from = 0;
}
- PMA_exportTable(
- $db, $table, $whatStrucOrData, $export_plugin, $crlf, $err_url,
- $export_type, $do_relation, $do_comments, $do_mime, $do_dates,
- $allrows, $limit_to, $limit_from, $sql_query, $aliases
- );
+ if (isset($lock_tables)) {
+ try {
+ PMA_lockTables($db, array($table), "READ");
+ PMA_exportTable(
+ $db, $table, $whatStrucOrData, $export_plugin, $crlf,
+ $err_url, $export_type, $do_relation, $do_comments,
+ $do_mime, $do_dates, $allrows, $limit_to, $limit_from,
+ $sql_query, $aliases
+ );
+ PMA_unlockTables();
+ } catch (Exception $e) { // TODO use finally when PHP version is 5.5
+ PMA_unlockTables();
+ throw $e;
+ }
+ } else {
+ PMA_exportTable(
+ $db, $table, $whatStrucOrData, $export_plugin, $crlf, $err_url,
+ $export_type, $do_relation, $do_comments, $do_mime, $do_dates,
+ $allrows, $limit_to, $limit_from, $sql_query, $aliases
+ );
+ }
}
if (! $export_plugin->exportFooter()) {
break;
@@ -448,33 +514,39 @@ if (!defined('TESTSUITE')) {
/**
* Send the dump as a file...
*/
- if (! empty($asfile)) {
- // Convert the charset if required.
- if ($output_charset_conversion) {
- $dump_buffer = PMA_convertString(
- 'utf-8',
- $GLOBALS['charset_of_file'],
- $dump_buffer
- );
- }
+ if (empty($asfile)) {
+ echo PMA_getHtmlForDisplayedExportFooter($back_button);
+ return;
+ } // end if
- // Compression needed?
- if ($compression) {
+ // Convert the charset if required.
+ if ($output_charset_conversion) {
+ $dump_buffer = PMA_convertString(
+ 'utf-8',
+ $GLOBALS['charset'],
$dump_buffer
- = PMA_compressExport($dump_buffer, $compression, $filename);
- }
+ );
+ }
- /* If we saved on server, we have to close file now */
- if ($save_on_server) {
- $message = PMA_closeExportFile(
- $file_handle, $dump_buffer, $save_filename
+ // Compression needed?
+ if ($compression) {
+ if (! empty($separate_files)) {
+ $dump_buffer = PMA_compressExport(
+ $dump_buffer_objects, $compression, $filename
);
- PMA_showExportPage($db, $table, $export_type);
} else {
- echo $dump_buffer;
+ $dump_buffer = PMA_compressExport($dump_buffer, $compression, $filename);
}
+
+ }
+
+ /* If we saved on server, we have to close file now */
+ if ($save_on_server) {
+ $message = PMA_closeExportFile(
+ $file_handle, $dump_buffer, $save_filename
+ );
+ PMA_showExportPage($db, $table, $export_type);
} else {
- echo PMA_getHtmlForDisplayedExportFooter($back_button);
- } // end if
+ echo $dump_buffer;
+ }
}
-?>
diff --git a/favicon.ico b/favicon.ico
index 2352b5fa4e..fb156b22e7 100644
--- a/favicon.ico
+++ b/favicon.ico
Binary files differ
diff --git a/file_echo.php b/file_echo.php
index e4409779da..1f27bb019b 100644
--- a/file_echo.php
+++ b/file_echo.php
@@ -78,4 +78,3 @@ if (isset($_REQUEST['filename']) && isset($_REQUEST['image'])) {
}
echo file_get_contents($_FILES['file']['tmp_name']);
}
-?>
diff --git a/gis_data_editor.php b/gis_data_editor.php
index f14e4662d2..ac876da4d9 100644
--- a/gis_data_editor.php
+++ b/gis_data_editor.php
@@ -22,7 +22,6 @@ function escape($variable)
require_once 'libraries/common.inc.php';
require_once 'libraries/gis/GIS_Factory.class.php';
require_once 'libraries/gis/GIS_Visualization.class.php';
-require_once 'libraries/tbl_gis_visualization.lib.php';
// Get data if any posted
$gis_data = array();
@@ -89,10 +88,11 @@ $visualizationSettings = array(
'spatialColumn' => 'wkt'
);
$data = array(array('wkt' => $wkt_with_zero, 'srid' => $srid));
-$visualization = PMA_GIS_visualizationResults(
- $data, $visualizationSettings, $format
-);
-$open_layers = PMA_GIS_visualizationResults($data, $visualizationSettings, 'ol');
+$visualization = PMA_GIS_Visualization::getByData($data, $visualizationSettings)
+ ->toImage($format);
+
+$open_layers = PMA_GIS_Visualization::getByData($data, $visualizationSettings)
+ ->asOl();
// If the call is to update the WKT and visualization make an AJAX response
if (isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) {
@@ -301,7 +301,7 @@ for ($a = 0; $a < $geom_count; $a++) {
echo '<label for="y">' . __("Y") . '</label>';
echo '<input type="text" name="gis_data[' . $a . '][' . $type . ']['
. $i . '][' . $j . '][y]"' . ' value="'
- . escape($gis_data[$a][$type][$i][$j]['x']) . '" />';
+ . escape($gis_data[$a][$type][$i][$j]['y']) . '" />';
}
echo '<input type="submit" name="gis_data[' . $a . '][' . $type . ']['
. $i . '][add_point]"'
@@ -426,4 +426,3 @@ echo '</form>';
PMA_Response::getInstance()->addJSON('gis_editor', ob_get_contents());
ob_end_clean();
-?>
diff --git a/import.php b/import.php
index c551179078..2015ec15eb 100644
--- a/import.php
+++ b/import.php
@@ -68,7 +68,6 @@ if (isset($_REQUEST['console_bookmark_add'])) {
* Sets globals from $_POST
*/
$post_params = array(
- 'bkm_label',
'charset_of_file',
'format',
'import_type',
@@ -76,7 +75,6 @@ $post_params = array(
'MAX_FILE_SIZE',
'message_to_show',
'noplugin',
- 'skip',
'skip_queries',
'local_import_file'
);
@@ -100,9 +98,31 @@ if (!isset($_SESSION['is_multi_query'])) {
$_SESSION['is_multi_query'] = false;
}
+$ajax_reload = array();
// Are we just executing plain query or sql file?
// (eg. non import, but query box/window run)
if (! empty($sql_query)) {
+
+ // apply values for parameters
+ if (! empty($_REQUEST['parameterized'])) {
+ $parameters = $_REQUEST['parameters'];
+ foreach ($parameters as $parameter => $replacement) {
+ $quoted = preg_quote($parameter);
+ // making sure that :param does not apply values to :param1
+ $sql_query = preg_replace(
+ '/' . $quoted . '([^a-zA-Z0-9_])/',
+ PMA_Util::sqlAddSlashes($replacement) . '${1}',
+ $sql_query
+ );
+ // for parameters the appear at the end of the string
+ $sql_query = preg_replace(
+ '/' . $quoted . '$/',
+ PMA_Util::sqlAddSlashes($replacement),
+ $sql_query
+ );
+ }
+ }
+
// run SQL query
$import_text = $sql_query;
$import_type = 'query';
@@ -117,6 +137,7 @@ if (! empty($sql_query)) {
// refresh navigation and main panels
if (preg_match('/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $sql_query)) {
$GLOBALS['reload'] = true;
+ $ajax_reload['reload'] = true;
}
// refresh navigation panel only
@@ -124,7 +145,7 @@ if (! empty($sql_query)) {
'/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
$sql_query
)) {
- $ajax_reload = array('reload' => true);
+ $ajax_reload['reload'] = true;
}
// do a dynamic reload if table is RENAMED
@@ -134,17 +155,11 @@ if (! empty($sql_query)) {
$sql_query,
$rename_table_names
)) {
- $ajax_reload = array('reload' => true);
+ $ajax_reload['reload'] = true;
$ajax_reload['table_name'] = PMA_Util::unQuote($rename_table_names[2]);
}
$sql_query = '';
-} elseif (! empty($sql_localfile)) {
- // run SQL file on server
- $local_import_file = $sql_localfile;
- $import_type = 'queryfile';
- $format = 'sql';
- unset($sql_localfile);
} elseif (! empty($sql_file)) {
// run uploaded SQL file
$import_file = $sql_file;
@@ -161,7 +176,10 @@ if (! empty($sql_query)) {
// upload limit has been reached, let's assume the second possibility.
if ($_POST == array() && $_GET == array()) {
$message = PMA_Message::error(
- __('You probably tried to upload a file that is too large. Please refer to %sdocumentation%s for a workaround for this limit.')
+ __(
+ 'You probably tried to upload a file that is too large. Please refer ' .
+ 'to %sdocumentation%s for a workaround for this limit.'
+ )
);
$message->addParam('[doc@faq1-16]');
$message->addParam('[/doc]');
@@ -311,9 +329,7 @@ if (! empty($_REQUEST['id_bookmark'])) {
isset($_REQUEST['action_bookmark_all'])
);
if (! empty($_REQUEST['bookmark_variable'])) {
- $import_text = preg_replace(
- '|/\*(.*)\[VARIABLE\](.*)\*/|imsU',
- '${1}' . PMA_Util::sqlAddSlashes($_REQUEST['bookmark_variable']) . '${2}',
+ $import_text = PMA_Bookmark_applyVariables(
$import_text
);
}
@@ -324,6 +340,7 @@ if (! empty($_REQUEST['id_bookmark'])) {
$import_text
)) {
$GLOBALS['reload'] = true;
+ $ajax_reload['reload'] = true;
}
// refresh navigation panel only
@@ -332,9 +349,6 @@ if (! empty($_REQUEST['id_bookmark'])) {
$import_text
)
) {
- if (! isset($ajax_reload)) {
- $ajax_reload = array();
- }
$ajax_reload['reload'] = true;
}
break;
@@ -452,7 +466,11 @@ if ($import_file != 'none' && ! $error) {
// instead.
$message = PMA_Message::error(
- __('Uploaded file cannot be moved, because the server has open_basedir enabled without access to the %s directory (for temporary files).')
+ __(
+ 'Uploaded file cannot be moved, because the server has ' .
+ 'open_basedir enabled without access to the %s directory ' .
+ '(for temporary files).'
+ )
);
$message->addParam($tmp_subdir);
PMA_stopImport($message);
@@ -475,7 +493,11 @@ if ($import_file != 'none' && ! $error) {
$import_handle = @bzopen($import_file, 'r');
} else {
$message = PMA_Message::error(
- __('You attempted to load file with unsupported compression (%s). Either support for it is not implemented or disabled by your configuration.')
+ __(
+ 'You attempted to load file with unsupported compression ' .
+ '(%s). Either support for it is not implemented or disabled ' .
+ 'by your configuration.'
+ )
);
$message->addParam($compression);
PMA_stopImport($message);
@@ -486,7 +508,11 @@ if ($import_file != 'none' && ! $error) {
$import_handle = @gzopen($import_file, 'r');
} else {
$message = PMA_Message::error(
- __('You attempted to load file with unsupported compression (%s). Either support for it is not implemented or disabled by your configuration.')
+ __(
+ 'You attempted to load file with unsupported compression ' .
+ '(%s). Either support for it is not implemented or disabled ' .
+ 'by your configuration.'
+ )
);
$message->addParam($compression);
PMA_stopImport($message);
@@ -507,7 +533,11 @@ if ($import_file != 'none' && ! $error) {
}
} else {
$message = PMA_Message::error(
- __('You attempted to load file with unsupported compression (%s). Either support for it is not implemented or disabled by your configuration.')
+ __(
+ 'You attempted to load file with unsupported compression ' .
+ '(%s). Either support for it is not implemented or disabled ' .
+ 'by your configuration.'
+ )
);
$message->addParam($compression);
PMA_stopImport($message);
@@ -518,7 +548,11 @@ if ($import_file != 'none' && ! $error) {
break;
default:
$message = PMA_Message::error(
- __('You attempted to load file with unsupported compression (%s). Either support for it is not implemented or disabled by your configuration.')
+ __(
+ 'You attempted to load file with unsupported compression (%s). ' .
+ 'Either support for it is not implemented or disabled by your ' .
+ 'configuration.'
+ )
);
$message->addParam($compression);
PMA_stopImport($message);
@@ -532,7 +566,11 @@ if ($import_file != 'none' && ! $error) {
} elseif (! $error) {
if (! isset($import_text) || empty($import_text)) {
$message = PMA_Message::error(
- __('No data was received to import. Either no file name was submitted, or the file size exceeded the maximum size permitted by your PHP configuration. See [doc@faq1-16]FAQ 1.16[/doc].')
+ __(
+ 'No data was received to import. Either no file name was ' .
+ 'submitted, or the file size exceeded the maximum size permitted ' .
+ 'by your PHP configuration. See [doc@faq1-16]FAQ 1.16[/doc].'
+ )
);
PMA_stopImport($message);
}
@@ -565,9 +603,9 @@ if ($GLOBALS['PMA_recoding_engine'] != PMA_CHARSET_NONE && isset($charset_of_fil
}
}
-// Something to skip?
-if (! $error && isset($skip)) {
- $original_skip = $skip;
+// Something to skip? (because timeout has passed)
+if (! $error && isset($_POST['skip'])) {
+ $original_skip = $skip = $_POST['skip'];
while ($skip > 0) {
PMA_importGetNextChunk($skip < $read_limit ? $skip : $read_limit);
// Disable read progressivity, otherwise we eat all memory!
@@ -584,6 +622,7 @@ $sql_data = array('valid_sql' => array(), 'valid_queries' => 0);
if (! $error) {
// Check for file existence
include_once "libraries/plugin_interface.lib.php";
+ /* @var $import_plugin ImportPlugin */
$import_plugin = PMA_getPlugin(
"import",
$format,
@@ -597,7 +636,14 @@ if (! $error) {
PMA_stopImport($message);
} else {
// Do the real import
- $import_plugin->doImport($sql_data);
+ try {
+ $default_fk_check = PMA_Util::handleDisableFKCheckInit();
+ $import_plugin->doImport($sql_data);
+ PMA_Util::handleDisableFKCheckCleanup($default_fk_check);
+ } catch (Exception $e) {
+ PMA_Util::handleDisableFKCheckCleanup($default_fk_check);
+ throw $e;
+ }
}
}
@@ -628,7 +674,7 @@ if (! empty($id_bookmark) && $_REQUEST['action_bookmark'] == 2) {
} elseif ($bookmark_created) {
$special_message = '[br]' . sprintf(
__('Bookmark %s has been created.'),
- htmlspecialchars($bkm_label)
+ htmlspecialchars($_POST['bkm_label'])
);
} elseif ($finished && ! $error) {
if ($import_type == 'query') {
@@ -656,7 +702,9 @@ if (! empty($id_bookmark) && $_REQUEST['action_bookmark'] == 2) {
// Did we hit timeout? Tell it user.
if ($timeout_passed) {
- $importUrl = $err_url .= '&timeout_passed=1&offset=' . urlencode($GLOBALS['offset']);
+ $importUrl = $err_url .= '&timeout_passed=1&offset=' . urlencode(
+ $GLOBALS['offset']
+ );
if (isset($local_import_file)) {
$importUrl .= '&local_import_file=' . urlencode($local_import_file);
}
@@ -718,19 +766,27 @@ if ($go_sql) {
include 'libraries/parse_analyze.inc.php';
$html_output .= PMA_executeQueryAndGetQueryResponse(
- $analyzed_sql_results, false, $db, $table, null,
- $sql_query, null, $analyzed_sql_results['is_affected'],
- null, null, null, $goto, $pmaThemeImage,
- null, null, null, $sql_query, null, null
+ $analyzed_sql_results, // analyzed_sql_results
+ false, // is_gotofile
+ $db, // db
+ $table, // table
+ null, // find_real_end
+ $sql_query, // sql_query_for_bookmark
+ null, // extra_data
+ null, // message_to_show
+ null, // message
+ null, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ null, // disp_query
+ null, // disp_message
+ null, // query_type
+ $sql_query, // sql_query
+ null, // selectedTables
+ null // complete_query
);
}
- if (!isset($ajax_reload)) {
- $ajax_reload = array();
- }
- if (isset($table)) {
- $ajax_reload['table_name'] = $table;
- }
$response = PMA_Response::getInstance();
$response->addJSON('ajax_reload', $ajax_reload);
$response->addHTML($html_output);
@@ -767,4 +823,3 @@ if ($go_sql) {
if (isset($_REQUEST['rollback_query'])) {
$GLOBALS['dbi']->query('ROLLBACK');
}
-?>
diff --git a/import_status.php b/import_status.php
index 87c6132bef..c4b442f456 100644
--- a/import_status.php
+++ b/import_status.php
@@ -115,4 +115,3 @@ if (isset($_GET["message"]) && $_GET["message"]) {
} else {
PMA_importAjaxStatus($_GET["id"]);
}
-?>
diff --git a/index.php b/index.php
index 5d6cc37628..17b0e7aa21 100644
--- a/index.php
+++ b/index.php
@@ -15,6 +15,7 @@ require_once 'libraries/common.inc.php';
* display Git revision if requested
*/
require_once 'libraries/display_git_revision.lib.php';
+require_once 'libraries/Template.class.php';
/**
* pass variables to child pages
@@ -38,9 +39,9 @@ unset($drops, $each_drop);
* Such scripts must not be loaded on home page.
*
*/
- $target_blacklist = array (
+$target_blacklist = array (
'import.php', 'export.php'
- );
+);
// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
@@ -61,9 +62,13 @@ if (isset($_REQUEST['ajax_request']) && ! empty($_REQUEST['access_time'])) {
if (! empty($_REQUEST['db'])) {
$page = null;
if (! empty($_REQUEST['table'])) {
- $page = $GLOBALS['cfg']['DefaultTabTable'];
+ $page = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ );
} else {
- $page = $GLOBALS['cfg']['DefaultTabDatabase'];
+ $page = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ );
}
include $page;
exit;
@@ -155,7 +160,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
echo '</div>';
}
echo '<div class="group">';
- echo '<h2>' . __('General Settings') . '</h2>';
+ echo '<h2>' . __('General settings') . '</h2>';
echo '<ul>';
/**
@@ -183,7 +188,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
if ($cfg['ShowChgPassword']) {
$conditional_class = 'ajax';
PMA_printListItem(
- PMA_Util::getImage('s_passwd.png') . " " . __('Change password'),
+ PMA_Util::getImage('s_passwd.png') . "&nbsp;" . __('Change password'),
'li_change_password',
'user_password.php' . $common_url_query,
null,
@@ -198,7 +203,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
echo ' <form method="post" action="index.php">' . "\n"
. PMA_URL_getHiddenInputs(null, null, 4, 'collation_connection')
. ' <label for="select_collation_connection">' . "\n"
- . ' ' . PMA_Util::getImage('s_asci.png') . " "
+ . ' ' . PMA_Util::getImage('s_asci.png') . "&nbsp;"
. __('Server connection collation') . "\n"
// put the doc link in the form so that it appears on the same line
. PMA_Util::showMySQLDocu('Charset-connection')
@@ -221,7 +226,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
}
echo '<div class="group">';
-echo '<h2>' . __('Appearance Settings') . '</h2>';
+echo '<h2>' . __('Appearance settings') . '</h2>';
echo ' <ul>';
// Displays language selection combo
@@ -251,7 +256,7 @@ echo '</ul>';
if ($server > 0) {
echo '<ul>';
PMA_printListItem(
- PMA_Util::getImage('b_tblops.png') . " " . __('More settings'),
+ PMA_Util::getImage('b_tblops.png') . "&nbsp;" . __('More settings'),
'li_user_preferences',
'prefs_manage.php' . $common_url_query,
null,
@@ -492,7 +497,13 @@ if ($cfg['LoginCookieValidityDisableWarning'] == false) {
$gc_time = (int)@ini_get('session.gc_maxlifetime');
if ($gc_time < $GLOBALS['cfg']['LoginCookieValidity'] ) {
trigger_error(
- __('Your PHP parameter [a@http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime@_blank]session.gc_maxlifetime[/a] is lower than cookie validity configured in phpMyAdmin, because of this, your login might expire sooner than configured in phpMyAdmin.'),
+ __(
+ 'Your PHP parameter [a@http://php.net/manual/en/session.' .
+ 'configuration.php#ini.session.gc-maxlifetime@_blank]session.' .
+ 'gc_maxlifetime[/a] is lower than cookie validity configured ' .
+ 'in phpMyAdmin, because of this, your login might expire sooner ' .
+ 'than configured in phpMyAdmin.'
+ ),
E_USER_WARNING
);
}
@@ -505,7 +516,11 @@ if ($GLOBALS['cfg']['LoginCookieStore'] != 0
&& $GLOBALS['cfg']['LoginCookieStore'] < $GLOBALS['cfg']['LoginCookieValidity']
) {
trigger_error(
- __('Login cookie store is lower than cookie validity configured in phpMyAdmin, because of this, your login will expire sooner than configured in phpMyAdmin.'),
+ __(
+ 'Login cookie store is lower than cookie validity configured in ' .
+ 'phpMyAdmin, because of this, your login will expire sooner than ' .
+ 'configured in phpMyAdmin.'
+ ),
E_USER_WARNING
);
}
@@ -517,7 +532,9 @@ if (! empty($_SESSION['encryption_key'])
&& empty($GLOBALS['cfg']['blowfish_secret'])
) {
trigger_error(
- __('The configuration file now needs a secret passphrase (blowfish_secret).'),
+ __(
+ 'The configuration file now needs a secret passphrase (blowfish_secret).'
+ ),
E_USER_WARNING
);
}
@@ -528,7 +545,13 @@ if (! empty($_SESSION['encryption_key'])
*/
if (file_exists('config')) {
trigger_error(
- __('Directory [code]config[/code], which is used by the setup script, still exists in your phpMyAdmin directory. It is strongly recommended to remove it once phpMyAdmin has been configured. Otherwise the security of your server may be compromised by unauthorized people downloading your configuration.'),
+ __(
+ 'Directory [code]config[/code], which is used by the setup script, ' .
+ 'still exists in your phpMyAdmin directory. It is strongly ' .
+ 'recommended to remove it once phpMyAdmin has been configured. ' .
+ 'Otherwise the security of your server may be compromised by ' .
+ 'unauthorized people downloading your configuration.'
+ ),
E_USER_WARNING
);
}
@@ -594,7 +617,11 @@ if (isset($GLOBALS['dbi'])
trigger_error(
PMA_sanitize(
sprintf(
- __('Your PHP MySQL library version %s differs from your MySQL server version %s. This may cause unpredictable behavior.'),
+ __(
+ 'Your PHP MySQL library version %s differs from your ' .
+ 'MySQL server version %s. This may cause unpredictable ' .
+ 'behavior.'
+ ),
$_client_info,
substr(
PMA_MYSQL_STR_VERSION,
@@ -618,7 +645,10 @@ if ($cfg['SuhosinDisableWarning'] == false
) {
trigger_error(
sprintf(
- __('Server running with Suhosin. Please refer to %sdocumentation%s for possible issues.'),
+ __(
+ 'Server running with Suhosin. Please refer to %sdocumentation%s ' .
+ 'for possible issues.'
+ ),
'[doc@faq1-38]',
'[/doc]'
),
@@ -669,33 +699,19 @@ function PMA_printListItem($name, $listId = null, $url = null,
$mysql_help_page = null, $target = null, $a_id = null, $class = null,
$a_class = null
) {
- echo '<li id="' . $listId . '"';
- if (null !== $class) {
- echo ' class="' . $class . '"';
- }
- echo '>';
- if (null !== $url) {
- echo '<a href="' . $url . '"';
- if (null !== $target) {
- echo ' target="' . $target . '"';
- }
- if (null != $a_id) {
- echo ' id="' . $a_id . '"';
- }
- if (null != $a_class) {
- echo ' class="' . $a_class . '"';
- }
- echo '>';
- }
-
- echo $name;
-
- if (null !== $url) {
- echo '</a>' . "\n";
- }
- if (null !== $mysql_help_page) {
- echo PMA_Util::showMySQLDocu($mysql_help_page);
- }
- echo '</li>';
+ echo PMA\Template::get('list/item')
+ ->render(
+ array(
+ 'content' => $name,
+ 'id' => $listId,
+ 'class' => $class,
+ 'url' => array(
+ 'href' => $url,
+ 'target' => $target,
+ 'id' => $a_id,
+ 'class' => $a_class,
+ ),
+ 'mysql_help_page' => $mysql_help_page,
+ )
+ );
}
-?>
diff --git a/js/ajax.js b/js/ajax.js
index 9882439f5d..3800c0d1b4 100644
--- a/js/ajax.js
+++ b/js/ajax.js
@@ -153,7 +153,12 @@ var AJAX = {
* @todo Fix Code mirror does not give correct full value (query)
* in textarea, it returns only the change in content.
*/
- var newHash = AJAX.hash($(this).val());
+ var newHash = null;
+ if (event.data.value == 1) {
+ newHash = AJAX.hash($(this).val());
+ } else {
+ newHash = AJAX.hash($(this).is(":checked"));
+ }
var oldHash = $(this).data('val-hash');
// Set lock if old value != new value
// otherwise release lock
@@ -179,6 +184,15 @@ var AJAX = {
AJAX.lockedTargets = {};
$('#lock_page_icon').html('');
},
+ handleMenu: {
+ replace: function (content) {
+ $('#floating_menubar').html(content)
+ // Remove duplicate wrapper
+ // TODO: don't send it in the response
+ .children().first().remove();
+ $('#topmenu').menuResizer(PMA_mainMenuResizerCallback);
+ }
+ },
/**
* Event handler for clicks on links and form submissions
*
@@ -226,6 +240,8 @@ var AJAX = {
return false;
}
AJAX.resetLock();
+ var isLink = !! href || false;
+ var previousLinkAborted = false;
if (AJAX.active === true) {
// Cancel the old request if abortable, when the user requests
@@ -239,6 +255,7 @@ var AJAX = {
AJAX.$msgbox = PMA_ajaxShowMessage(PMA_messages.strAbortedRequest);
AJAX.active = false;
AJAX.xhr = null;
+ previousLinkAborted = true;
} else {
//If can't abort
return false;
@@ -253,14 +270,15 @@ var AJAX = {
$('html, body').animate({scrollTop: 0}, 'fast');
- var isLink = !! href || false;
var url = isLink ? href : $(this).attr('action');
var params = 'ajax_request=true&ajax_page_request=true';
if (! isLink) {
params += '&' + $(this).serialize();
}
- // Add a list of menu hashes that we have in the cache to the request
- params += AJAX.cache.menus.getRequestParam();
+ if (! (history && history.pushState)) {
+ // Add a list of menu hashes that we have in the cache to the request
+ params += PMA_MicroHistory.menus.getRequestParam();
+ }
if (AJAX._debug) {
console.log("Loading: " + url); // no need to translate
@@ -271,6 +289,18 @@ var AJAX = {
AJAX.$msgbox = PMA_ajaxShowMessage();
//Save reference for the new link request
AJAX.xhr = $.get(url, params, AJAX.responseHandler);
+ if (history && history.pushState) {
+ var state = {
+ url : href
+ };
+ if (previousLinkAborted) {
+ //hack: there is already an aborted entry on stack
+ //so just modify the aborted one
+ history.replaceState(state, null, href);
+ } else {
+ history.pushState(state, null, href);
+ }
+ }
} else {
/**
* Manually fire the onsubmit event for the form, if any.
@@ -305,7 +335,6 @@ var AJAX = {
return;
}
if (typeof data.success != 'undefined' && data.success) {
- $table_clone = false;
$('html, body').animate({scrollTop: 0}, 'fast');
PMA_ajaxRemoveMessage(AJAX.$msgbox);
@@ -324,10 +353,27 @@ var AJAX = {
$('title').replaceWith(data._title);
}
if (data._menu) {
- AJAX.cache.menus.replace(data._menu);
- AJAX.cache.menus.add(data._menuHash, data._menu);
+ if (history && history.pushState) {
+ var state = {
+ url : data._selflink,
+ menu : data._menu
+ };
+ history.replaceState(state, null);
+ AJAX.handleMenu.replace(data._menu);
+ } else {
+ PMA_MicroHistory.menus.replace(data._menu);
+ PMA_MicroHistory.menus.add(data._menuHash, data._menu);
+ }
} else if (data._menuHash) {
- AJAX.cache.menus.replace(AJAX.cache.menus.get(data._menuHash));
+ if (! (history && history.pushState)) {
+ PMA_MicroHistory.menus.replace(PMA_MicroHistory.menus.get(data._menuHash));
+ }
+ }
+ if (data._disableNaviSettings) {
+ PMA_disableNaviSettings();
+ }
+ else {
+ PMA_ensureNaviSettings(data._selflink);
}
// Remove all containers that may have
@@ -335,15 +381,14 @@ var AJAX = {
$('body').children()
.not('#pma_navigation')
.not('#floating_menubar')
- .not('#goto_pagetop')
- .not('#lock_page_icon')
+ .not('#page_nav_icons')
.not('#page_content')
.not('#selflink')
- .not('#session_debug')
.not('#pma_header')
.not('#pma_footer')
.not('#pma_demo')
.not('#pma_console_container')
+ .not('#prefs_autoload')
.remove();
// Replace #page_content with new content
if (data.message && data.message.length > 0) {
@@ -355,29 +400,35 @@ var AJAX = {
}
if (data._selflink) {
-
var source = data._selflink.split('?')[0];
//Check for faulty links
- if (source == "import.php") {
- var replacement = "tbl_sql.php";
- data._selflink = data._selflink.replace(source,replacement);
+ $selflink_replace = {
+ "import.php": "tbl_sql.php",
+ "tbl_chart.php": "sql.php",
+ "tbl_gis_visualization.php": "sql.php"
+ };
+ if ($selflink_replace[source]) {
+ var replacement = $selflink_replace[source];
+ data._selflink = data._selflink.replace(source, replacement);
}
- $('#selflink > a').attr('href', data._selflink);
+ $('#selflink').find('> a').attr('href', data._selflink);
+ }
+ if (data._params) {
+ PMA_commonParams.setAll(data._params);
}
if (data._scripts) {
AJAX.scriptHandler.load(data._scripts);
}
if (data._selflink && data._scripts && data._menuHash && data._params) {
- AJAX.cache.add(
- data._selflink,
- data._scripts,
- data._menuHash,
- data._params,
- AJAX.source.attr('rel')
- );
- }
- if (data._params) {
- PMA_commonParams.setAll(data._params);
+ if (! (history && history.pushState)) {
+ PMA_MicroHistory.add(
+ data._selflink,
+ data._scripts,
+ data._menuHash,
+ data._params,
+ AJAX.source.attr('rel')
+ );
+ }
}
if (data._displayMessage) {
$('#page_content').prepend(data._displayMessage);
@@ -390,18 +441,17 @@ var AJAX = {
if(data._errSubmitMsg){
msg = data._errSubmitMsg;
}
- if (data._debug) {
- $('#session_debug').replaceWith(data._debug);
- }
if (data._errors) {
$('<div/>', {id : 'pma_errors'})
.insertAfter('#selflink')
.append(data._errors);
// bind for php error reporting forms (bottom)
- $("#pma_ignore_errors_bottom").bind("click", function() {
+ $("#pma_ignore_errors_bottom").bind("click", function(e) {
+ e.preventDefault();
PMA_ignorePhpErrors();
});
- $("#pma_ignore_all_errors_bottom").bind("click", function() {
+ $("#pma_ignore_all_errors_bottom").bind("click", function(e) {
+ e.preventDefault();
PMA_ignorePhpErrors(false);
});
// In case of 'sendErrorReport'='always'
@@ -433,6 +483,7 @@ var AJAX = {
}
AJAX._callback = function () {};
});
+
} else {
PMA_ajaxShowMessage(data.error, false);
AJAX.active = false;
@@ -463,6 +514,11 @@ var AJAX = {
*/
_scripts: [],
/**
+ * @var string _scriptsVersion version of phpMyAdmin from which the
+ * scripts have been loaded
+ */
+ _scriptsVersion: null,
+ /**
* @var array _scriptsToBeLoaded The list of files that
* need to be downloaded
*/
@@ -497,8 +553,16 @@ var AJAX = {
*
* @return void
*/
- load: function (files) {
+ load: function (files, callback) {
var self = this;
+ // Clear loaded scripts if they are from another version of phpMyAdmin.
+ // Depends on common params being set before loading scripts in responseHandler
+ if (self._scriptsVersion == null) {
+ self._scriptsVersion = PMA_commonParams.get('PMA_VERSION');
+ } else if (self._scriptsVersion != PMA_commonParams.get('PMA_VERSION')) {
+ self._scripts = [];
+ self._scriptsVersion = PMA_commonParams.get('PMA_VERSION');
+ }
self._scriptsToBeLoaded = [];
self._scriptsToBeFired = [];
for (var i in files) {
@@ -520,11 +584,12 @@ var AJAX = {
}
}
request.push("call_done=1");
+ request.push("v=" + encodeURIComponent(PMA_commonParams.get('PMA_VERSION')));
// Download the composite js file, if necessary
if (needRequest) {
this.appendScript("js/get_scripts.js.php?" + request.join("&"));
} else {
- self.done();
+ self.done(callback);
}
},
/**
@@ -532,7 +597,10 @@ var AJAX = {
*
* @return void
*/
- done: function () {
+ done: function (callback) {
+ if($.isFunction(callback)) {
+ callback();
+ }
if (typeof ErrorReport !== 'undefined') {
ErrorReport.wrap_global_functions();
}
@@ -573,7 +641,9 @@ var AJAX = {
*/
$(document).off('click', 'a').on('click', 'a', AJAX.requestHandler);
$(document).off('submit', 'form').on('submit', 'form', AJAX.requestHandler);
- AJAX.cache.update();
+ if (! (history && history.pushState)) {
+ PMA_MicroHistory.update();
+ }
callback();
}
}
@@ -596,11 +666,12 @@ AJAX.registerOnload('functions.js', function () {
}
});
+ var $page_content = $('#page_content');
/**
* Workaround for passing submit button name,value on ajax form submit
* by appending hidden element with submit button name and value.
*/
- $("#page_content").on('click', 'form input[type=submit]', function() {
+ $page_content.on('click', 'form input[type=submit]', function() {
var buttonName = $(this).attr('name');
if (typeof buttonName === 'undefined') {
return;
@@ -614,12 +685,22 @@ AJAX.registerOnload('functions.js', function () {
/**
* Attach event listener to events when user modify visible
- * Input or Textarea fields to make changes in forms
+ * Input,Textarea and select fields to make changes in forms
*/
- $('#page_content').on(
+ $page_content.on(
'keyup change',
'form.lock-page textarea, ' +
- 'form.lock-page input[type="text"]',
+ 'form.lock-page input[type="text"], ' +
+ 'form.lock-page input[type="number"], ' +
+ 'form.lock-page select',
+ {value:1},
+ AJAX.lockPageHandler
+ );
+ $page_content.on(
+ 'change',
+ 'form.lock-page input[type="checkbox"], ' +
+ 'form.lock-page input[type="radio"]',
+ {value:2},
AJAX.lockPageHandler
);
/**
@@ -633,374 +714,67 @@ AJAX.registerOnload('functions.js', function () {
});
/**
- * Unbind all event handlers before tearing down a page
- */
-AJAX.registerTeardown('functions.js', function () {
- $('#page_content').off('keyup change',
- 'form.lock-page textarea, ' +
- 'form.lock-page input[type="text"]'
- );
- $('form.lock-page').off('reset');
-});
-
-/**
- * An implementation of a client-side page cache.
- * This object also uses the cache to provide a simple microhistory,
- * that is the ability to use the back and forward buttons in the browser
- */
-AJAX.cache = {
- /**
- * @var int The maximum number of pages to keep in the cache
- */
- MAX: 6,
- /**
- * @var object A hash used to prime the cache with data about the initially
- * loaded page. This is set in the footer, and then loaded
- * by a double-queued event further down this file.
- */
- primer: {},
- /**
- * @var array Stores the content of the cached pages
- */
- pages: [],
- /**
- * @var int The index of the currently loaded page
- * This is used to know at which point in the history we are
- */
- current: 0,
- /**
- * Saves a new page in the cache
- *
- * @param string hash The hash part of the url that is being loaded
- * @param array scripts A list of scripts that is required for the page
- * @param string menu A hash that links to a menu stored
- * in a dedicated menu cache
- * @param array params A list of parameters used by PMA_commonParams()
- * @param string rel A relationship to the current page:
- * 'samepage': Forces the response to be treated as
- * the same page as the current one
- * 'newpage': Forces the response to be treated as
- * a new page
- * undefined: Default behaviour, 'samepage' if the
- * selflinks of the two pages are the same.
- * 'newpage' otherwise
- *
- * @return void
- */
- add: function (hash, scripts, menu, params, rel) {
- if (this.pages.length > AJAX.cache.MAX) {
- // Trim the cache, to the maximum number of allowed entries
- // This way we will have a cached menu for every page
- for (var i = 0; i < this.pages.length - this.MAX; i++) {
- delete this.pages[i];
- }
- }
- while (this.current < this.pages.length) {
- // trim the cache if we went back in the history
- // and are now going forward again
- this.pages.pop();
- }
- if (rel === 'newpage' ||
- (
- typeof rel === 'undefined' && (
- typeof this.pages[this.current - 1] === 'undefined' ||
- this.pages[this.current - 1].hash !== hash
- )
- )
- ) {
- this.pages.push({
- hash: hash,
- content: $('#page_content').html(),
- scripts: scripts,
- selflink: $('#selflink').html(),
- menu: menu,
- params: params
- });
- AJAX.setUrlHash(this.current, hash);
- this.current++;
- }
- },
- /**
- * Restores a page from the cache. This is called when the hash
- * part of the url changes and it's structure appears to be valid
- *
- * @param string index Which page from the history to load
- *
- * @return void
- */
- navigate: function (index) {
- if (typeof this.pages[index] === 'undefined' ||
- typeof this.pages[index].content === 'undefined' ||
- typeof this.pages[index].menu === 'undefined' ||
- ! AJAX.cache.menus.get(this.pages[index].menu)
- ) {
- PMA_ajaxShowMessage(
- '<div class="error">' + PMA_messages.strInvalidPage + '</div>',
- false
- );
- } else {
- AJAX.active = true;
- var record = this.pages[index];
- AJAX.scriptHandler.reset(function () {
- $('#page_content').html(record.content);
- $('#selflink').html(record.selflink);
- AJAX.cache.menus.replace(AJAX.cache.menus.get(record.menu));
- PMA_commonParams.setAll(record.params);
- AJAX.scriptHandler.load(record.scripts);
- AJAX.cache.current = ++index;
- });
- }
- },
- /**
- * Resaves the content of the current page in the cache.
- * Necessary in order not to show the user some outdated version of the page
- *
- * @return void
- */
- update: function () {
- var page = this.pages[this.current - 1];
- if (page) {
- page.content = $('#page_content').html();
- }
- },
- /**
- * @var object Dedicated menu cache
- */
- menus: {
- /**
- * Returns the number of items in an associative array
- *
- * @return int
- */
- size: function (obj) {
- var size = 0, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- size++;
- }
- }
- return size;
- },
- /**
- * @var hash Stores the content of the cached menus
- */
- data: {},
- /**
- * Saves a new menu in the cache
- *
- * @param string hash The hash (trimmed md5) of the menu to be saved
- * @param string content The HTML code of the menu to be saved
- *
- * @return void
- */
- add: function (hash, content) {
- if (this.size(this.data) > AJAX.cache.MAX) {
- // when the cache grows, we remove the oldest entry
- var oldest, key, init = 0;
- for (var i in this.data) {
- if (this.data[i]) {
- if (! init || this.data[i].timestamp.getTime() < oldest.getTime()) {
- oldest = this.data[i].timestamp;
- key = i;
- init = 1;
- }
- }
- }
- delete this.data[key];
- }
- this.data[hash] = {
- content: content,
- timestamp: new Date()
- };
- },
- /**
- * Retrieves a menu given its hash
- *
- * @param string hash The hash of the menu to be retrieved
- *
- * @return string
- */
- get: function (hash) {
- if (this.data[hash]) {
- return this.data[hash].content;
- } else {
- // This should never happen as long as the number of stored menus
- // is larger or equal to the number of pages in the page cache
- return '';
- }
- },
- /**
- * Prepares part of the parameter string used during page requests,
- * this is necessary to tell the server which menus we have in the cache
- *
- * @return string
- */
- getRequestParam: function () {
- var param = '';
- var menuHashes = [];
- for (var i in this.data) {
- menuHashes.push(i);
- }
- var menuHashesParam = menuHashes.join('-');
- if (menuHashesParam) {
- param = '&menuHashes=' + menuHashesParam;
- }
- return param;
- },
- /**
- * Replaces the menu with new content
- *
- * @return void
- */
- replace: function (content) {
- $('#floating_menubar').html(content)
- // Remove duplicate wrapper
- // TODO: don't send it in the response
- .children().first().remove();
- $('#topmenu').menuResizer(PMA_mainMenuResizerCallback);
- }
- }
-};
-
-/**
- * URL hash management module.
- * Allows direct bookmarking and microhistory.
+ * Page load event handler
*/
-AJAX.setUrlHash = (function (jQuery, window) {
- "use strict";
- /**
- * Indictaes whether we have already completed
- * the initialisation of the hash
- *
- * @access private
- */
- var ready = false;
- /**
- * Stores a hash that needed to be set when we were not ready
- *
- * @access private
- */
- var savedHash = "";
- /**
- * Flag to indicate if the change of hash was triggered
- * by a user pressing the back/forward button or if
- * the change was triggered internally
- *
- * @access private
- */
- var userChange = true;
-
- // Fix favicon disappearing in Firefox when setting location.hash
- function resetFavicon() {
- if (navigator.userAgent.indexOf('Firefox') > -1) {
- // Move the link tags for the favicon to the bottom
- // of the head element to force a reload of the favicon
- $('head > link[href=favicon\\.ico]').appendTo('head');
- }
- }
-
- /**
- * Sets the hash part of the URL
- *
- * @access public
- */
- function setUrlHash(index, hash) {
- /*
- * Known problem:
- * Setting hash leads to reload in webkit:
- * http://www.quirksmode.org/bugreports/archives/2005/05/Safari_13_visual_anomaly_with_windowlocationhref.html
- *
- * so we expect that users are not running an ancient Safari version
- */
+$(function () {
+ var menuContent = $('<div></div>')
+ .append($('#serverinfo').clone())
+ .append($('#topmenucontainer').clone())
+ .html();
+ if (history && history.pushState) {
+ //set initial state reload
+ var initState = ('state' in window.history && window.history.state !== null);
+ var initURL = $('#selflink').find('> a').attr('href') || location.href;
+ var state = {
+ url : initURL,
+ menu : menuContent
+ };
+ history.replaceState(state, null);
- userChange = false;
- if (ready) {
- window.location.hash = "PMAURL-" + index + ":" + hash;
- resetFavicon();
- } else {
- savedHash = "PMAURL-" + index + ":" + hash;
- }
- }
- /**
- * Start initialisation
- */
- if (window.location.hash.substring(0, 8) == '#PMAURL-') {
- // We have a valid hash, let's redirect the user
- // to the page that it's pointing to
- var colon_position = window.location.hash.indexOf(':');
- var questionmark_position = window.location.hash.indexOf('?');
- if (colon_position != -1 && questionmark_position != -1 && colon_position < questionmark_position) {
- var hash_url = window.location.hash.substring(colon_position + 1, questionmark_position);
- if (PMA_gotoWhitelist.indexOf(hash_url) != -1) {
- window.location = window.location.hash.substring(
- colon_position + 1
- );
- }
- }
- } else {
- // We don't have a valid hash, so we'll set it up
- // when the page finishes loading
- jQuery(function () {
- /* Check if we should set URL */
- if (savedHash !== "") {
- window.location.hash = savedHash;
- savedHash = "";
- resetFavicon();
+ $(window).on('popstate', function(event) {
+ var initPop = (! initState && location.href == initURL);
+ initState = true;
+ //check if popstate fired on first page itself
+ if (initPop) {
+ return;
}
- // Indicate that we're done initialising
- ready = true;
- });
- }
- /**
- * Register an event handler for when the url hash changes
- */
- jQuery(function () {
- jQuery(window).hashchange(function () {
- if (userChange === false) {
- // Ignore internally triggered hash changes
- userChange = true;
- } else if (/^#PMAURL-\d+:/.test(window.location.hash)) {
- // Change page if the hash changed was triggered by a user action
- var index = window.location.hash.substring(
- 8, window.location.hash.indexOf(':')
- );
- AJAX.cache.navigate(index);
+ var state = event.originalEvent.state;
+ if (state && state.menu) {
+ AJAX.$msgbox = PMA_ajaxShowMessage();
+ var params = 'ajax_request=true&ajax_page_request=true';
+ var url = state.url || location.href;
+ $.get(url, params, AJAX.responseHandler);
+ //TODO: Check if sometimes menu is not retrieved from server,
+ // Not sure but it seems menu was missing only for printview which
+ // been removed lately, so if it's right some dead menu checks/fallbacks
+ // may need to be removed from this file and Header.class.php
+ //AJAX.handleMenu.replace(event.originalEvent.state.menu);
}
});
- });
- /**
- * Publicly exposes a reference to the otherwise private setUrlHash function
- */
- return setUrlHash;
-})(jQuery, window);
-
-/**
- * Page load event handler
- */
-$(function () {
- // Add the menu from the initial page into the cache
- // The cache primer is set by the footer class
- if (AJAX.cache.primer.url) {
- AJAX.cache.menus.add(
- AJAX.cache.primer.menuHash,
- $('<div></div>')
- .append('<div></div>')
- .append($('#serverinfo').clone())
- .append($('#topmenucontainer').clone())
- .html()
- );
+ } else {
+ // Fallback to microhistory mechanism
+ AJAX.scriptHandler
+ .load([{'name' : 'microhistory.js', 'fire' : 1}], function () {
+ // The cache primer is set by the footer class
+ if (PMA_MicroHistory.primer.url) {
+ PMA_MicroHistory.menus.add(
+ PMA_MicroHistory.primer.menuHash,
+ menuContent
+ );
+ }
+ $(function () {
+ // Queue up this event twice to make sure that we get a copy
+ // of the page after all other onload events have been fired
+ if (PMA_MicroHistory.primer.url) {
+ PMA_MicroHistory.add(
+ PMA_MicroHistory.primer.url,
+ PMA_MicroHistory.primer.scripts,
+ PMA_MicroHistory.primer.menuHash
+ );
+ }
+ });
+ });
}
- $(function () {
- // Queue up this event twice to make sure that we get a copy
- // of the page after all other onload events have been fired
- if (AJAX.cache.primer.url) {
- AJAX.cache.add(
- AJAX.cache.primer.url,
- AJAX.cache.primer.scripts,
- AJAX.cache.primer.menuHash
- );
- }
- });
});
/**
diff --git a/js/codemirror/LICENSE b/js/codemirror/LICENSE
index d21bbea5a6..f4a5a4a25f 100644
--- a/js/codemirror/LICENSE
+++ b/js/codemirror/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
+Copyright (C) 2015 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/js/codemirror/addon/hint/show-hint.css b/js/codemirror/addon/hint/show-hint.css
new file mode 100644
index 0000000000..924e638f7f
--- /dev/null
+++ b/js/codemirror/addon/hint/show-hint.css
@@ -0,0 +1,38 @@
+.CodeMirror-hints {
+ position: absolute;
+ z-index: 10;
+ overflow: hidden;
+ list-style: none;
+
+ margin: 0;
+ padding: 2px;
+
+ -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+ -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+ box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+ border-radius: 3px;
+ border: 1px solid silver;
+
+ background: white;
+ font-size: 90%;
+ font-family: monospace;
+
+ max-height: 20em;
+ overflow-y: auto;
+}
+
+.CodeMirror-hint {
+ margin: 0;
+ padding: 0 4px;
+ border-radius: 2px;
+ max-width: 19em;
+ overflow: hidden;
+ white-space: pre;
+ color: black;
+ cursor: pointer;
+}
+
+li.CodeMirror-hint-active {
+ background: #08f;
+ color: white;
+}
diff --git a/js/codemirror/addon/hint/show-hint.js b/js/codemirror/addon/hint/show-hint.js
index f544619428..d228fc8890 100644
--- a/js/codemirror/addon/hint/show-hint.js
+++ b/js/codemirror/addon/hint/show-hint.js
@@ -24,44 +24,45 @@
return cm.showHint(newOpts);
};
- var asyncRunID = 0;
- function retrieveHints(getter, cm, options, then) {
- if (getter.async) {
- var id = ++asyncRunID;
- getter(cm, function(hints) {
- if (asyncRunID == id) then(hints);
- }, options);
- } else {
- then(getter(cm, options));
- }
- }
-
CodeMirror.defineExtension("showHint", function(options) {
// We want a single cursor position.
if (this.listSelections().length > 1 || this.somethingSelected()) return;
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
- var getHints = completion.options.hint;
- if (!getHints) return;
+ if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
- return retrieveHints(getHints, this, completion.options, function(hints) { completion.showHints(hints); });
+ completion.update(true);
});
function Completion(cm, options) {
this.cm = cm;
this.options = this.buildOptions(options);
- this.widget = this.onClose = null;
+ this.widget = null;
+ this.debounce = 0;
+ this.tick = 0;
+ this.startPos = this.cm.getCursor();
+ this.startLen = this.cm.getLine(this.startPos.line).length;
+
+ var self = this;
+ cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
}
+ var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
+ return setTimeout(fn, 1000/60);
+ };
+ var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
+
Completion.prototype = {
close: function() {
if (!this.active()) return;
this.cm.state.completionActive = null;
+ this.tick = null;
+ this.cm.off("cursorActivity", this.activityFunc);
+ if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
- if (this.onClose) this.onClose();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
@@ -78,70 +79,50 @@
this.close();
},
- showHints: function(data) {
- if (!data || !data.list.length || !this.active()) return this.close();
-
- if (this.options.completeSingle && data.list.length == 1)
- this.pick(data, 0);
- else
- this.showWidget(data);
- },
-
- showWidget: function(data) {
- this.widget = new Widget(this, data);
- CodeMirror.signal(data, "shown");
-
- var debounce = 0, completion = this, finished;
- var closeOn = this.options.closeCharacters;
- var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
-
- var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
- return setTimeout(fn, 1000/60);
- };
- var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
-
- function done() {
- if (finished) return;
- finished = true;
- completion.close();
- completion.cm.off("cursorActivity", activity);
- if (data) CodeMirror.signal(data, "close");
+ cursorActivity: function() {
+ if (this.debounce) {
+ cancelAnimationFrame(this.debounce);
+ this.debounce = 0;
}
- function update() {
- if (finished) return;
- CodeMirror.signal(data, "update");
- retrieveHints(completion.options.hint, completion.cm, completion.options, finishUpdate);
- }
- function finishUpdate(data_) {
- data = data_;
- if (finished) return;
- if (!data || !data.list.length) return done();
- if (completion.widget) completion.widget.close();
- completion.widget = new Widget(completion, data);
+ var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
+ if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
+ pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
+ (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
+ this.close();
+ } else {
+ var self = this;
+ this.debounce = requestAnimationFrame(function() {self.update();});
+ if (this.widget) this.widget.disable();
}
+ },
- function clearDebounce() {
- if (debounce) {
- cancelAnimationFrame(debounce);
- debounce = 0;
- }
+ update: function(first) {
+ if (this.tick == null) return;
+ if (this.data) CodeMirror.signal(this.data, "update");
+ if (!this.options.hint.async) {
+ this.finishUpdate(this.options.hint(this.cm, this.options), first);
+ } else {
+ var myTick = ++this.tick, self = this;
+ this.options.hint(this.cm, function(data) {
+ if (self.tick == myTick) self.finishUpdate(data, first);
+ }, this.options);
}
+ },
+
+ finishUpdate: function(data, first) {
+ this.data = data;
- function activity() {
- clearDebounce();
- var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
- if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
- pos.ch < startPos.ch || completion.cm.somethingSelected() ||
- (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
- completion.close();
+ var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
+ if (this.widget) this.widget.close();
+ if (data && data.list.length) {
+ if (picked && data.list.length == 1) {
+ this.pick(data, 0);
} else {
- debounce = requestAnimationFrame(update);
- if (completion.widget) completion.widget.close();
+ this.widget = new Widget(this, data);
+ CodeMirror.signal(data, "shown");
}
}
- this.cm.on("cursorActivity", activity);
- this.onClose = done;
},
buildOptions: function(options) {
@@ -206,6 +187,7 @@
function Widget(completion, data) {
this.completion = completion;
this.data = data;
+ this.picked = false;
var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul");
@@ -320,6 +302,13 @@
cm.off("scroll", this.onScroll);
},
+ disable: function() {
+ this.completion.cm.removeKeyMap(this.keyMap);
+ var widget = this;
+ this.keyMap = {Enter: function() { widget.picked = true; }};
+ this.completion.cm.addKeyMap(this.keyMap);
+ },
+
pick: function() {
this.completion.pick(this.data, this.selectedHint);
},
diff --git a/js/codemirror/addon/hint/sql-hint.js b/js/codemirror/addon/hint/sql-hint.js
index 37937ca9a2..22124b58f7 100644
--- a/js/codemirror/addon/hint/sql-hint.js
+++ b/js/codemirror/addon/hint/sql-hint.js
@@ -52,12 +52,9 @@
function addMatches(result, search, wordlist, formatter) {
for (var word in wordlist) {
if (!wordlist.hasOwnProperty(word)) continue;
- if (Array.isArray(wordlist)) {
- word = wordlist[word];
- }
- if (match(search, word)) {
- result.push(formatter(word));
- }
+ if (wordlist.slice) word = wordlist[word];
+
+ if (match(search, word)) result.push(formatter(word));
}
}
@@ -115,21 +112,28 @@
string = nameParts.pop();
var table = nameParts.join(".");
+ var alias = false;
+ var aliasTable = table;
// Check if table is available. If not, find table by Alias
- if (!getItem(tables, table))
+ if (!getItem(tables, table)) {
+ var oldTable = table;
table = findTableByAlias(table, editor);
+ if (table !== oldTable) alias = true;
+ }
var columns = getItem(tables, table);
- if (columns && Array.isArray(tables) && columns.columns)
+ if (columns && columns.columns)
columns = columns.columns;
if (columns) {
addMatches(result, string, columns, function(w) {
+ var tableInsert = table;
+ if (alias == true) tableInsert = aliasTable;
if (typeof w == "string") {
- w = table + "." + w;
+ w = tableInsert + "." + w;
} else {
w = shallowClone(w);
- w.text = table + "." + w.text;
+ w.text = tableInsert + "." + w.text;
}
return useBacktick ? insertBackticks(w) : w;
});
@@ -208,6 +212,7 @@
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
tables = (options && options.tables) || {};
var defaultTableName = options && options.defaultTable;
+ var disableKeywords = options && options.disableKeywords;
defaultTable = defaultTableName && getItem(tables, defaultTableName);
keywords = keywords || getKeywords(editor);
@@ -216,7 +221,7 @@
defaultTable = defaultTable || [];
- if (Array.isArray(tables) && defaultTable.columns)
+ if (defaultTable.columns)
defaultTable = defaultTable.columns;
var cur = editor.getCursor();
@@ -240,7 +245,8 @@
} else {
addMatches(result, search, tables, function(w) {return w;});
addMatches(result, search, defaultTable, function(w) {return w;});
- addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
+ if (!disableKeywords)
+ addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
}
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
diff --git a/js/codemirror/addon/lint/lint.css b/js/codemirror/addon/lint/lint.css
new file mode 100644
index 0000000000..ca59a6f1ff
--- /dev/null
+++ b/js/codemirror/addon/lint/lint.css
@@ -0,0 +1,77 @@
+/* The lint marker gutter */
+.CodeMirror-lint-markers {
+ width: 16px;
+}
+
+.CodeMirror-lint-tooltip {
+ background-color: infobackground;
+ border: 1px solid black;
+ border-radius: 4px 4px 4px 4px;
+ color: infotext;
+ font-size: 10pt;
+ overflow: hidden;
+ padding: 2px 5px;
+ position: fixed;
+ white-space: pre;
+ white-space: pre-wrap;
+ z-index: 100;
+ max-width: 600px;
+ opacity: 0;
+ transition: opacity .4s;
+ -moz-transition: opacity .4s;
+ -webkit-transition: opacity .4s;
+ -o-transition: opacity .4s;
+ -ms-transition: opacity .4s;
+}
+
+.CodeMirror-lint-tooltip code {
+ font-family: monospace;
+ font-weight: bold;
+}
+
+.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
+ background-position: left bottom;
+ background-repeat: repeat-x;
+}
+
+.CodeMirror-lint-mark-error {
+ background-image:
+ url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
+ ;
+}
+
+.CodeMirror-lint-mark-warning {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
+}
+
+.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
+ background-position: center center;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ display: inline-block;
+ height: 16px;
+ width: 16px;
+ vertical-align: middle;
+ position: relative;
+}
+
+.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
+ padding-left: 18px;
+ background-position: top left;
+ background-repeat: no-repeat;
+}
+
+.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
+}
+
+.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
+}
+
+.CodeMirror-lint-marker-multiple {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
+ background-repeat: no-repeat;
+ background-position: right bottom;
+ width: 100%; height: 100%;
+}
diff --git a/js/codemirror/addon/lint/lint.js b/js/codemirror/addon/lint/lint.js
new file mode 100644
index 0000000000..fc4a636320
--- /dev/null
+++ b/js/codemirror/addon/lint/lint.js
@@ -0,0 +1,209 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ "use strict";
+ var GUTTER_ID = "CodeMirror-lint-markers";
+
+ function showTooltip(e, content) {
+ var tt = document.createElement("div");
+ tt.className = "CodeMirror-lint-tooltip";
+ tt.appendChild(content.cloneNode(true));
+ document.body.appendChild(tt);
+
+ function position(e) {
+ if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
+ tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
+ tt.style.left = (e.clientX + 5) + "px";
+ }
+ CodeMirror.on(document, "mousemove", position);
+ position(e);
+ if (tt.style.opacity != null) tt.style.opacity = 1;
+ return tt;
+ }
+ function rm(elt) {
+ if (elt.parentNode) elt.parentNode.removeChild(elt);
+ }
+ function hideTooltip(tt) {
+ if (!tt.parentNode) return;
+ if (tt.style.opacity == null) rm(tt);
+ tt.style.opacity = 0;
+ setTimeout(function() { rm(tt); }, 600);
+ }
+
+ function showTooltipFor(e, content, node) {
+ var tooltip = showTooltip(e, content);
+ function hide() {
+ CodeMirror.off(node, "mouseout", hide);
+ if (tooltip) { hideTooltip(tooltip); tooltip = null; }
+ }
+ var poll = setInterval(function() {
+ if (tooltip) for (var n = node;; n = n.parentNode) {
+ if (n && n.nodeType == 11) n = n.host;
+ if (n == document.body) return;
+ if (!n) { hide(); break; }
+ }
+ if (!tooltip) return clearInterval(poll);
+ }, 400);
+ CodeMirror.on(node, "mouseout", hide);
+ }
+
+ function LintState(cm, options, hasGutter) {
+ this.marked = [];
+ this.options = options;
+ this.timeout = null;
+ this.hasGutter = hasGutter;
+ this.onMouseOver = function(e) { onMouseOver(cm, e); };
+ }
+
+ function parseOptions(_cm, options) {
+ if (options instanceof Function) return {getAnnotations: options};
+ if (!options || options === true) options = {};
+ return options;
+ }
+
+ function clearMarks(cm) {
+ var state = cm.state.lint;
+ if (state.hasGutter) cm.clearGutter(GUTTER_ID);
+ for (var i = 0; i < state.marked.length; ++i)
+ state.marked[i].clear();
+ state.marked.length = 0;
+ }
+
+ function makeMarker(labels, severity, multiple, tooltips) {
+ var marker = document.createElement("div"), inner = marker;
+ marker.className = "CodeMirror-lint-marker-" + severity;
+ if (multiple) {
+ inner = marker.appendChild(document.createElement("div"));
+ inner.className = "CodeMirror-lint-marker-multiple";
+ }
+
+ if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
+ showTooltipFor(e, labels, inner);
+ });
+
+ return marker;
+ }
+
+ function getMaxSeverity(a, b) {
+ if (a == "error") return a;
+ else return b;
+ }
+
+ function groupByLine(annotations) {
+ var lines = [];
+ for (var i = 0; i < annotations.length; ++i) {
+ var ann = annotations[i], line = ann.from.line;
+ (lines[line] || (lines[line] = [])).push(ann);
+ }
+ return lines;
+ }
+
+ function annotationTooltip(ann) {
+ var severity = ann.severity;
+ if (!severity) severity = "error";
+ var tip = document.createElement("div");
+ tip.className = "CodeMirror-lint-message-" + severity;
+ tip.appendChild(document.createTextNode(ann.message));
+ // Unescaping only the <code> tag.
+ tip.innerHTML = tip.innerHTML.replace("&lt;code&gt;", "<code>")
+ .replace("&lt;/code&gt;", "</code>");
+ return tip;
+ }
+
+ function startLinting(cm) {
+ var state = cm.state.lint, options = state.options;
+ var passOptions = options.options || options; // Support deprecated passing of `options` property in options
+ var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
+ if (!getAnnotations) return;
+ if (options.async || getAnnotations.async)
+ getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
+ else
+ updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));
+ }
+
+ function updateLinting(cm, annotationsNotSorted) {
+ clearMarks(cm);
+ var state = cm.state.lint, options = state.options;
+
+ var annotations = groupByLine(annotationsNotSorted);
+
+ for (var line = 0; line < annotations.length; ++line) {
+ var anns = annotations[line];
+ if (!anns) continue;
+
+ var maxSeverity = null;
+ var tipLabel = state.hasGutter && document.createDocumentFragment();
+
+ for (var i = 0; i < anns.length; ++i) {
+ var ann = anns[i];
+ var severity = ann.severity;
+ if (!severity) severity = "error";
+ maxSeverity = getMaxSeverity(maxSeverity, severity);
+
+ if (options.formatAnnotation) ann = options.formatAnnotation(ann);
+ if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
+
+ if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
+ className: "CodeMirror-lint-mark-" + severity,
+ __annotation: ann
+ }));
+ }
+
+ if (state.hasGutter)
+ cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
+ state.options.tooltips));
+ }
+ if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
+ }
+
+ function onChange(cm) {
+ var state = cm.state.lint;
+ if (!state) return;
+ clearTimeout(state.timeout);
+ state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
+ }
+
+ function popupSpanTooltip(ann, e) {
+ var target = e.target || e.srcElement;
+ showTooltipFor(e, annotationTooltip(ann), target);
+ }
+
+ function onMouseOver(cm, e) {
+ var target = e.target || e.srcElement;
+ if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
+ var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
+ var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
+ for (var i = 0; i < spans.length; ++i) {
+ var ann = spans[i].__annotation;
+ if (ann) return popupSpanTooltip(ann, e);
+ }
+ }
+
+ CodeMirror.defineOption("lint", false, function(cm, val, old) {
+ if (old && old != CodeMirror.Init) {
+ clearMarks(cm);
+ cm.off("change", onChange);
+ CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
+ clearTimeout(cm.state.lint.timeout);
+ delete cm.state.lint;
+ }
+
+ if (val) {
+ var gutters = cm.getOption("gutters"), hasLintGutter = false;
+ for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
+ var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
+ cm.on("change", onChange);
+ if (state.options.tooltips != false)
+ CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
+
+ startLinting(cm);
+ }
+ });
+});
diff --git a/js/codemirror/addon/lint/sql-lint.js b/js/codemirror/addon/lint/sql-lint.js
new file mode 100644
index 0000000000..22a5785a6d
--- /dev/null
+++ b/js/codemirror/addon/lint/sql-lint.js
@@ -0,0 +1,39 @@
+CodeMirror.sqlLint = function(text, updateLinting, options, cm) {
+
+ // Skipping check if text box is empty.
+ if(text.trim() == "") {
+ updateLinting(cm, []);
+ return;
+ }
+
+ function handleResponse(json) {
+ response = JSON.parse(json);
+
+ var found = [];
+ for (var idx in response) {
+ found.push({
+ from: CodeMirror.Pos(
+ response[idx].fromLine, response[idx].fromColumn
+ ),
+ to: CodeMirror.Pos(
+ response[idx].toLine, response[idx].toColumn
+ ),
+ message: response[idx].message,
+ severity : response[idx].severity
+ });
+ }
+
+ updateLinting(cm, found);
+ }
+
+ $.ajax({
+ method: "POST",
+ url: "lint.php",
+ data: {
+ sql_query: text,
+ token: PMA_commonParams.get('token'),
+ server: PMA_commonParams.get('server')
+ },
+ success: handleResponse
+ });
+}
diff --git a/js/codemirror/lib/codemirror.css b/js/codemirror/lib/codemirror.css
new file mode 100644
index 0000000000..b313b61c68
--- /dev/null
+++ b/js/codemirror/lib/codemirror.css
@@ -0,0 +1,325 @@
+/* BASICS */
+
+.CodeMirror {
+ /* Set height, width, borders, and global font properties here */
+ font-family: monospace;
+ height: 300px;
+ color: black;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+ padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre {
+ padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+ background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* GUTTER */
+
+.CodeMirror-gutters {
+ border-right: 1px solid #ddd;
+ background-color: #f7f7f7;
+ white-space: nowrap;
+}
+.CodeMirror-linenumbers {}
+.CodeMirror-linenumber {
+ padding: 0 3px 0 5px;
+ min-width: 20px;
+ text-align: right;
+ color: #999;
+ white-space: nowrap;
+}
+
+.CodeMirror-guttermarker { color: black; }
+.CodeMirror-guttermarker-subtle { color: #999; }
+
+/* CURSOR */
+
+.CodeMirror div.CodeMirror-cursor {
+ border-left: 1px solid black;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+ border-left: 1px solid silver;
+}
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
+ width: auto;
+ border: 0;
+ background: #7e7;
+}
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
+ z-index: 1;
+}
+
+.cm-animate-fat-cursor {
+ width: auto;
+ border: 0;
+ -webkit-animation: blink 1.06s steps(1) infinite;
+ -moz-animation: blink 1.06s steps(1) infinite;
+ animation: blink 1.06s steps(1) infinite;
+}
+@-moz-keyframes blink {
+ 0% { background: #7e7; }
+ 50% { background: none; }
+ 100% { background: #7e7; }
+}
+@-webkit-keyframes blink {
+ 0% { background: #7e7; }
+ 50% { background: none; }
+ 100% { background: #7e7; }
+}
+@keyframes blink {
+ 0% { background: #7e7; }
+ 50% { background: none; }
+ 100% { background: #7e7; }
+}
+
+/* Can style cursor different in overwrite (non-insert) mode */
+div.CodeMirror-overwrite div.CodeMirror-cursor {}
+
+.cm-tab { display: inline-block; text-decoration: inherit; }
+
+.CodeMirror-ruler {
+ border-left: 1px solid #ccc;
+ position: absolute;
+}
+
+/* DEFAULT THEME */
+
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
+
+.cm-s-default .cm-keyword {color: #708;}
+.cm-s-default .cm-atom {color: #219;}
+.cm-s-default .cm-number {color: #164;}
+.cm-s-default .cm-def {color: #00f;}
+.cm-s-default .cm-variable,
+.cm-s-default .cm-punctuation,
+.cm-s-default .cm-property,
+.cm-s-default .cm-operator {}
+.cm-s-default .cm-variable-2 {color: #05a;}
+.cm-s-default .cm-variable-3 {color: #085;}
+.cm-s-default .cm-comment {color: #a50;}
+.cm-s-default .cm-string {color: #a11;}
+.cm-s-default .cm-string-2 {color: #f50;}
+.cm-s-default .cm-meta {color: #555;}
+.cm-s-default .cm-qualifier {color: #555;}
+.cm-s-default .cm-builtin {color: #30a;}
+.cm-s-default .cm-bracket {color: #997;}
+.cm-s-default .cm-tag {color: #170;}
+.cm-s-default .cm-attribute {color: #00c;}
+.cm-s-default .cm-hr {color: #999;}
+.cm-s-default .cm-link {color: #00c;}
+
+.cm-s-default .cm-error {color: #f00;}
+.cm-invalidchar {color: #f00;}
+
+.CodeMirror-composing { border-bottom: 2px solid; }
+
+/* Default styles for common addons */
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
+.CodeMirror-activeline-background {background: #e8f2ff;}
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+ the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+ position: relative;
+ overflow: hidden;
+ background: white;
+}
+
+.CodeMirror-scroll {
+ overflow: scroll !important; /* Things will break if this is overridden */
+ /* 30px is the magic margin used to hide the element's real scrollbars */
+ /* See overflow: hidden in .CodeMirror */
+ margin-bottom: -30px; margin-right: -30px;
+ padding-bottom: 30px;
+ height: 100%;
+ outline: none; /* Prevent dragging from highlighting the element */
+ position: relative;
+}
+.CodeMirror-sizer {
+ position: relative;
+ border-right: 30px solid transparent;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+ before actuall scrolling happens, thus preventing shaking and
+ flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+ position: absolute;
+ z-index: 6;
+ display: none;
+}
+.CodeMirror-vscrollbar {
+ right: 0; top: 0;
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+ bottom: 0; left: 0;
+ overflow-y: hidden;
+ overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+ right: 0; bottom: 0;
+}
+.CodeMirror-gutter-filler {
+ left: 0; bottom: 0;
+}
+
+.CodeMirror-gutters {
+ position: absolute; left: 0; top: 0;
+ z-index: 3;
+}
+.CodeMirror-gutter {
+ white-space: normal;
+ height: 100%;
+ display: inline-block;
+ margin-bottom: -30px;
+ /* Hack to make IE7 behave */
+ *zoom:1;
+ *display:inline;
+}
+.CodeMirror-gutter-wrapper {
+ position: absolute;
+ z-index: 4;
+ height: 100%;
+}
+.CodeMirror-gutter-elt {
+ position: absolute;
+ cursor: default;
+ z-index: 4;
+}
+.CodeMirror-gutter-wrapper {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+}
+
+.CodeMirror-lines {
+ cursor: text;
+ min-height: 1px; /* prevents collapsing before first draw */
+}
+.CodeMirror pre {
+ /* Reset some styles that the rest of the page might have set */
+ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
+ border-width: 0;
+ background: transparent;
+ font-family: inherit;
+ font-size: inherit;
+ margin: 0;
+ white-space: pre;
+ word-wrap: normal;
+ line-height: inherit;
+ color: inherit;
+ z-index: 2;
+ position: relative;
+ overflow: visible;
+ -webkit-tap-highlight-color: transparent;
+}
+.CodeMirror-wrap pre {
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ word-break: normal;
+}
+
+.CodeMirror-linebackground {
+ position: absolute;
+ left: 0; right: 0; top: 0; bottom: 0;
+ z-index: 0;
+}
+
+.CodeMirror-linewidget {
+ position: relative;
+ z-index: 2;
+ overflow: auto;
+}
+
+.CodeMirror-widget {}
+
+.CodeMirror-code {
+ outline: none;
+}
+
+/* Force content-box sizing for the elements where we expect it */
+.CodeMirror-scroll,
+.CodeMirror-sizer,
+.CodeMirror-gutter,
+.CodeMirror-gutters,
+.CodeMirror-linenumber {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+.CodeMirror-measure {
+ position: absolute;
+ width: 100%;
+ height: 0;
+ overflow: hidden;
+ visibility: hidden;
+}
+.CodeMirror-measure pre { position: static; }
+
+.CodeMirror div.CodeMirror-cursor {
+ position: absolute;
+ border-right: none;
+ width: 0;
+}
+
+div.CodeMirror-cursors {
+ visibility: hidden;
+ position: relative;
+ z-index: 3;
+}
+.CodeMirror-focused div.CodeMirror-cursors {
+ visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+.CodeMirror-crosshair { cursor: crosshair; }
+.CodeMirror ::selection { background: #d7d4f0; }
+.CodeMirror ::-moz-selection { background: #d7d4f0; }
+
+.cm-searching {
+ background: #ffa;
+ background: rgba(255, 255, 0, .4);
+}
+
+/* IE7 hack to prevent it from returning funny offsetTops on the spans */
+.CodeMirror span { *vertical-align: text-bottom; }
+
+/* Used to force a border model for a node */
+.cm-force-border { padding-right: .1px; }
+
+@media print {
+ /* Hide the cursor when printing */
+ .CodeMirror div.CodeMirror-cursors {
+ visibility: hidden;
+ }
+}
+
+/* See issue #2901 */
+.cm-tab-wrap-hack:after { content: ''; }
+
+/* Help users use markselection to safely style text background */
+span.CodeMirror-selectedtext { background: none; }
diff --git a/js/codemirror/lib/codemirror.js b/js/codemirror/lib/codemirror.js
index 98a45c60ba..283fc09fec 100644
--- a/js/codemirror/lib/codemirror.js
+++ b/js/codemirror/lib/codemirror.js
@@ -82,12 +82,15 @@
keyMaps: [], // stores maps added by addKeyMap
overlays: [], // highlighting overlays, as added by addOverlay
modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
- overwrite: false, focused: false,
+ overwrite: false,
+ delayingBlurEvent: false,
+ focused: false,
suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
draggingText: false,
highlight: new Delayed(), // stores highlight worker timeout
- keySeq: null // Unfinished key sequence
+ keySeq: null, // Unfinished key sequence
+ specialChars: null
};
var cm = this;
@@ -591,7 +594,7 @@
"CodeMirror-linenumber CodeMirror-gutter-elt"));
var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
display.lineGutter.style.width = "";
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
display.lineNumWidth = display.lineNumInnerWidth + padding;
display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
display.lineGutter.style.width = display.lineNumWidth + "px";
@@ -725,12 +728,9 @@
}
function postUpdateDisplay(cm, update) {
- var force = update.force, viewport = update.viewport;
+ var viewport = update.viewport;
for (var first = true;; first = false) {
- if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
- force = true;
- } else {
- force = false;
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
// Clip forced viewport to actual scrollable area.
if (viewport && viewport.top != null)
viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
@@ -1076,14 +1076,15 @@
// was made out of.
var lastCopied = null;
- function applyTextInput(cm, inserted, deleted, sel) {
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
var doc = cm.doc;
cm.display.shift = false;
if (!sel) sel = doc.sel;
+ var paste = cm.state.pasteIncoming || origin == "paste";
var textLines = splitLines(inserted), multiPaste = null;
// When pasing N lines into N selections, insert one line per selection
- if (cm.state.pasteIncoming && sel.ranges.length > 1) {
+ if (paste && sel.ranges.length > 1) {
if (lastCopied && lastCopied.join("\n") == inserted)
multiPaste = sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
else if (textLines.length == sel.ranges.length)
@@ -1097,38 +1098,57 @@
if (range.empty()) {
if (deleted && deleted > 0) // Handle deletion
from = Pos(from.line, from.ch - deleted);
- else if (cm.state.overwrite && !cm.state.pasteIncoming) // Handle overwrite
+ else if (cm.state.overwrite && !paste) // Handle overwrite
to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
}
var updateInput = cm.curOp.updateInput;
var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
- origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
+ origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
makeChange(cm.doc, changeEvent);
signalLater(cm, "inputRead", cm, changeEvent);
- // When an 'electric' character is inserted, immediately trigger a reindent
- if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
- cm.options.smartIndent && range.head.ch < 100 &&
- (!i || sel.ranges[i - 1].head.line != range.head.line)) {
- var mode = cm.getModeAt(range.head);
- var end = changeEnd(changeEvent);
- if (mode.electricChars) {
- for (var j = 0; j < mode.electricChars.length; j++)
- if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
- indentLine(cm, end.line, "smart");
- break;
- }
- } else if (mode.electricInput) {
- if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
- indentLine(cm, end.line, "smart");
- }
- }
}
+ if (inserted && !paste)
+ triggerElectric(cm, inserted);
+
ensureCursorVisible(cm);
cm.curOp.updateInput = updateInput;
cm.curOp.typing = true;
cm.state.pasteIncoming = cm.state.cutIncoming = false;
}
+ function handlePaste(e, cm) {
+ var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
+ if (pasted) {
+ e.preventDefault();
+ runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
+ return true;
+ }
+ }
+
+ function triggerElectric(cm, inserted) {
+ // When an 'electric' character is inserted, immediately trigger a reindent
+ if (!cm.options.electricChars || !cm.options.smartIndent) return;
+ var sel = cm.doc.sel;
+
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
+ var range = sel.ranges[i];
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
+ var mode = cm.getModeAt(range.head);
+ var indented = false;
+ if (mode.electricChars) {
+ for (var j = 0; j < mode.electricChars.length; j++)
+ if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
+ indented = indentLine(cm, range.head.line, "smart");
+ break;
+ }
+ } else if (mode.electricInput) {
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
+ indented = indentLine(cm, range.head.line, "smart");
+ }
+ if (indented) signalLater(cm, "electricInput", cm, range.head.line);
+ }
+ }
+
function copyableRanges(cm) {
var text = [], ranges = [];
for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
@@ -1164,6 +1184,7 @@
this.inaccurateSelection = false;
// Used to work around IE issue with selection being forgotten when focus moves away from textarea
this.hasSelection = false;
+ this.composing = null;
};
function hiddenTextarea() {
@@ -1200,21 +1221,9 @@
input.poll();
});
- on(te, "paste", function() {
- // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
- // Add a char to the end of textarea before paste occur so that
- // selection doesn't span to the end of textarea.
- if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
- var start = te.selectionStart, end = te.selectionEnd;
- te.value += "$";
- // The selection end needs to be set before the start, otherwise there
- // can be an intermediate non-empty selection between the two, which
- // can override the middle-click paste buffer on linux and cause the
- // wrong thing to get pasted.
- te.selectionEnd = end;
- te.selectionStart = start;
- cm.state.fakedLastChar = true;
- }
+ on(te, "paste", function(e) {
+ if (handlePaste(e, cm)) return true;
+
cm.state.pasteIncoming = true;
input.fastPoll();
});
@@ -1228,6 +1237,8 @@
te.value = lastCopied.join("\n");
selectInput(te);
}
+ } else if (!cm.options.lineWiseCopyCut) {
+ return;
} else {
var ranges = copyableRanges(cm);
lastCopied = ranges.text;
@@ -1254,6 +1265,21 @@
on(display.lineSpace, "selectstart", function(e) {
if (!eventInWidget(display, e)) e_preventDefault(e);
});
+
+ on(te, "compositionstart", function() {
+ var start = cm.getCursor("from");
+ input.composing = {
+ start: start,
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
+ };
+ });
+ on(te, "compositionend", function() {
+ if (input.composing) {
+ input.poll();
+ input.composing.range.clear();
+ input.composing = null;
+ }
+ });
},
prepareSelection: function() {
@@ -1361,14 +1387,11 @@
// possible when it is clear that nothing happened. hasSelection
// will be the case when there is a lot of text in the textarea,
// in which case reading its value would be expensive.
- if (!cm.state.focused || (hasSelection(input) && !prevInput) ||
+ if (this.contextMenuPending || !cm.state.focused ||
+ (hasSelection(input) && !prevInput) ||
isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
return false;
- // See paste handler for more on the fakedLastChar kludge
- if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
- input.value = input.value.substring(0, input.value.length - 1);
- cm.state.fakedLastChar = false;
- }
+
var text = input.value;
// If nothing changed, bail.
if (text == prevInput && !cm.somethingSelected()) return false;
@@ -1381,19 +1404,29 @@
return false;
}
- if (text.charCodeAt(0) == 0x200b && cm.doc.sel == cm.display.selForContextMenu && !prevInput)
- prevInput = "\u200b";
+ if (cm.doc.sel == cm.display.selForContextMenu) {
+ var first = text.charCodeAt(0);
+ if (first == 0x200b && !prevInput) prevInput = "\u200b";
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
+ }
// Find the part of the input that is actually new
var same = 0, l = Math.min(prevInput.length, text.length);
while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
var self = this;
runInOp(cm, function() {
- applyTextInput(cm, text.slice(same), prevInput.length - same);
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
+ null, self.composing ? "*compose" : null);
// Don't leave long text in the textarea, since it makes further polling slow
if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
else self.prevInput = text;
+
+ if (self.composing) {
+ self.composing.range.clear();
+ self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
+ {className: "CodeMirror-composing"});
+ }
});
return true;
},
@@ -1440,7 +1473,9 @@
function prepareSelectAllHack() {
if (te.selectionStart != null) {
var selected = cm.somethingSelected();
- var extval = te.value = "\u200b" + (selected ? te.value : "");
+ var extval = "\u200b" + (selected ? te.value : "");
+ te.value = "\u21da"; // Used to catch context-menu undo
+ te.value = extval;
input.prevInput = selected ? "" : "\u200b";
te.selectionStart = 1; te.selectionEnd = extval.length;
// Re-set this, in case some other handler touched the
@@ -1458,7 +1493,8 @@
if (te.selectionStart != null) {
if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
var i = 0, poll = function() {
- if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0)
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
+ te.selectionEnd > 0 && input.prevInput == "\u200b")
operation(cm, commands.selectAll)(cm);
else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
else display.input.reset();
@@ -1491,6 +1527,7 @@
this.cm = cm;
this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
this.polling = new Delayed();
+ this.gracePeriod = false;
}
ContentEditableInput.prototype = copyObj({
@@ -1500,13 +1537,7 @@
div.contentEditable = "true";
disableBrowserMagic(div);
- on(div, "paste", function(e) {
- var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
- if (pasted) {
- e.preventDefault();
- cm.replaceSelection(pasted, null, "paste");
- }
- });
+ on(div, "paste", function(e) { handlePaste(e, cm); })
on(div, "compositionstart", function(e) {
var data = e.data;
@@ -1552,6 +1583,8 @@
if (cm.somethingSelected()) {
lastCopied = cm.getSelections();
if (e.type == "cut") cm.replaceSelection("", null, "cut");
+ } else if (!cm.options.lineWiseCopyCut) {
+ return;
} else {
var ranges = copyableRanges(cm);
lastCopied = ranges.text;
@@ -1625,10 +1658,21 @@
sel.removeAllRanges();
sel.addRange(rng);
if (old && sel.anchorNode == null) sel.addRange(old);
+ else if (gecko) this.startGracePeriod();
}
this.rememberSelection();
},
+ startGracePeriod: function() {
+ var input = this;
+ clearTimeout(this.gracePeriod);
+ this.gracePeriod = setTimeout(function() {
+ input.gracePeriod = false;
+ if (input.selectionChanged())
+ input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
+ }, 20);
+ },
+
showMultipleSelections: function(info) {
removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
@@ -1671,12 +1715,15 @@
this.polling.set(this.cm.options.pollInterval, poll);
},
- pollSelection: function() {
- if (this.composing) return;
+ selectionChanged: function() {
+ var sel = window.getSelection();
+ return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
+ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
+ },
- var sel = window.getSelection(), cm = this.cm;
- if (sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
- sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset) {
+ pollSelection: function() {
+ if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
+ var sel = window.getSelection(), cm = this.cm;
this.rememberSelection();
var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
var head = domToPos(cm, sel.focusNode, sel.focusOffset);
@@ -1703,7 +1750,7 @@
var toIndex = findViewIndex(cm, to.line);
if (toIndex == display.view.length - 1) {
var toLine = display.viewTo - 1;
- var toNode = display.view[toIndex].node;
+ var toNode = display.lineDiv.lastChild;
} else {
var toLine = lineNo(display.view[toIndex + 1].line) - 1;
var toNode = display.view[toIndex + 1].node.previousSibling;
@@ -1783,7 +1830,7 @@
var partPos = getBidiPartAt(order, pos.ch);
side = partPos % 2 ? "right" : "left";
}
- var result = nodeAndOffsetInLineMap(info.map, pos.ch, "left");
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
result.offset = result.collapse == "right" ? result.end : result.start;
return result;
}
@@ -2895,6 +2942,7 @@
updateMaxLine: false, // Set when the widest line needs to be determined anew
scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
scrollToPos: null, // Used to scroll to a specific position
+ focus: false,
id: ++nextOpId // Unique ID
};
if (operationGroup) {
@@ -3012,6 +3060,7 @@
if (cm.state.focused && op.updateInput)
cm.display.input.reset(op.typing);
+ if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
}
function endOperation_finish(op) {
@@ -3376,15 +3425,11 @@
// Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
- function drag_(e) {
- if (!signalDOMEvent(cm, e)) e_stop(e);
- }
- if (cm.options.dragDrop) {
- on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
- on(d.scroller, "dragenter", drag_);
- on(d.scroller, "dragover", drag_);
- on(d.scroller, "drop", operation(cm, onDrop));
- }
+ d.dragFunctions = {
+ simple: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
+ start: function(e){onDragStart(cm, e);},
+ drop: operation(cm, onDrop)
+ };
var inp = d.input.getField();
on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
@@ -3394,6 +3439,18 @@
on(inp, "blur", bind(onBlur, cm));
}
+ function dragDropChanged(cm, value, old) {
+ var wasOn = old && old != CodeMirror.Init;
+ if (!value != !wasOn) {
+ var funcs = cm.display.dragFunctions;
+ var toggle = value ? on : off;
+ toggle(cm.display.scroller, "dragstart", funcs.start);
+ toggle(cm.display.scroller, "dragenter", funcs.simple);
+ toggle(cm.display.scroller, "dragover", funcs.simple);
+ toggle(cm.display.scroller, "drop", funcs.drop);
+ }
+ }
+
// Called when the window resizes
function onResize(cm) {
var d = cm.display;
@@ -3475,6 +3532,7 @@
break;
case 3:
if (captureRightClick) onContextMenu(cm, e);
+ else delayBlurEvent(cm);
break;
}
}
@@ -3482,7 +3540,7 @@
var lastClick, lastDoubleClick;
function leftButtonDown(cm, e, start) {
if (ie) setTimeout(bind(ensureFocus, cm), 0);
- else ensureFocus(cm);
+ else cm.curOp.focus = activeElt();
var now = +new Date, type;
if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
@@ -3498,7 +3556,8 @@
var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
type == "single" && (contained = sel.contains(start)) > -1 &&
- !sel.ranges[contained].empty())
+ (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
+ (cmp(contained.to(), start) > 0 || start.xRel < 0))
leftButtonStartDrag(cm, e, start, modifier);
else
leftButtonSelect(cm, e, start, type, modifier);
@@ -3507,7 +3566,7 @@
// Start a text drag. When it ends, see if any dragging actually
// happen, and treat as a click if it didn't.
function leftButtonStartDrag(cm, e, start, modifier) {
- var display = cm.display;
+ var display = cm.display, startTime = +new Date;
var dragEnd = operation(cm, function(e2) {
if (webkit) display.scroller.draggable = false;
cm.state.draggingText = false;
@@ -3515,12 +3574,13 @@
off(display.scroller, "drop", dragEnd);
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
e_preventDefault(e2);
- if (!modifier)
+ if (!modifier && +new Date - 200 < startTime)
extendSelection(cm.doc, start);
- display.input.focus();
- // Work around unexplainable focus problem in IE9 (#2127)
- if (ie && ie_version == 9)
+ // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
+ if (webkit || ie && ie_version == 9)
setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
+ else
+ display.input.focus();
}
});
// Let the drag handler handle this.
@@ -3546,6 +3606,7 @@
ourRange = new Range(start, start);
} else {
ourRange = doc.sel.primary();
+ ourIndex = doc.sel.primIndex;
}
if (e.altKey) {
@@ -3577,7 +3638,7 @@
ourIndex = ranges.length;
setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
{scroll: false, origin: "*mouse"});
- } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {
+ } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
startSel = doc.sel;
} else {
@@ -3640,7 +3701,7 @@
var cur = posFromMouse(cm, e, true, type == "rect");
if (!cur) return;
if (cmp(cur, lastPos) != 0) {
- ensureFocus(cm);
+ cm.curOp.focus = activeElt();
extendTo(cur);
var visible = visibleLines(display, doc);
if (cur.line >= visible.to || cur.line < visible.from)
@@ -3743,7 +3804,7 @@
try {
var text = e.dataTransfer.getData("Text");
if (text) {
- if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
+ if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
var selected = cm.listSelections();
setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
if (selected) for (var i = 0; i < selected.length; ++i)
@@ -3998,7 +4059,7 @@
var lastStoppedKey = null;
function onKeyDown(e) {
var cm = this;
- ensureFocus(cm);
+ cm.curOp.focus = activeElt();
if (signalDOMEvent(cm, e)) return;
// IE does strange things with escape.
if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
@@ -4050,7 +4111,19 @@
// FOCUS/BLUR EVENTS
+ function delayBlurEvent(cm) {
+ cm.state.delayingBlurEvent = true;
+ setTimeout(function() {
+ if (cm.state.delayingBlurEvent) {
+ cm.state.delayingBlurEvent = false;
+ onBlur(cm);
+ }
+ }, 100);
+ }
+
function onFocus(cm) {
+ if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
+
if (cm.options.readOnly == "nocursor") return;
if (!cm.state.focused) {
signal(cm, "focus", cm);
@@ -4068,6 +4141,8 @@
restartBlink(cm);
}
function onBlur(cm) {
+ if (cm.state.delayingBlurEvent) return;
+
if (cm.state.focused) {
signal(cm, "blur", cm);
cm.state.focused = false;
@@ -4572,6 +4647,8 @@
if (indentString != curSpaceString) {
replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
+ line.stateAfter = null;
+ return true;
} else {
// Ensure that, if the cursor was in the whitespace at the start
// of the line, it is moved to the end of that space.
@@ -4584,7 +4661,6 @@
}
}
}
- line.stateAfter = null;
}
// Utility for applying a change to a line by handle or number,
@@ -4824,7 +4900,7 @@
getHelpers: function(pos, type) {
var found = [];
- if (!helpers.hasOwnProperty(type)) return helpers;
+ if (!helpers.hasOwnProperty(type)) return found;
var help = helpers[type], mode = this.getModeAt(pos);
if (typeof mode[type] == "string") {
if (help[mode[type]]) found.push(help[mode[type]]);
@@ -4874,10 +4950,15 @@
return lineAtHeight(this.doc, height + this.display.viewOffset);
},
heightAtLine: function(line, mode) {
- var end = false, last = this.doc.first + this.doc.size - 1;
- if (line < this.doc.first) line = this.doc.first;
- else if (line > last) { line = last; end = true; }
- var lineObj = getLine(this.doc, line);
+ var end = false, lineObj;
+ if (typeof line == "number") {
+ var last = this.doc.first + this.doc.size - 1;
+ if (line < this.doc.first) line = this.doc.first;
+ else if (line > last) { line = last; end = true; }
+ lineObj = getLine(this.doc, line);
+ } else {
+ lineObj = line;
+ }
return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
(end ? this.doc.height - heightAtLine(lineObj) : 0);
},
@@ -4906,12 +4987,6 @@
});
}),
- addLineWidget: methodOp(function(handle, node, options) {
- return addLineWidget(this, handle, node, options);
- }),
-
- removeLineWidget: function(widget) { widget.clear(); },
-
lineInfo: function(line) {
if (typeof line == "number") {
if (!isLine(this.doc, line)) return null;
@@ -4973,6 +5048,8 @@
return commands[cmd](this);
},
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
+
findPosH: function(from, amount, unit, visually) {
var dir = 1;
if (amount < 0) { dir = -1; amount = -amount; }
@@ -5186,10 +5263,10 @@
clearCaches(cm);
regChange(cm);
}, true);
- option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val) {
- cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
- cm.refresh();
- }, true);
+ option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
+ cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
+ if (old != CodeMirror.Init) cm.refresh();
+ });
option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
option("electricChars", true);
option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
@@ -5235,6 +5312,7 @@
option("showCursorWhenSelecting", false, updateSelection, true);
option("resetSelectionOnContextMenu", true);
+ option("lineWiseCopyCut", true);
option("readOnly", false, function(cm, val) {
if (val == "nocursor") {
@@ -5247,7 +5325,7 @@
}
});
option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
- option("dragDrop", true);
+ option("dragDrop", true, dragDropChanged);
option("cursorBlinkRate", 530);
option("cursorScrollMargin", 0);
@@ -5639,7 +5717,7 @@
for (var i = 0; i < keys.length; i++) {
var val, name;
if (i == keys.length - 1) {
- name = keyname;
+ name = keys.join(" ");
val = value;
} else {
name = keys.slice(0, i + 1).join(" ");
@@ -6431,10 +6509,10 @@
// Line widgets are block elements displayed above or below a line.
- var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
+ var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
if (options) for (var opt in options) if (options.hasOwnProperty(opt))
this[opt] = options[opt];
- this.cm = cm;
+ this.doc = doc;
this.node = node;
};
eventMixin(LineWidget);
@@ -6445,52 +6523,55 @@
}
LineWidget.prototype.clear = function() {
- var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
+ var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
if (no == null || !ws) return;
for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
if (!ws.length) line.widgets = null;
var height = widgetHeight(this);
- runInOp(cm, function() {
+ updateLineHeight(line, Math.max(0, line.height - height));
+ if (cm) runInOp(cm, function() {
adjustScrollWhenAboveVisible(cm, line, -height);
regLineChange(cm, no, "widget");
- updateLineHeight(line, Math.max(0, line.height - height));
});
};
LineWidget.prototype.changed = function() {
- var oldH = this.height, cm = this.cm, line = this.line;
+ var oldH = this.height, cm = this.doc.cm, line = this.line;
this.height = null;
var diff = widgetHeight(this) - oldH;
if (!diff) return;
- runInOp(cm, function() {
+ updateLineHeight(line, line.height + diff);
+ if (cm) runInOp(cm, function() {
cm.curOp.forceUpdate = true;
adjustScrollWhenAboveVisible(cm, line, diff);
- updateLineHeight(line, line.height + diff);
});
};
function widgetHeight(widget) {
if (widget.height != null) return widget.height;
+ var cm = widget.doc.cm;
+ if (!cm) return 0;
if (!contains(document.body, widget.node)) {
var parentStyle = "position: relative;";
if (widget.coverGutter)
- parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;";
+ parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
if (widget.noHScroll)
- parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;";
- removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
+ parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
+ removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
}
return widget.height = widget.node.offsetHeight;
}
- function addLineWidget(cm, handle, node, options) {
- var widget = new LineWidget(cm, node, options);
- if (widget.noHScroll) cm.display.alignWidgets = true;
- changeLine(cm.doc, handle, "widget", function(line) {
+ function addLineWidget(doc, handle, node, options) {
+ var widget = new LineWidget(doc, node, options);
+ var cm = doc.cm;
+ if (cm && widget.noHScroll) cm.display.alignWidgets = true;
+ changeLine(doc, handle, "widget", function(line) {
var widgets = line.widgets || (line.widgets = []);
if (widget.insertAt == null) widgets.push(widget);
else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
widget.line = line;
- if (!lineIsHidden(cm.doc, line)) {
- var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;
+ if (cm && !lineIsHidden(doc, line)) {
+ var aboveVisible = heightAtLine(line) < doc.scrollTop;
updateLineHeight(line, line.height + widgetHeight(widget));
if (aboveVisible) addToScrollPos(cm, null, widget.height);
cm.curOp.forceUpdate = true;
@@ -6710,7 +6791,9 @@
// is needed on Webkit to be able to get line-level bounding
// rectangles for it (in measureChar).
var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
- var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm};
+ var builder = {pre: elt("pre", [content]), content: content,
+ col: 0, pos: 0, cm: cm,
+ splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
lineView.measure = {};
// Iterate over the logical lines that make up this visual line.
@@ -6720,8 +6803,6 @@
builder.addToken = buildToken;
// Optionally wire in some hacks into the token-rendering
// algorithm, to deal with browser quirks.
- if ((ie || webkit) && cm.getOption("lineWrapping"))
- builder.addToken = buildTokenSplitSpaces(builder.addToken);
if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
builder.addToken = buildTokenBadBidi(builder.addToken, order);
builder.map = [];
@@ -6770,10 +6851,11 @@
// the line map. Takes care to render special characters separately.
function buildToken(builder, text, style, startStyle, endStyle, title, css) {
if (!text) return;
- var special = builder.cm.options.specialChars, mustWrap = false;
+ var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
+ var special = builder.cm.state.specialChars, mustWrap = false;
if (!special.test(text)) {
builder.col += text.length;
- var content = document.createTextNode(text);
+ var content = document.createTextNode(displayText);
builder.map.push(builder.pos, builder.pos + text.length, content);
if (ie && ie_version < 9) mustWrap = true;
builder.pos += text.length;
@@ -6784,7 +6866,7 @@
var m = special.exec(text);
var skipped = m ? m.index - pos : text.length - pos;
if (skipped) {
- var txt = document.createTextNode(text.slice(pos, pos + skipped));
+ var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
else content.appendChild(txt);
builder.map.push(builder.pos, builder.pos + skipped, txt);
@@ -6821,22 +6903,17 @@
builder.content.appendChild(content);
}
- function buildTokenSplitSpaces(inner) {
- function split(old) {
- var out = " ";
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
- out += " ";
- return out;
- }
- return function(builder, text, style, startStyle, endStyle, title) {
- inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
- };
+ function splitSpaces(old) {
+ var out = " ";
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
+ out += " ";
+ return out;
}
// Work around nonsense dimensions being reported for stretches of
// right-to-left text.
function buildTokenBadBidi(inner, order) {
- return function(builder, text, style, startStyle, endStyle, title) {
+ return function(builder, text, style, startStyle, endStyle, title, css) {
style = style ? style + " cm-force-border" : "cm-force-border";
var start = builder.pos, end = start + text.length;
for (;;) {
@@ -6845,8 +6922,8 @@
var part = order[i];
if (part.to > start && part.from <= start) break;
}
- if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title);
- inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);
+ if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
startStyle = null;
text = text.slice(part.to - start);
start = part.to;
@@ -6888,8 +6965,13 @@
var foundBookmarks = [];
for (var j = 0; j < spans.length; ++j) {
var sp = spans[j], m = sp.marker;
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
+ foundBookmarks.push(m);
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
+ nextChange = sp.to;
+ spanEndStyle = "";
+ }
if (m.className) spanStyle += " " + m.className;
if (m.css) css = m.css;
if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
@@ -6900,12 +6982,12 @@
} else if (sp.from > pos && nextChange > sp.from) {
nextChange = sp.from;
}
- if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
}
if (collapsed && (collapsed.from || 0) == pos) {
buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
collapsed.marker, collapsed.from == null);
if (collapsed.to == null) return;
+ if (collapsed.to == pos) collapsed = false;
}
if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
buildCollapsedSpan(builder, 0, foundBookmarks[j]);
@@ -7368,13 +7450,19 @@
});
}),
+ addLineWidget: docMethodOp(function(handle, node, options) {
+ return addLineWidget(this, handle, node, options);
+ }),
+ removeLineWidget: function(widget) { widget.clear(); },
+
markText: function(from, to, options) {
return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
},
setBookmark: function(pos, options) {
var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
insertLeft: options && options.insertLeft,
- clearWhenEmpty: false, shared: options && options.shared};
+ clearWhenEmpty: false, shared: options && options.shared,
+ handleMouseEvents: options && options.handleMouseEvents};
pos = clipPos(this, pos);
return markText(this, pos, pos, realOpts, "bookmark");
},
@@ -7489,7 +7577,7 @@
Doc.prototype.eachLine = Doc.prototype.iter;
// Set up methods on CodeMirror's prototype to redirect to the editor's document.
- var dontDelegate = "iter insert remove copy getEditor".split(" ");
+ var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
CodeMirror.prototype[prop] = (function(method) {
return function() {return method.apply(this.doc, arguments);};
@@ -8108,7 +8196,7 @@
return function(){return f.apply(null, args);};
}
- var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
return /\w/.test(ch) || ch > "\x80" &&
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
@@ -8630,6 +8718,8 @@
lst(order).to -= m[0].length;
order.push(new BidiSpan(0, len - m[0].length, len));
}
+ if (order[0].level == 2)
+ order.unshift(new BidiSpan(1, order[0].to, order[0].to));
if (order[0].level != lst(order).level)
order.push(new BidiSpan(order[0].level, len, len));
@@ -8639,7 +8729,7 @@
// THE END
- CodeMirror.version = "5.0.1";
+ CodeMirror.version = "5.4.0";
return CodeMirror;
});
diff --git a/js/codemirror/mode/javascript/javascript.js b/js/codemirror/mode/javascript/javascript.js
index 3f05ac46c3..c86f49e1f6 100644
--- a/js/codemirror/mode/javascript/javascript.js
+++ b/js/codemirror/mode/javascript/javascript.js
@@ -482,8 +482,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybetype(type) {
if (isTS && type == ":") return cont(typedef);
}
+ function maybedefault(_, value) {
+ if (value == "=") return cont(expressionNoComma);
+ }
function typedef(type) {
- if (type == "variable"){cx.marked = "variable-3"; return cont();}
+ if (type == "variable") {cx.marked = "variable-3"; return cont();}
}
function vardef() {
return pass(pattern, maybetype, maybeAssign, vardefCont);
@@ -538,7 +541,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function funarg(type) {
if (type == "spread") return cont(funarg);
- return pass(pattern, maybetype);
+ return pass(pattern, maybetype, maybedefault);
}
function className(type, value) {
if (type == "variable") {register(value); return cont(classNameAfter);}
@@ -549,6 +552,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function classBody(type, value) {
if (type == "variable" || cx.style == "keyword") {
+ if (value == "static") {
+ cx.marked = "keyword";
+ return cont(classBody);
+ }
cx.marked = "property";
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
return cont(functiondef, classBody);
@@ -581,7 +588,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function importSpec(type, value) {
if (type == "{") return contCommasep(importSpec, "}");
if (type == "variable") register(value);
- return cont();
+ if (value == "*") cx.marked = "keyword";
+ return cont(maybeAs);
+ }
+ function maybeAs(_type, value) {
+ if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
}
function maybeFrom(_type, value) {
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
@@ -669,6 +680,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
blockCommentEnd: jsonMode ? null : "*/",
lineComment: jsonMode ? null : "//",
fold: "brace",
+ closeBrackets: "()[]{}''\"\"``",
helperType: jsonMode ? "json" : "javascript",
jsonldMode: jsonldMode,
diff --git a/js/codemirror/mode/sql/sql.js b/js/codemirror/mode/sql/sql.js
index ee6c194b0e..a908277151 100644
--- a/js/codemirror/mode/sql/sql.js
+++ b/js/codemirror/mode/sql/sql.js
@@ -257,7 +257,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
}
// these keywords are used by all SQL dialects (however, a mode can still overwrite it)
- var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from having in insert into is join like not on or order select set table union update values where ";
+ var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where ";
// turn a space-separated list into an array
function set(str) {
@@ -280,7 +280,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-mssql", {
name: "sql",
client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
- keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered"),
+ keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered declare"),
builtin: set("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "),
atoms: set("false true null unknown"),
operatorChars: /^[*+\-%<>!=]/,
@@ -293,7 +293,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-mysql", {
name: "sql",
client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
- keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
+ keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group group_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),
atoms: set("false true null unknown"),
operatorChars: /^[*+\-%<>!=&|^]/,
@@ -327,9 +327,9 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-cassandra", {
name: "sql",
client: { },
- keywords: set("use select from using consistency where limit first reversed first and in insert into values using consistency ttl update set delete truncate begin batch apply create keyspace with columnfamily primary key index on drop alter type add any one quorum all local_quorum each_quorum"),
- builtin: set("ascii bigint blob boolean counter decimal double float int text timestamp uuid varchar varint"),
- atoms: set("false true"),
+ keywords: set("add all allow alter and any apply as asc authorize batch begin by clustering columnfamily compact consistency count create custom delete desc distinct drop each_quorum exists filtering from grant if in index insert into key keyspace keyspaces level limit local_one local_quorum modify nan norecursive nosuperuser not of on one order password permission permissions primary quorum rename revoke schema select set storage superuser table three to token truncate ttl two type unlogged update use user users using values where with writetime"),
+ builtin: set("ascii bigint blob boolean counter decimal double float frozen inet int list map static text timestamp timeuuid tuple uuid varchar varint"),
+ atoms: set("false true infinity NaN"),
operatorChars: /^[<>=]/,
dateSQL: { },
support: set("commentSlashSlash decimallessFloat"),
diff --git a/js/common.js b/js/common.js
index 22c38d2c12..4e8545af3f 100644
--- a/js/common.js
+++ b/js/common.js
@@ -140,7 +140,7 @@ var PMA_commonActions = {
*/
refreshMain: function (url, callback) {
if (! url) {
- url = $('#selflink a').attr('href');
+ url = $('#selflink').find('a').attr('href');
url = url.substring(0, url.indexOf('?'));
}
url += PMA_commonParams.getUrlQuery();
@@ -350,9 +350,10 @@ PMA_DROP_IMPORT = {
_dragleave: function (event) {
event.stopPropagation();
event.preventDefault();
- $(".pma_drop_handler").clearQueue().stop();
- $(".pma_drop_handler").fadeOut();
- $(".pma_drop_handler").html(PMA_messages.dropImportDropFiles);
+ var $pma_drop_handler = $(".pma_drop_handler");
+ $pma_drop_handler.clearQueue().stop();
+ $pma_drop_handler.fadeOut();
+ $pma_drop_handler.html(PMA_messages.dropImportDropFiles);
},
/**
* Called when upload has finished
@@ -423,15 +424,17 @@ PMA_DROP_IMPORT = {
var ext = (PMA_DROP_IMPORT._getExtension(files[i].name));
var hash = AJAX.hash(++PMA_DROP_IMPORT.uploadCount);
- $(".pma_sql_import_status div").append('<li data-hash="' +hash +'">' +
+ var $pma_sql_import_status_div = $(".pma_sql_import_status div");
+ $pma_sql_import_status_div.append('<li data-hash="' +hash +'">' +
((ext !== '') ? '' : '<img src="./themes/dot.gif" title="invalid format" class="icon ic_s_notice"> ') +
escapeHtml(files[i].name) + '<span class="filesize" data-filename="' +
escapeHtml(files[i].name) +'">' +(files[i].size/1024).toFixed(2) +
' kb</span></li>');
//scroll the UI to bottom
- $(".pma_sql_import_status div").scrollTop(
- $(".pma_sql_import_status div").scrollTop() + 50); //50 hardcoded for now
+ $pma_sql_import_status_div.scrollTop(
+ $pma_sql_import_status_div.scrollTop() + 50
+ ); //50 hardcoded for now
if (ext !== '') {
// Increment liveUploadCount by one
diff --git a/js/config.js b/js/config.js
index d029782852..2b173cf47d 100644
--- a/js/config.js
+++ b/js/config.js
@@ -7,8 +7,8 @@
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('config.js', function () {
- $('input[id], select[id], textarea[id]').unbind('change').unbind('keyup');
- $('input[type=button][name=submit_reset]').unbind('click');
+ $('.optbox input[id], .optbox select[id], .optbox textarea[id]').unbind('change').unbind('keyup');
+ $('.optbox input[type=button][name=submit_reset]').unbind('click');
$('div.tabs_contents').undelegate();
$('#import_local_storage, #export_local_storage').unbind('click');
$('form.prefs-form').unbind('change').unbind('submit');
@@ -17,8 +17,9 @@ AJAX.registerTeardown('config.js', function () {
});
AJAX.registerOnload('config.js', function () {
- $('#topmenu2').find('li.active a').attr('rel', 'samepage');
- $('#topmenu2').find('li:not(.active) a').attr('rel', 'newpage');
+ var $topmenu_upt = $('#topmenu2.user_prefs_tabs');
+ $topmenu_upt.find('li.active a').attr('rel', 'samepage');
+ $topmenu_upt.find('li:not(.active) a').attr('rel', 'newpage');
});
// default values for fields
@@ -44,6 +45,35 @@ function getFieldType(field)
}
/**
+ * Enables or disables the "restore default value" button
+ *
+ * @param {Element} field
+ * @param {boolean} display
+ */
+function setRestoreDefaultBtn(field, display)
+{
+ var $el = $(field).closest('td').find('.restore-default img');
+ $el[display ? 'show' : 'hide']();
+}
+
+/**
+ * Marks field depending on its value (system default or custom)
+ *
+ * @param {Element} field
+ */
+function markField(field)
+{
+ var $field = $(field);
+ var type = getFieldType($field);
+ var isDefault = checkFieldDefault($field, type);
+
+ // checkboxes uses parent <span> for marking
+ var $fieldMarker = (type == 'checkbox') ? $field.parent() : $field;
+ setRestoreDefaultBtn($field, !isDefault);
+ $fieldMarker[isDefault ? 'removeClass' : 'addClass']('custom');
+}
+
+/**
* Sets field value
*
* value must be of type:
@@ -299,7 +329,7 @@ function validateField(id, type, onKeyUp, params)
function getFieldValidators(field_id, onKeyUpOnly)
{
// look for field bound validator
- var name = field_id.match(/[^-]+$/)[0];
+ var name = field_id && field_id.match(/[^-]+$/)[0];
if (typeof validators._field[name] != 'undefined') {
return [[validators._field[name], null]];
}
@@ -423,7 +453,7 @@ function validate_field(field, isKeyUp, errors)
args = [];
}
args.unshift(isKeyUp);
- result = functions[i][0].apply(field[0], args);
+ result = functions[i][0].apply($field[0], args);
if (result !== true) {
if (typeof result == 'string') {
result = [result];
@@ -444,43 +474,30 @@ function validate_field_and_fieldset(field, isKeyUp)
var $field = $(field);
var errors = {};
validate_field($field, isKeyUp, errors);
- validate_fieldset($field.closest('fieldset'), isKeyUp, errors);
+ validate_fieldset($field.closest('fieldset.optbox'), isKeyUp, errors);
displayErrors(errors);
}
-/**
- * Marks field depending on its value (system default or custom)
- *
- * @param {Element} field
- */
-function markField(field)
-{
- var $field = $(field);
- var type = getFieldType($field);
- var isDefault = checkFieldDefault($field, type);
-
- // checkboxes uses parent <span> for marking
- var $fieldMarker = (type == 'checkbox') ? $field.parent() : $field;
- setRestoreDefaultBtn($field, !isDefault);
- $fieldMarker[isDefault ? 'removeClass' : 'addClass']('custom');
-}
-
-/**
- * Enables or disables the "restore default value" button
- *
- * @param {Element} field
- * @param {boolean} display
- */
-function setRestoreDefaultBtn(field, display)
-{
- var $el = $(field).closest('td').find('.restore-default img');
- $el[display ? 'show' : 'hide']();
+function loadInlineConfig() {
+ if (!Array.isArray(configInlineParams)) {
+ return;
+ }
+ for (var i = 0; i < configInlineParams.length; ++i) {
+ if (typeof configInlineParams[i] === 'function') {
+ configInlineParams[i]();
+ }
+ }
}
-AJAX.registerOnload('config.js', function () {
+function setupValidation() {
+ validate = {};
+ configScriptLoaded = true;
+ if (configScriptLoaded && typeof configInlineParams !== "undefined") {
+ loadInlineConfig();
+ }
// register validators and mark custom values
- var $elements = $('input[id], select[id], textarea[id]');
- $('input[id], select[id], textarea[id]').each(function () {
+ var $elements = $('.optbox input[id], .optbox select[id], .optbox textarea[id]');
+ $elements.each(function () {
markField(this);
var $el = $(this);
$el.bind('change', function () {
@@ -511,7 +528,7 @@ AJAX.registerOnload('config.js', function () {
validate_field($elements[i], false, errors);
}
// run all fieldset validators
- $('fieldset').each(function () {
+ $('fieldset.optbox').each(function () {
validate_fieldset(this, false, errors);
});
@@ -519,6 +536,10 @@ AJAX.registerOnload('config.js', function () {
} else if ($check_page_refresh) {
$check_page_refresh.val('1');
}
+}
+
+AJAX.registerOnload('config.js', function () {
+ setupValidation();
});
//
@@ -536,27 +557,42 @@ AJAX.registerOnload('config.js', function () {
*/
function setTab(tab_id)
{
- $('ul.tabs li').removeClass('active').find('a[href=#' + tab_id + ']').parent().addClass('active');
- $('div.tabs_contents fieldset').hide().filter('#' + tab_id).show();
- location.hash = 'tab_' + tab_id;
- $('form.config-form input[name=tab_hash]').val(location.hash);
+ $('ul.tabs').each(function() {
+ var $this = $(this);
+ if (!$this.find('li a[href=#' + tab_id + ']').length) {
+ return;
+ }
+ $this.find('li').removeClass('active').find('a[href=#' + tab_id + ']').parent().addClass('active');
+ $this.parent().find('div.tabs_contents fieldset').hide().filter('#' + tab_id).show();
+ location.hash = 'tab_' + tab_id;
+ $this.parent().find('input[name=tab_hash]').val(location.hash);
+ });
+}
+
+function setupConfigTabs() {
+ var forms = $('form.config-form');
+ forms.each(function() {
+ var $this = $(this);
+ var $tabs = $this.find('ul.tabs');
+ if (!$tabs.length) {
+ return;
+ }
+ // add tabs events and activate one tab (the first one or indicated by location hash)
+ $tabs.find('li').removeClass('active');
+ $tabs.find('a')
+ .click(function (e) {
+ e.preventDefault();
+ setTab($(this).attr('href').substr(1));
+ })
+ .filter(':first')
+ .parent()
+ .addClass('active');
+ $this.find('div.tabs_contents fieldset').hide().filter(':first').show();
+ });
}
AJAX.registerOnload('config.js', function () {
- var $tabs = $('ul.tabs');
- if (!$tabs.length) {
- return;
- }
- // add tabs events and activate one tab (the first one or indicated by location hash)
- $tabs.find('a')
- .click(function (e) {
- e.preventDefault();
- setTab($(this).attr('href').substr(1));
- })
- .filter(':first')
- .parent()
- .addClass('active');
- $('div.tabs_contents fieldset').hide().filter(':first').show();
+ setupConfigTabs();
// tab links handling, check each 200ms
// (works with history in FF, further browser support here would be an overkill)
@@ -582,7 +618,7 @@ AJAX.registerOnload('config.js', function () {
//
AJAX.registerOnload('config.js', function () {
- $('input[type=button][name=submit_reset]').click(function () {
+ $('.optbox input[type=button][name=submit_reset]').click(function () {
var fields = $(this).closest('fieldset').find('input, select, textarea');
for (var i = 0, imax = fields.length; i < imax; i++) {
setFieldValue(fields[i], getFieldType(fields[i]));
@@ -612,7 +648,7 @@ function restoreField(field_id)
setFieldValue($field, getFieldType($field), defaultValues[field_id]);
}
-AJAX.registerOnload('config.js', function () {
+function setupRestoreField() {
$('div.tabs_contents')
.delegate('.restore-default, .set-value', 'mouseenter', function () {
$(this).css('opacity', 1);
@@ -637,6 +673,10 @@ AJAX.registerOnload('config.js', function () {
.find('.restore-default, .set-value')
// inline-block for IE so opacity inheritance works
.css({display: 'inline-block', opacity: 0.25});
+}
+
+AJAX.registerOnload('config.js', function () {
+ setupRestoreField();
});
//
@@ -763,7 +803,7 @@ function updatePrefsDate()
'@DATE@',
PMA_formatDateTime(d)
);
- $('#opts_import_local_storage div.localStorage-exists').html(msg);
+ $('#opts_import_local_storage').find('div.localStorage-exists').html(msg);
}
/**
diff --git a/js/console.js b/js/console.js
index f824b9ae52..c66f4590b3 100644
--- a/js/console.js
+++ b/js/console.js
@@ -57,25 +57,25 @@ var PMA_console = {
*/
initialize: function() {
- if($('#pma_console').length === 0) {
+ if ($('#pma_console').length === 0) {
return;
}
PMA_console.isEnabled = true;
// Cookie var checks and init
- if(! $.cookie('pma_console_height')) {
+ if (! $.cookie('pma_console_height')) {
$.cookie('pma_console_height', 92);
}
- if(! $.cookie('pma_console_mode')) {
+ if (! $.cookie('pma_console_mode')) {
$.cookie('pma_console_mode', 'info');
}
// Vars init
- PMA_console.$consoleToolbar = $('#pma_console>.toolbar');
- PMA_console.$consoleContent = $('#pma_console>.content');
- PMA_console.$consoleAllContents = $('#pma_console .content');
- PMA_console.$consoleTemplates = $('#pma_console>.templates');
+ PMA_console.$consoleToolbar = $("#pma_console").find(">.toolbar");
+ PMA_console.$consoleContent = $("#pma_console").find(">.content");
+ PMA_console.$consoleAllContents = $('#pma_console').find('.content');
+ PMA_console.$consoleTemplates = $('#pma_console').find('>.templates');
// Generate a from for post
PMA_console.$requestForm = $('<form method="post" action="import.php">' +
@@ -93,22 +93,29 @@ var PMA_console = {
PMA_console.$requestForm.bind('submit', AJAX.requestHandler);
// Event binds shouldn't run again
- if(PMA_console.isInitialized === false) {
+ if (PMA_console.isInitialized === false) {
// Load config first
var tempConfig = JSON.parse($.cookie('pma_console_config'));
- if(tempConfig) {
- if(tempConfig.alwaysExpand === true) {
+ if (tempConfig) {
+ if (tempConfig.alwaysExpand === true) {
$('#pma_console_options input[name=always_expand]').prop('checked', true);
}
- if(tempConfig.startHistory === true) {
- $('#pma_console_options input[name=start_history]').prop('checked', true);
+ if (tempConfig.startHistory === true) {
+ $('#pma_console_options').find('input[name=start_history]').prop('checked', true);
}
- if(tempConfig.currentQuery === true) {
- $('#pma_console_options input[name=current_query]').prop('checked', true);
+ if (tempConfig.currentQuery === true) {
+ $('#pma_console_options').find('input[name=current_query]').prop('checked', true);
+ }
+ if (ConsoleEnterExecutes === true) {
+ $('#pma_console_options').find('input[name=enter_executes]').prop('checked', true);
+ }
+ if (tempConfig.darkTheme === true) {
+ $('#pma_console_options').find('input[name=dark_theme]').prop('checked', true);
+ $('#pma_console').find('>.content').addClass('console_dark_theme');
}
} else {
- $('#pma_console_options input[name=current_query]').prop('checked', true);
+ $('#pma_console_options').find('input[name=current_query]').prop('checked', true);
}
PMA_console.updateConfig();
@@ -117,63 +124,80 @@ var PMA_console = {
PMA_consoleInput.initialize();
PMA_consoleMessages.initialize();
PMA_consoleBookmarks.initialize();
+ PMA_consoleDebug.initialize();
PMA_console.$consoleToolbar.children('.console_switch').click(PMA_console.toggle);
$(document).keydown(function(event) {
// Ctrl + Alt + C
- if(event.ctrlKey && event.altKey && event.keyCode === 67) {
+ if (event.ctrlKey && event.altKey && event.keyCode === 67) {
PMA_console.toggle();
}
});
- $('#pma_console .toolbar').children().mousedown(function(event) {
+ $('#pma_console').find('.toolbar').children().mousedown(function(event) {
event.preventDefault();
event.stopImmediatePropagation();
});
- $('#pma_console .button.clear').click(function() {
+ $('#pma_console').find('.button.clear').click(function() {
PMA_consoleMessages.clear();
});
- $('#pma_console .button.history').click(function() {
+ $('#pma_console').find('.button.history').click(function() {
PMA_consoleMessages.showHistory();
});
- $('#pma_console .button.options').click(function() {
+ $('#pma_console').find('.button.options').click(function() {
PMA_console.showCard('#pma_console_options');
});
+ $('#pma_console').find('.button.debug').click(function() {
+ PMA_console.showCard('#debug_console');
+ });
+
PMA_console.$consoleContent.click(function(event) {
if (event.target == this) {
PMA_consoleInput.focus();
}
});
- $('#pma_console .mid_layer').click(function() {
+ $('#pma_console').find('.mid_layer').click(function() {
PMA_console.hideCard($(this).parent().children('.card'));
});
- $('#pma_bookmarks .switch_button').click(function() {
+ $('#debug_console').find('.switch_button').click(function() {
+ PMA_console.hideCard($(this).closest('.card'));
+ });
+ $('#pma_bookmarks').find('.switch_button').click(function() {
+ PMA_console.hideCard($(this).closest('.card'));
+ });
+ $('#pma_console_options').find('.switch_button').click(function() {
PMA_console.hideCard($(this).closest('.card'));
});
- $('#pma_console_options input[type=checkbox]').change(function() {
+ $('#pma_console_options').find('input[type=checkbox]').change(function() {
PMA_console.updateConfig();
});
- $('#pma_console_options .button.default').click(function() {
+ $('#pma_console_options').find('.button.default').click(function() {
$('#pma_console_options input[name=always_expand]').prop('checked', false);
- $('#pma_console_options input[name=start_history]').prop('checked', false);
- $('#pma_console_options input[name=current_query]').prop('checked', true);
+ $('#pma_console_options').find('input[name=start_history]').prop('checked', false);
+ $('#pma_console_options').find('input[name=current_query]').prop('checked', true);
+ $('#pma_console_options').find('input[name=enter_executes]').prop('checked', false);
+ $('#pma_console_options').find('input[name=dark_theme]').prop('checked', false);
PMA_console.updateConfig();
});
+ $('#pma_console_options').find('input[name=enter_executes]').change(function() {
+ PMA_consoleMessages.showInstructions(PMA_console.config.enterExecutes);
+ });
+
$(document).ajaxComplete(function (event, xhr) {
try {
var data = $.parseJSON(xhr.responseText);
PMA_console.ajaxCallback(data);
} catch (e) {
console.log("Invalid JSON!" + e.message);
- if(AJAX.xhr && AJAX.xhr.status === 0 && AJAX.xhr.statusText !== 'abort') {
+ if (AJAX.xhr && AJAX.xhr.status === 0 && AJAX.xhr.statusText !== 'abort') {
PMA_ajaxShowMessage($('<div />',{class:'error',html:PMA_messages.strRequestFailed+' ( '+AJAX.xhr.statusText+' )'}));
AJAX.active = false;
AJAX.xhr = null;
@@ -208,14 +232,14 @@ var PMA_console = {
* @return void
*/
execute: function(queryString, options) {
- if(typeof(queryString) != 'string' || ! /[a-z]|[A-Z]/.test(queryString)){
+ if (typeof(queryString) != 'string' || ! /[a-z]|[A-Z]/.test(queryString)) {
return;
}
PMA_console.$requestForm.children('textarea').val(queryString);
PMA_console.$requestForm.children('[name=server]').attr('value', PMA_commonParams.get('server'));
- if(options && options.db) {
+ if (options && options.db) {
PMA_console.$requestForm.children('[name=db]').val(options.db);
- if(options.table) {
+ if (options.table) {
PMA_console.$requestForm.children('[name=table]').val(options.table);
} else {
PMA_console.$requestForm.children('[name=table]').val('');
@@ -225,7 +249,7 @@ var PMA_console = {
(PMA_commonParams.get('db').length > 0 ? PMA_commonParams.get('db') : ''));
}
PMA_console.$requestForm.find('[name=profiling]').remove();
- if(options && options.profiling === true) {
+ if (options && options.profiling === true) {
PMA_console.$requestForm.append('<input name="profiling" value="on">');
}
if (! confirmQuery(PMA_console.$requestForm[0], PMA_console.$requestForm.children('textarea')[0])) {
@@ -238,11 +262,11 @@ var PMA_console = {
PMA_reloadNavigation();
},
ajaxCallback: function(data) {
- if(data && data.console_message_id) {
+ if (data && data.console_message_id) {
PMA_consoleMessages.updateQuery(data.console_message_id, data.success,
(data._reloadQuerywindow ? data._reloadQuerywindow : false));
- } else if( data && data._reloadQuerywindow) {
- if(data._reloadQuerywindow.sql_query.length > 0) {
+ } else if ( data && data._reloadQuerywindow) {
+ if (data._reloadQuerywindow.sql_query.length > 0) {
PMA_consoleMessages.appendQuery(data._reloadQuerywindow, 'successed')
.$message.addClass(PMA_console.config.currentQuery ? '' : 'hide');
}
@@ -257,7 +281,7 @@ var PMA_console = {
$.cookie('pma_console_mode', 'collapse');
var pmaConsoleHeight = $.cookie('pma_console_height');
- if(pmaConsoleHeight < 32) {
+ if (pmaConsoleHeight < 32) {
$.cookie('pma_console_height', 92);
}
PMA_console.$consoleToolbar.addClass('collapsed');
@@ -281,13 +305,13 @@ var PMA_console = {
var pmaConsoleHeight = $.cookie('pma_console_height');
- if(pmaConsoleHeight < 32) {
+ if (pmaConsoleHeight < 32) {
$.cookie('pma_console_height', 32);
PMA_console.collapse();
return;
}
PMA_console.$consoleContent.css({display:'block'});
- if(PMA_console.$consoleToolbar.hasClass('collapsed')) {
+ if (PMA_console.$consoleToolbar.hasClass('collapsed')) {
PMA_console.$consoleToolbar.removeClass('collapsed');
}
PMA_console.$consoleAllContents.height(pmaConsoleHeight);
@@ -295,7 +319,7 @@ var PMA_console = {
PMA_console.$consoleContent.animate({'margin-bottom': 0},
'fast', 'easeOutQuart', function() {
$(window).trigger('resize');
- if(inputFocus) {
+ if (inputFocus) {
PMA_consoleInput.focus();
}
});
@@ -348,7 +372,7 @@ var PMA_console = {
*/
showCard: function(cardSelector) {
var $card = null;
- if(typeof(cardSelector) !== 'string') {
+ if (typeof(cardSelector) !== 'string') {
if (cardSelector.length > 0) {
$card = cardSelector;
} else {
@@ -357,13 +381,13 @@ var PMA_console = {
} else {
$card = $("#pma_console " + cardSelector);
}
- if($card.length === 0) {
+ if ($card.length === 0) {
return;
}
$card.parent().children('.mid_layer').show().fadeTo(0, 0.15);
$card.addClass('show');
PMA_consoleInput.blur();
- if($card.parents('.card').length > 0) {
+ if ($card.parents('.card').length > 0) {
PMA_console.showCard($card.parents('.card'));
}
},
@@ -374,10 +398,10 @@ var PMA_console = {
* @return void
*/
hideCard: function($targetCard) {
- if(! $targetCard) {
- $('#pma_console .mid_layer').fadeOut(140);
- $('#pma_console .card').removeClass('show');
- } else if($targetCard.length > 0) {
+ if (! $targetCard) {
+ $('#pma_console').find('.mid_layer').fadeOut(140);
+ $('#pma_console').find('.card').removeClass('show');
+ } else if ($targetCard.length > 0) {
$targetCard.parent().find('.mid_layer').fadeOut(140);
$targetCard.find('.card').removeClass('show');
$targetCard.removeClass('show');
@@ -391,10 +415,18 @@ var PMA_console = {
updateConfig: function() {
PMA_console.config = {
alwaysExpand: $('#pma_console_options input[name=always_expand]').prop('checked'),
- startHistory: $('#pma_console_options input[name=start_history]').prop('checked'),
- currentQuery: $('#pma_console_options input[name=current_query]').prop('checked')
+ startHistory: $('#pma_console_options').find('input[name=start_history]').prop('checked'),
+ currentQuery: $('#pma_console_options').find('input[name=current_query]').prop('checked'),
+ enterExecutes: $('#pma_console_options').find('input[name=enter_executes]').prop('checked'),
+ darkTheme: $('#pma_console_options').find('input[name=dark_theme]').prop('checked')
};
$.cookie('pma_console_config', JSON.stringify(PMA_console.config));
+ /*Setting the dark theme of the console*/
+ if (PMA_console.config.darkTheme) {
+ $('#pma_console').find('>.content').addClass('console_dark_theme');
+ } else {
+ $('#pma_console').find('>.content').removeClass('console_dark_theme');
+ }
},
isSelect: function (queryString) {
var reg_exp = /^SELECT\s+/i;
@@ -417,7 +449,7 @@ var PMA_consoleResizer = {
* @return void
*/
_mousedown: function(event) {
- if($.cookie('pma_console_mode') !== 'show') {
+ if ($.cookie('pma_console_mode') !== 'show') {
return;
}
PMA_consoleResizer._posY = event.pageY;
@@ -425,7 +457,7 @@ var PMA_consoleResizer = {
$(document).mousemove(PMA_consoleResizer._mousemove);
$(document).mouseup(PMA_consoleResizer._mouseup);
// Disable text selection while resizing
- $(document).bind('selectstart', function(){ return false; });
+ $(document).bind('selectstart', function() { return false; });
},
/**
* Mousemove event handler for bind to resizer
@@ -438,13 +470,13 @@ var PMA_consoleResizer = {
}
PMA_consoleResizer._resultHeight = PMA_consoleResizer._height + (PMA_consoleResizer._posY -event.pageY);
// Content min-height is 32, if adjusting height small than it we'll move it out of the page
- if(PMA_consoleResizer._resultHeight <= 32) {
+ if (PMA_consoleResizer._resultHeight <= 32) {
PMA_console.$consoleAllContents.height(32);
PMA_console.$consoleContent.css('margin-bottom', PMA_consoleResizer._resultHeight - 32);
}
else {
// Logic below makes viewable area always at bottom when adjusting height and content already at bottom
- if(PMA_console.$consoleContent.scrollTop() + PMA_console.$consoleContent.innerHeight() + 16
+ if (PMA_console.$consoleContent.scrollTop() + PMA_console.$consoleContent.innerHeight() + 16
>= PMA_console.$consoleContent.prop('scrollHeight')) {
PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight);
PMA_console.scrollBottom();
@@ -471,8 +503,8 @@ var PMA_consoleResizer = {
* @return void
*/
initialize: function() {
- $('#pma_console .toolbar').unbind('mousedown');
- $('#pma_console .toolbar').mousedown(PMA_consoleResizer._mousedown);
+ $('#pma_console').find('.toolbar').unbind('mousedown');
+ $('#pma_console').find('.toolbar').mousedown(PMA_consoleResizer._mousedown);
}
};
@@ -508,32 +540,42 @@ var PMA_consoleInput = {
*/
initialize: function() {
// _cm object can't be reinitialize
- if(PMA_consoleInput._inputs !== null) {
+ if (PMA_consoleInput._inputs !== null) {
return;
}
- if(typeof CodeMirror !== 'undefined') {
+ if (typeof CodeMirror !== 'undefined') {
PMA_consoleInput._codemirror = true;
}
PMA_consoleInput._inputs = [];
if (PMA_consoleInput._codemirror) {
- PMA_consoleInput._inputs.console = CodeMirror($('#pma_console .console_query_input')[0], {
+ PMA_consoleInput._inputs.console = CodeMirror($('#pma_console').find('.console_query_input')[0], {
theme: 'pma',
mode: 'text/x-sql',
lineWrapping: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true}
+ hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
+ gutters: ["CodeMirror-lint-markers"],
+ lint: {
+ "getAnnotations": CodeMirror.sqlLint,
+ "async": true,
+ }
});
PMA_consoleInput._inputs.console.on("inputRead", codemirrorAutocompleteOnInputRead);
PMA_consoleInput._inputs.console.on("keydown", function(instance, event) {
PMA_consoleInput._historyNavigate(event);
});
if ($('#pma_bookmarks').length !== 0) {
- PMA_consoleInput._inputs.bookmark = CodeMirror($('#pma_console .bookmark_add_input')[0], {
+ PMA_consoleInput._inputs.bookmark = CodeMirror($('#pma_console').find('.bookmark_add_input')[0], {
theme: 'pma',
mode: 'text/x-sql',
lineWrapping: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true}
+ hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
+ gutters: ["CodeMirror-lint-markers"],
+ lint: {
+ "getAnnotations": CodeMirror.sqlLint,
+ "async": true,
+ }
});
PMA_consoleInput._inputs.bookmark.on("inputRead", codemirrorAutocompleteOnInputRead);
}
@@ -546,7 +588,7 @@ var PMA_consoleInput = {
$('<textarea>').appendTo('#pma_console .bookmark_add_input');
}
}
- $('#pma_console .console_query_input').keydown(PMA_consoleInput._keydown);
+ $('#pma_console').find('.console_query_input').keydown(PMA_consoleInput._keydown);
},
_historyNavigate: function(event) {
if (event.keyCode == 38 || event.keyCode == 40) {
@@ -603,13 +645,22 @@ var PMA_consoleInput = {
},
/**
* Mousedown event handler for bind to input
- * Shortcut is Ctrl+Enter key
+ * Shortcut is Ctrl+Enter key or just ENTER, depending on console's
+ * configuration.
*
* @return void
*/
_keydown: function(event) {
- if(event.ctrlKey && event.keyCode === 13) {
- PMA_consoleInput.execute();
+ if (PMA_console.config.enterExecutes) {
+ // Enter, but not in combination with Shift (which writes a new line).
+ if (!event.shiftKey && event.keyCode === 13) {
+ PMA_consoleInput.execute();
+ }
+ } else {
+ // Ctrl+Enter
+ if (event.ctrlKey && event.keyCode === 13) {
+ PMA_consoleInput.execute();
+ }
}
},
/**
@@ -714,9 +765,9 @@ var PMA_consoleMessages = {
* @return void
*/
clear: function() {
- $('#pma_console .content .console_message_container .message:not(.welcome)').addClass('hide');
- $('#pma_console .content .console_message_container .message.failed').remove();
- $('#pma_console .content .console_message_container .message.expanded').find('.action.collapse').click();
+ $('#pma_console').find('.content .console_message_container .message:not(.welcome)').addClass('hide');
+ $('#pma_console').find('.content .console_message_container .message.failed').remove();
+ $('#pma_console').find('.content .console_message_container .message.expanded').find('.action.collapse').click();
},
/**
* Used for show history messages
@@ -724,7 +775,7 @@ var PMA_consoleMessages = {
* @return void
*/
showHistory: function() {
- $('#pma_console .content .console_message_container .message.hide').removeClass('hide');
+ $('#pma_console').find('.content .console_message_container .message.hide').removeClass('hide');
},
/**
* Used for getting a perticular history query
@@ -733,7 +784,7 @@ var PMA_consoleMessages = {
* @return string message
*/
getHistory: function(nthLast) {
- var $queries = $('#pma_console .content .console_message_container .query');
+ var $queries = $('#pma_console').find('.content .console_message_container .query');
var length = $queries.length;
var $query = $queries.eq(length - nthLast);
if (!$query || (length - nthLast) < 0) {
@@ -743,6 +794,19 @@ var PMA_consoleMessages = {
}
},
/**
+ * Used to show the correct message depending on which key
+ * combination executes the query (Ctrl+Enter or Enter).
+ *
+ * @param bool enterExecutes Only Enter has to be pressed to execute query.
+ * @return void
+ */
+ showInstructions: function(enterExecutes) {
+ enterExecutes = +enterExecutes || 0; // conversion to int
+ var $welcomeMsg = $('#pma_console').find('.content .console_message_container .message.welcome span');
+ $welcomeMsg.children('[id^=instructions]').hide();
+ $welcomeMsg.children('#instructions-' + enterExecutes).show();
+ },
+ /**
* Used for log new message
*
* @param string msgString Message to show
@@ -750,20 +814,20 @@ var PMA_consoleMessages = {
* @return object, {message_id, $message}
*/
append: function(msgString, msgType) {
- if(typeof(msgString) !== 'string') {
+ if (typeof(msgString) !== 'string') {
return false;
}
// Generate an ID for each message, we can find them later
var msgId = Math.round(Math.random()*(899999999999)+100000000000);
var now = new Date();
var $newMessage =
- $('<div class="message '
- + (PMA_console.config.alwaysExpand ? 'expanded' : 'collapsed')
- +'" msgid="' + msgId + '"><div class="action_content"></div></div>');
+ $('<div class="message ' +
+ (PMA_console.config.alwaysExpand ? 'expanded' : 'collapsed') +
+ '" msgid="' + msgId + '"><div class="action_content"></div></div>');
switch(msgType) {
case 'query':
$newMessage.append('<div class="query highlighted"></div>');
- if(PMA_consoleInput._codemirror) {
+ if (PMA_consoleInput._codemirror) {
CodeMirror.runMode(msgString,
'text/x-sql', $newMessage.children('.query')[0]);
} else {
@@ -793,15 +857,15 @@ var PMA_consoleMessages = {
*/
appendQuery: function(queryData, state) {
var targetMessage = PMA_consoleMessages.append(queryData.sql_query, 'query');
- if(! targetMessage) {
+ if (! targetMessage) {
return false;
}
- if(queryData.db && queryData.table) {
+ if (queryData.db && queryData.table) {
targetMessage.$message.attr('targetdb', queryData.db);
targetMessage.$message.attr('targettable', queryData.table);
targetMessage.$message.find('.text.targetdb span').text(queryData.db);
}
- if(PMA_console.isSelect(queryData.sql_query)) {
+ if (PMA_console.isSelect(queryData.sql_query)) {
targetMessage.$message.addClass('select');
}
switch(state) {
@@ -820,7 +884,7 @@ var PMA_consoleMessages = {
_msgEventBinds: function($targetMessage) {
// Leave unbinded elements, remove binded.
$targetMessage = $targetMessage.filter(':not(.binded)');
- if($targetMessage.length === 0) {
+ if ($targetMessage.length === 0) {
return;
}
$targetMessage.addClass('binded');
@@ -840,8 +904,9 @@ var PMA_consoleMessages = {
$targetMessage.find('.action.requery').click(function () {
var query = $(this).parent().siblings('.query').text();
var $message = $(this).closest('.message');
- if(confirm(PMA_messages.strConsoleRequeryConfirm + '\n'
- + (query.length<100 ? query : query.slice(0, 100) + '...'))) {
+ if (confirm(PMA_messages.strConsoleRequeryConfirm + '\n' +
+ (query.length<100 ? query : query.slice(0, 100) + '...'))
+ ) {
PMA_console.execute(query, {db: $message.attr('targetdb'), table: $message.attr('targettable')});
}
});
@@ -861,7 +926,7 @@ var PMA_consoleMessages = {
});
$targetMessage.find('.action.delete_bookmark').click(function () {
var $message = $(this).closest('.message');
- if(confirm(PMA_messages.strConsoleDeleteBookmarkConfirm + '\n' + $message.find('.bookmark_label').text())) {
+ if (confirm(PMA_messages.strConsoleDeleteBookmarkConfirm + '\n' + $message.find('.bookmark_label').text())) {
$.post('import.php',
{token: PMA_commonParams.get('token'),
server: PMA_commonParams.get('server'),
@@ -886,7 +951,35 @@ var PMA_consoleMessages = {
{db: $message.attr('targetdb'),
table: $message.attr('targettable')});
});
- if(PMA_consoleInput._codemirror) {
+ $targetMessage.find('.action.dbg_show_trace').click(function () {
+ var $message = $(this).closest('.message');
+ if (!$message.find('.trace').length) {
+ PMA_consoleDebug.getQueryDetails(
+ $message.data('queryInfo'),
+ $message.data('totalTime'),
+ $message
+ );
+ PMA_consoleMessages._msgEventBinds($message.find('.message:not(.binded)'));
+ }
+ $message.addClass('show_trace');
+ $message.removeClass('hide_trace');
+ });
+ $targetMessage.find('.action.dbg_hide_trace').click(function () {
+ var $message = $(this).closest('.message');
+ $message.addClass('hide_trace');
+ $message.removeClass('show_trace');
+ });
+ $targetMessage.find('.action.dbg_show_args').click(function () {
+ var $message = $(this).closest('.message');
+ $message.addClass('show_args expanded');
+ $message.removeClass('hide_args collapsed');
+ });
+ $targetMessage.find('.action.dbg_hide_args').click(function () {
+ var $message = $(this).closest('.message');
+ $message.addClass('hide_args collapsed');
+ $message.removeClass('show_args expanded');
+ });
+ if (PMA_consoleInput._codemirror) {
$targetMessage.find('.query:not(.highlighted)').each(function(index, elem) {
CodeMirror.runMode($(elem).text(),
'text/x-sql', elem);
@@ -895,27 +988,27 @@ var PMA_consoleMessages = {
}
},
msgAppend: function(msgId, msgString, msgType) {
- var $targetMessage = $('#pma_console .content .console_message_container .message[msgid=' + msgId +']');
- if($targetMessage.length === 0 || isNaN(parseInt(msgId)) || typeof(msgString) !== 'string') {
+ var $targetMessage = $('#pma_console').find('.content .console_message_container .message[msgid=' + msgId +']');
+ if ($targetMessage.length === 0 || isNaN(parseInt(msgId)) || typeof(msgString) !== 'string') {
return false;
}
$targetMessage.append('<div>' + msgString + '</div>');
},
updateQuery: function(msgId, isSuccessed, queryData) {
- var $targetMessage = $('#pma_console .console_message_container .message[msgid=' + parseInt(msgId) +']');
- if($targetMessage.length === 0 || isNaN(parseInt(msgId))) {
+ var $targetMessage = $('#pma_console').find('.console_message_container .message[msgid=' + parseInt(msgId) +']');
+ if ($targetMessage.length === 0 || isNaN(parseInt(msgId))) {
return false;
}
$targetMessage.removeClass('pending failed successed');
- if(isSuccessed) {
+ if (isSuccessed) {
$targetMessage.addClass('successed');
- if(queryData) {
+ if (queryData) {
$targetMessage.children('.query').text('');
$targetMessage.removeClass('select');
- if(PMA_console.isSelect(queryData.sql_query)) {
+ if (PMA_console.isSelect(queryData.sql_query)) {
$targetMessage.addClass('select');
}
- if(PMA_consoleInput._codemirror) {
+ if (PMA_consoleInput._codemirror) {
CodeMirror.runMode(queryData.sql_query, 'text/x-sql', $targetMessage.children('.query')[0]);
} else {
$targetMessage.children('.query').text(queryData.sql_query);
@@ -934,10 +1027,11 @@ var PMA_consoleMessages = {
* @return void
*/
initialize: function() {
- PMA_consoleMessages._msgEventBinds($('#pma_console .message:not(.binded)'));
- if(PMA_console.config.startHistory) {
+ PMA_consoleMessages._msgEventBinds($('#pma_console').find('.message:not(.binded)'));
+ if (PMA_console.config.startHistory) {
PMA_consoleMessages.showHistory();
}
+ PMA_consoleMessages.showInstructions(PMA_console.config.enterExecutes);
}
};
@@ -948,19 +1042,19 @@ var PMA_consoleMessages = {
var PMA_consoleBookmarks = {
_bookmarks: [],
addBookmark: function (queryString, targetDb, label, isShared, id) {
- $('#pma_bookmarks .add [name=shared]').prop('checked', false);
- $('#pma_bookmarks .add [name=label]').val('');
- $('#pma_bookmarks .add [name=targetdb]').val('');
- $('#pma_bookmarks .add [name=id_bookmark]').val('');
+ $('#pma_bookmarks').find('.add [name=shared]').prop('checked', false);
+ $('#pma_bookmarks').find('.add [name=label]').val('');
+ $('#pma_bookmarks').find('.add [name=targetdb]').val('');
+ $('#pma_bookmarks').find('.add [name=id_bookmark]').val('');
PMA_consoleInput.setText('', 'bookmark');
switch(arguments.length) {
case 4:
- $('#pma_bookmarks .add [name=shared]').prop('checked', isShared);
+ $('#pma_bookmarks').find('.add [name=shared]').prop('checked', isShared);
case 3:
- $('#pma_bookmarks .add [name=label]').val(label);
+ $('#pma_bookmarks').find('.add [name=label]').val(label);
case 2:
- $('#pma_bookmarks .add [name=targetdb]').val(targetDb);
+ $('#pma_bookmarks').find('.add [name=targetdb]').val(targetDb);
case 1:
PMA_consoleInput.setText(queryString, 'bookmark');
default:
@@ -974,9 +1068,9 @@ var PMA_consoleBookmarks = {
server: PMA_commonParams.get('server'),
console_bookmark_refresh: 'refresh'},
function(data) {
- if(data.console_message_bookmark) {
- $('#pma_bookmarks .content.bookmark').html(data.console_message_bookmark);
- PMA_consoleMessages._msgEventBinds($('#pma_bookmarks .message:not(.binded)'));
+ if (data.console_message_bookmark) {
+ $('#pma_bookmarks').find('.content.bookmark').html(data.console_message_bookmark);
+ PMA_consoleMessages._msgEventBinds($('#pma_bookmarks').find('.message:not(.binded)'));
}
});
},
@@ -987,17 +1081,17 @@ var PMA_consoleBookmarks = {
* @return void
*/
initialize: function() {
- if($('#pma_bookmarks').length === 0) {
+ if ($('#pma_bookmarks').length === 0) {
return;
}
- $('#pma_console .button.bookmarks').click(function() {
+ $('#pma_console').find('.button.bookmarks').click(function() {
PMA_console.showCard('#pma_bookmarks');
});
- $('#pma_bookmarks .button.add').click(function() {
+ $('#pma_bookmarks').find('.button.add').click(function() {
PMA_console.showCard('#pma_bookmarks .card.add');
});
- $('#pma_bookmarks .card.add [name=submit]').click(function () {
- if ($('#pma_bookmarks .card.add [name=label]').val().length === 0
+ $('#pma_bookmarks').find('.card.add [name=submit]').click(function () {
+ if ($('#pma_bookmarks').find('.card.add [name=label]').val().length === 0
|| PMA_consoleInput.getText('bookmark').length === 0)
{
alert(PMA_messages.strFormEmpty);
@@ -1008,24 +1102,433 @@ var PMA_consoleBookmarks = {
{token: PMA_commonParams.get('token'),
ajax_request: true,
console_bookmark_add: 'true',
- label: $('#pma_bookmarks .card.add [name=label]').val(),
+ label: $('#pma_bookmarks').find('.card.add [name=label]').val(),
server: PMA_commonParams.get('server'),
- db: $('#pma_bookmarks .card.add [name=targetdb]').val(),
+ db: $('#pma_bookmarks').find('.card.add [name=targetdb]').val(),
bookmark_query: PMA_consoleInput.getText('bookmark'),
- shared: $('#pma_bookmarks .card.add [name=shared]').prop('checked')},
+ shared: $('#pma_bookmarks').find('.card.add [name=shared]').prop('checked')},
function () {
PMA_consoleBookmarks.refresh();
- $('#pma_bookmarks .card.add [name=submit]').prop('disabled', false);
- PMA_console.hideCard($('#pma_bookmarks .card.add'));
+ $('#pma_bookmarks').find('.card.add [name=submit]').prop('disabled', false);
+ PMA_console.hideCard($('#pma_bookmarks').find('.card.add'));
});
});
- $('#pma_console .button.refresh').click(function() {
+ $('#pma_console').find('.button.refresh').click(function() {
PMA_consoleBookmarks.refresh();
});
}
};
-/**
+var PMA_consoleDebug;
+PMA_consoleDebug = {
+ _config: {
+ groupQueries: false,
+ orderBy: 'exec', // Possible 'exec' => Execution order, 'time' => Time taken, 'count'
+ order: 'asc' // Possible 'asc', 'desc'
+ },
+ _lastDebugInfo: {
+ debugInfo: null,
+ url: null
+ },
+ initialize: function () {
+ // Try to get debug info after every AJAX request
+ $(document).ajaxSuccess(function (event, xhr, settings, data) {
+ if (data._debug) {
+ PMA_consoleDebug.showLog(data._debug, settings.url);
+ }
+ });
+
+ // Initialize config
+ this._initConfig();
+
+ if (this.configParam('groupQueries')) {
+ $('#debug_console').addClass('grouped');
+ } else {
+ $('#debug_console').addClass('ungrouped');
+ if (PMA_consoleDebug.configParam('orderBy') == 'count') {
+ $('#debug_console').find('.button.order_by.sort_exec').addClass('active');
+ }
+ }
+ var orderBy = this.configParam('orderBy');
+ var order = this.configParam('order');
+ $('#debug_console').find('.button.order_by.sort_' + orderBy).addClass('active');
+ $('#debug_console').find('.button.order.order_' + order).addClass('active');
+
+ // Initialize actions in toolbar
+ $('#debug_console').find('.button.group_queries').click(function () {
+ $('#debug_console').addClass('grouped');
+ $('#debug_console').removeClass('ungrouped');
+ PMA_consoleDebug.configParam('groupQueries', true);
+ PMA_consoleDebug.refresh();
+ if (PMA_consoleDebug.configParam('orderBy') == 'count') {
+ $('#debug_console').find('.button.order_by.sort_exec').removeClass('active');
+ }
+ });
+ $('#debug_console').find('.button.ungroup_queries').click(function () {
+ $('#debug_console').addClass('ungrouped');
+ $('#debug_console').removeClass('grouped');
+ PMA_consoleDebug.configParam('groupQueries', false);
+ PMA_consoleDebug.refresh();
+ if (PMA_consoleDebug.configParam('orderBy') == 'count') {
+ $('#debug_console').find('.button.order_by.sort_exec').addClass('active');
+ }
+ });
+ $('#debug_console').find('.button.order_by').click(function () {
+ var $this = $(this);
+ $('#debug_console').find('.button.order_by').removeClass('active');
+ $this.addClass('active');
+ if ($this.hasClass('sort_time')) {
+ PMA_consoleDebug.configParam('orderBy', 'time');
+ } else if ($this.hasClass('sort_exec')) {
+ PMA_consoleDebug.configParam('orderBy', 'exec');
+ } else if ($this.hasClass('sort_count')) {
+ PMA_consoleDebug.configParam('orderBy', 'count');
+ }
+ PMA_consoleDebug.refresh();
+ });
+ $('#debug_console').find('.button.order').click(function () {
+ var $this = $(this);
+ $('#debug_console').find('.button.order').removeClass('active');
+ $this.addClass('active');
+ if ($this.hasClass('order_asc')) {
+ PMA_consoleDebug.configParam('order', 'asc');
+ } else if ($this.hasClass('order_desc')) {
+ PMA_consoleDebug.configParam('order', 'desc');
+ }
+ PMA_consoleDebug.refresh();
+ });
+
+ // Show SQL debug info for first page load
+ if (typeof debugSQLInfo !== 'undefined' && debugSQLInfo !== 'null') {
+ $('#pma_console').find('.button.debug').removeClass('hide');
+ }
+ else {
+ return;
+ }
+ PMA_consoleDebug.showLog(debugSQLInfo);
+ },
+ _initConfig: function () {
+ var config = JSON.parse($.cookie('pma_console_dbg_config'));
+ if (config) {
+ for (var name in config) {
+ if (config.hasOwnProperty(name)) {
+ this._config[name] = config[name];
+ }
+ }
+ }
+ },
+ configParam: function (name, value) {
+ if (typeof value === 'undefined') {
+ return this._config[name];
+ }
+ this._config[name] = value;
+ $.cookie('pma_console_dbg_config', JSON.stringify(this._config));
+ return value;
+ },
+ _formatFunctionCall: function (dbgStep) {
+ var functionName = '';
+ if ('class' in dbgStep) {
+ functionName += dbgStep.class;
+ functionName += dbgStep.type;
+ }
+ functionName += dbgStep.function;
+ if (dbgStep.args.length) {
+ functionName += '(...)';
+ } else {
+ functionName += '()';
+ }
+ return functionName;
+ },
+ _formatFunctionArgs: function (dbgStep) {
+ var $args = $('<div>');
+ if (dbgStep.args.length) {
+ $args.append('<div class="message welcome">')
+ .append(
+ $('<div class="message welcome">')
+ .text(
+ PMA_sprintf(
+ PMA_messages.strConsoleDebugArgsSummary,
+ dbgStep.args.length
+ )
+ )
+ );
+ for (var i = 0; i < dbgStep.args.length; i++) {
+ $args.append(
+ $('<div class="message">')
+ .html(
+ '<pre>' +
+ escapeHtml(JSON.stringify(dbgStep.args[i], null, " ")) +
+ '</pre>'
+ )
+ );
+ }
+ }
+ return $args;
+ },
+ _formatFileName: function (dbgStep) {
+ var fileName = '';
+ if ('file' in dbgStep) {
+ fileName += dbgStep.file;
+ fileName += '#' + dbgStep.line;
+ }
+ return fileName;
+ },
+ _formatBackTrace: function (dbgTrace) {
+ var $traceElem = $('<div class="trace">');
+ $traceElem.append(
+ $('<div class="message welcome">')
+ );
+ var step, $stepElem;
+ for (var stepId in dbgTrace) {
+ if (dbgTrace.hasOwnProperty(stepId)) {
+ step = dbgTrace[stepId];
+ if (!Array.isArray(step) && typeof step !== 'object') {
+ $stepElem =
+ $('<div class="message traceStep collapsed hide_args">')
+ .append(
+ $('<span>').text(step)
+ );
+ } else {
+ if (typeof step.args === 'string' && step.args) {
+ step.args = [step.args];
+ }
+ $stepElem =
+ $('<div class="message traceStep collapsed hide_args">')
+ .append(
+ $('<span class="function">').text(this._formatFunctionCall(step))
+ )
+ .append(
+ $('<span class="file">').text(this._formatFileName(step))
+ );
+ if (step.args.length) {
+ $stepElem
+ .append(
+ $('<span class="args">').html(this._formatFunctionArgs(step))
+ )
+ .prepend(
+ $('<div class="action_content">')
+ .append(
+ '<span class="action dbg_show_args">' +
+ PMA_messages.strConsoleDebugShowArgs +
+ '</span> '
+ )
+ .append(
+ '<span class="action dbg_hide_args">' +
+ PMA_messages.strConsoleDebugHideArgs +
+ '</span> '
+ )
+ );
+ }
+ }
+ $traceElem.append($stepElem);
+ }
+ }
+ return $traceElem;
+ },
+ _formatQueryOrGroup: function (queryInfo, totalTime) {
+ var grouped, queryText, queryTime, count, i;
+ if (Array.isArray(queryInfo)) {
+ // It is grouped
+ grouped = true;
+
+ queryText = queryInfo[0].query;
+
+ queryTime = 0;
+ for (i in queryInfo) {
+ queryTime += queryInfo[i].time;
+ }
+
+ count = queryInfo.length;
+ } else {
+ queryText = queryInfo.query;
+ queryTime = queryInfo.time;
+ }
+
+ var $query = $('<div class="message collapsed hide_trace">')
+ .append(
+ $('#debug_console').find('.templates .debug_query').clone()
+ )
+ .append(
+ $('<div class="query">')
+ .text(queryText)
+ )
+ .data('queryInfo', queryInfo)
+ .data('totalTime', totalTime);
+ if (grouped) {
+ $query.find('.text.count').removeClass('hide');
+ $query.find('.text.count span').text(count);
+ }
+ $query.find('.text.time span').text(queryTime + 's (' + ((queryTime * 100) / totalTime).toFixed(3) + '%)');
+
+ return $query;
+ },
+ _appendQueryExtraInfo: function (query, $elem) {
+ if ('error' in query) {
+ $elem.append(
+ $('<div>').html(query.error)
+ );
+ }
+ $elem.append(this._formatBackTrace(query.trace));
+ },
+ getQueryDetails: function (queryInfo, totalTime, $query) {
+ if (Array.isArray(queryInfo)) {
+ var $singleQuery;
+ for (var i in queryInfo) {
+ $singleQuery = $('<div class="message welcome trace">')
+ .text((parseInt(i) + 1) + '.')
+ .append(
+ $('<span class="time">').text(
+ PMA_messages.strConsoleDebugTimeTaken +
+ ' ' + queryInfo[i].time + 's' +
+ ' (' + ((queryInfo[i].time * 100) / totalTime).toFixed(3) + '%)'
+ )
+ );
+ this._appendQueryExtraInfo(queryInfo[i], $singleQuery);
+ $query
+ .append('<div class="message welcome trace">')
+ .append($singleQuery);
+ }
+ } else {
+ this._appendQueryExtraInfo(queryInfo, $query);
+ }
+ },
+ showLog: function (debugInfo, url) {
+ this._lastDebugInfo.debugInfo = debugInfo;
+ this._lastDebugInfo.url = url;
+
+ $('#debug_console').find('.debugLog').empty();
+ $("#debug_console").find(".debug>.welcome").empty();
+
+ var debugJson = false, i;
+ if (typeof debugInfo === "object" && 'queries' in debugInfo) {
+ // Copy it to debugJson, so that it doesn't get changed
+ if (!('queries' in debugInfo)) {
+ debugJson = false;
+ } else {
+ debugJson = {queries: []};
+ for (i in debugInfo.queries) {
+ debugJson.queries[i] = debugInfo.queries[i];
+ }
+ }
+ } else if (typeof debugInfo === "string") {
+ try {
+ debugJson = JSON.parse(debugInfo);
+ } catch (e) {
+ debugJson = false;
+ }
+ if (debugJson && !('queries' in debugJson)) {
+ debugJson = false;
+ }
+ }
+ if (debugJson === false) {
+ $("#debug_console").find(".debug>.welcome").text(
+ PMA_messages.strConsoleDebugError
+ );
+ return;
+ }
+ var allQueries = debugJson.queries;
+ var uniqueQueries = {};
+
+ var totalExec = allQueries.length;
+
+ // Calculate total time and make unique query array
+ var totalTime = 0;
+ for (i = 0; i < totalExec; ++i) {
+ totalTime += allQueries[i].time;
+ if (!(allQueries[i].hash in uniqueQueries)) {
+ uniqueQueries[allQueries[i].hash] = [];
+ }
+ uniqueQueries[allQueries[i].hash].push(allQueries[i]);
+ }
+ // Count total unique queries, convert uniqueQueries to Array
+ var totalUnique = 0, uniqueArray = [];
+ for (var hash in uniqueQueries) {
+ if (uniqueQueries.hasOwnProperty(hash)) {
+ ++totalUnique;
+ uniqueArray.push(uniqueQueries[hash]);
+ }
+ }
+ uniqueQueries = uniqueArray;
+ // Show summary
+ $("#debug_console").find(".debug>.welcome").append(
+ $('<span class="debug_summary">').text(
+ PMA_sprintf(
+ PMA_messages.strConsoleDebugSummary,
+ totalUnique,
+ totalExec,
+ totalTime
+ )
+ )
+ );
+ if (url) {
+ $("#debug_console").find(".debug>.welcome").append(
+ $('<span class="script_name">').text(url.split('?')[0])
+ );
+ }
+
+ // For sorting queries
+ function sortByTime(a, b) {
+ var order = ((PMA_consoleDebug.configParam('order') == 'asc') ? 1 : -1);
+ if (Array.isArray(a) && Array.isArray(b)) {
+ // It is grouped
+ var timeA = 0, timeB = 0, i;
+ for (i in a) {
+ timeA += a[i].time;
+ }
+ for (i in b) {
+ timeB += b[i].time;
+ }
+ return (timeA - timeB) * order;
+ } else {
+ return (a.time - b.time) * order;
+ }
+ }
+
+ function sortByCount(a, b) {
+ var order = ((PMA_consoleDebug.configParam('order') == 'asc') ? 1 : -1);
+ return (a.length - b.length) * order;
+ }
+
+ var orderBy = this.configParam('orderBy');
+ var order = PMA_consoleDebug.configParam('order');
+
+ if (this.configParam('groupQueries')) {
+ // Sort queries
+ if (orderBy == 'time') {
+ uniqueQueries.sort(sortByTime);
+ } else if (orderBy == 'count') {
+ uniqueQueries.sort(sortByCount);
+ } else if (orderBy == 'exec' && order == 'desc') {
+ uniqueQueries.reverse();
+ }
+ for (i in uniqueQueries) {
+ if (orderBy == 'time') {
+ uniqueQueries[i].sort(sortByTime);
+ } else if (orderBy == 'exec' && order == 'desc') {
+ uniqueQueries[i].reverse();
+ }
+ $('#debug_console').find('.debugLog').append(this._formatQueryOrGroup(uniqueQueries[i], totalTime));
+ }
+ } else {
+ if (orderBy == 'time') {
+ allQueries.sort(sortByTime);
+ } else if (order == 'desc') {
+ allQueries.reverse();
+ }
+ for (i = 0; i < totalExec; ++i) {
+ $('#debug_console').find('.debugLog').append(this._formatQueryOrGroup(allQueries[i], totalTime));
+ }
+ }
+
+ PMA_consoleMessages._msgEventBinds($('#debug_console').find('.message:not(.binded)'));
+ },
+ refresh: function () {
+ var last = this._lastDebugInfo;
+ PMA_consoleDebug.showLog(last.debugInfo, last.url);
+ }
+};
+
+/**s
* Executed on page load
*/
$(function () {
diff --git a/js/db_central_columns.js b/js/db_central_columns.js
index feebd76953..258eb0c884 100644
--- a/js/db_central_columns.js
+++ b/js/db_central_columns.js
@@ -12,6 +12,7 @@
* Actions ajaxified here:
* Inline Edit and save of a result row
* Delete a row
+ * Multiple edit and delete option
*
*/
@@ -24,14 +25,19 @@ AJAX.registerTeardown('db_central_columns.js', function () {
$('.edit_cancel_form').unbind('click');
$('#table-select').unbind('change');
$('#column-select').unbind('change');
- $("#add_col_div>a").unbind('click');
+ $("#add_col_div").find(">a").unbind('click');
$('#add_new').unbind('submit');
+ $('#multi_edit_central_columns').unbind('submit');
$("select.default_type").unbind('change');
+ $("button[name='delete_central_columns']").unbind('click');
+ $("button[name='edit_central_columns']").unbind('click');
});
AJAX.registerOnload('db_central_columns.js', function () {
- $('#tableslistcontainer input,#tableslistcontainer select,.default_value,.open_enum_editor').hide();
- if ($('#table_columns tbody tr').length > 0) {
+ $('#tableslistcontainer input,#tableslistcontainer select,#tableslistcontainer .default_value,#tableslistcontainer .open_enum_editor').hide();
+ $('#tableslistcontainer').find('.checkall').show();
+ $('#tableslistcontainer').find('.checkall_box').show();
+ if ($('#table_columns').find('tbody tr').length > 0) {
$("#table_columns").tablesorter({
headers: {
0: {sorter: false},
@@ -40,12 +46,43 @@ AJAX.registerOnload('db_central_columns.js', function () {
}
});
}
- $('#add_new td').each(function(){
+ $('#tableslistcontainer').find('button[name="delete_central_columns"]').click(function(event){
+ event.preventDefault();
+ var multi_delete_columns = $('.checkall:checkbox:checked').serialize();
+ if(multi_delete_columns === ''){
+ PMA_ajaxShowMessage(PMA_messages.strRadioUnchecked);
+ return false;
+ }
+ PMA_ajaxShowMessage();
+ $("#del_col_name").val(multi_delete_columns);
+ $("#del_form").submit();
+ });
+ $('#tableslistcontainer').find('button[name="edit_central_columns"]').click(function(event){
+ event.preventDefault();
+ var editColumnList = $('.checkall:checkbox:checked').serialize();
+ if(editColumnList === ''){
+ PMA_ajaxShowMessage(PMA_messages.strRadioUnchecked);
+ return false;
+ }
+ var editColumnData = editColumnList+ '&edit_central_columns_page=true&ajax_request=true&ajax_page_request=true&token='+PMA_commonParams.get('token')+'&db='+PMA_commonParams.get('db');
+ PMA_ajaxShowMessage();
+ AJAX.source = $(this);
+ $.get('db_central_columns.php', editColumnData, AJAX.responseHandler);
+ });
+ $('#multi_edit_central_columns').submit(function(event){
+ event.preventDefault();
+ event.stopPropagation();
+ var multi_column_edit_data = $("#multi_edit_central_columns").serialize()+'&multi_edit_central_column_save=true&ajax_request=true&ajax_page_request=true&token='+PMA_commonParams.get('token')+'&db='+PMA_commonParams.get('db');
+ PMA_ajaxShowMessage();
+ AJAX.source = $(this);
+ $.post('db_central_columns.php', multi_column_edit_data, AJAX.responseHandler);
+ });
+ $('#add_new').find('td').each(function(){
if ($(this).attr('name') !== 'undefined') {
$(this).find('input,select:first').attr('name', $(this).attr('name'));
}
});
- $("#add_new #field_0_0").attr('required','required');
+ $("#field_0_0").attr('required','required');
$('#add_new input[type="text"], #add_new input[type="number"], #add_new select')
.css({
'width' : '10em',
@@ -60,15 +97,13 @@ AJAX.registerOnload('db_central_columns.js', function () {
$.uiTableFilter($("#table_columns"), $(this).val(), cols, null, "td span");
});
$('.edit').click(function() {
- rownum = $(this).parent().data('rownum');
+ var rownum = $(this).parent().data('rownum');
$('#save_' + rownum).show();
$(this).hide();
$('#f_' + rownum + ' td span').hide();
$('#f_' + rownum + ' input, #f_' + rownum + ' select, #f_' + rownum + ' .open_enum_editor').show();
- var extra_val = $('#f_' + rownum + ' td[name=col_extra] span').html();
var attribute_val = $('#f_' + rownum + ' td[name=col_attribute] span').html();
$('#f_' + rownum + ' select[name=field_attribute\\['+ rownum +'\\] ] option[value="' + attribute_val + '"]').attr("selected","selected");
- $('#f_' + rownum + ' select[name=col_extra] option[value="' + extra_val + '"]').attr("selected","selected");
if($('#f_' + rownum + ' .default_type').val() === 'USER_DEFINED') {
$('#f_' + rownum + ' .default_type').siblings('.default_value').show();
} else {
@@ -78,28 +113,29 @@ AJAX.registerOnload('db_central_columns.js', function () {
$(".del_row").click(function (event) {
event.preventDefault();
event.stopPropagation();
- $td = $(this);
+ var $td = $(this);
var question = PMA_messages.strDeleteCentralColumnWarning;
$td.PMA_confirm(question, null, function (url) {
- rownum = $td.data('rownum');
- $("#del_col_name").val($('#f_' + rownum + ' td[name=col_name] span').html());
+ var rownum = $td.data('rownum');
+ $("#del_col_name").val("selected_fld%5B%5D="+$('#checkbox_row_' + rownum ).val());
$("#del_form").submit();
});
});
$('.edit_cancel_form').click(function(event) {
event.preventDefault();
event.stopPropagation();
- rownum = $(this).data('rownum');
+ var rownum = $(this).data('rownum');
$('#save_' + rownum).hide();
$('#edit_' + rownum).show();
$('#f_' + rownum + ' td span').show();
$('#f_' + rownum + ' input, #f_' + rownum + ' select,#f_'+rownum+' .default_value, #f_' + rownum + ' .open_enum_editor').hide();
+ $('#tableslistcontainer').find('.checkall').show();
});
$('.edit_save_form').click(function(event) {
//alert(1);
event.preventDefault();
event.stopPropagation();
- rownum = $(this).data('rownum');
+ var rownum = $(this).data('rownum');
$('#f_' + rownum + ' td').each(function() {
if ($(this).attr('name') !== 'undefined') {
$(this).find(':input[type!="hidden"],select:first')
@@ -133,14 +169,15 @@ AJAX.registerOnload('db_central_columns.js', function () {
$('#f_' + rownum + ' td[name=col_length] span').text($('#f_' + rownum + ' input[name=col_length]').val()).html();
$('#f_' + rownum + ' td[name=collation] span').text($('#f_' + rownum + ' select[name=collation]').val()).html();
$('#f_' + rownum + ' td[name=col_attribute] span').text($('#f_' + rownum + ' select[name=col_attribute]').val()).html();
- $('#f_' + rownum + ' td[name=col_isNull] span').text($('#f_' + rownum + ' input[name=col_isNull]').val()).html();
- $('#f_' + rownum + ' td[name=col_extra] span').text($('#f_' + rownum + ' select[name=col_extra]').val()).html();
+ $('#f_' + rownum + ' td[name=col_isNull] span').text($('#f_' + rownum +' input[name=col_isNull]').is(":checked")?"Yes":"No").html();
+ $('#f_' + rownum + ' td[name=col_extra] span').text($('#f_' + rownum + ' input[name=col_extra]').is(":checked") ? "auto_increment" : "").html();
$('#f_' + rownum + ' td[name=col_default] span').text($('#f_' + rownum + ' :input[name=col_default]').val()).html();
}
$('#save_' + rownum).hide();
$('#edit_' + rownum).show();
$('#f_' + rownum + ' td span').show();
$('#f_' + rownum + ' input, #f_' + rownum + ' select,#f_' + rownum + ' .default_value, #f_' + rownum + ' .open_enum_editor').hide();
+ $('#tableslistcontainer').find('.checkall').show();
},
error: function() {
PMA_ajaxShowMessage(
@@ -154,7 +191,7 @@ AJAX.registerOnload('db_central_columns.js', function () {
});
$('#table-select').change(function(e) {
var selectvalue = $(this).val();
- var default_column_select = $('#column-select option:first');
+ var default_column_select = $('#column-select').find('option:first');
var href = "db_central_columns.php";
var params = {
'ajax_request' : true,
@@ -178,18 +215,19 @@ AJAX.registerOnload('db_central_columns.js', function () {
$("#add_column").submit();
}
});
- $("#add_col_div>a").click(function(event){
+ $("#add_col_div").find(">a").click(function(event){
$('#add_new').slideToggle("slow");
- if($("#add_col_div>a span").html() === '+') {
- $("#add_col_div>a span").html('-');
+ var $addColDivLinkSpan = $("#add_col_div").find(">a span");
+ if($addColDivLinkSpan.html() === '+') {
+ $addColDivLinkSpan.html('-');
} else {
- $("#add_col_div>a span").html('+');
+ $addColDivLinkSpan.html('+');
}
});
$('#add_new').submit(function(event){
$('#add_new').toggle();
});
- $("select.default_type").change(function () {
+ $("#tableslistcontainer").find("select.default_type").change(function () {
if ($(this).val() === 'USER_DEFINED') {
$(this).siblings('.default_value').attr('name','col_default');
$(this).attr('name','col_default_sel');
diff --git a/js/db_qbe.js b/js/db_qbe.js
index 94ef14623a..4b6854912e 100644
--- a/js/db_qbe.js
+++ b/js/db_qbe.js
@@ -20,6 +20,7 @@
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('db_qbe.js', function () {
+ $(document).off('change', 'select[name^=criteriaColumn]');
$(document).off('change', "#searchId");
$(document).off('click', "#saveSearch");
$(document).off('click', "#updateSearch");
@@ -28,6 +29,18 @@ AJAX.registerTeardown('db_qbe.js', function () {
AJAX.registerOnload('db_qbe.js', function () {
+ PMA_getSQLEditor($('#textSqlquery'), {}, 'both');
+
+ /**
+ * Ajax handler to check the corresponding 'show' checkbox when column is selected
+ */
+ $(document).on('change', 'select[name^=criteriaColumn]', function (event) {
+ if ($(this).val()) {
+ var index = (/\d+/).exec($(this).attr('name'));
+ $('input[name=criteriaShow\\[' + index + '\\]]').prop('checked', true);
+ }
+ });
+
/**
* Ajax event handlers for 'Select saved search'
*/
@@ -39,7 +52,7 @@ AJAX.registerOnload('db_qbe.js', function () {
/**
* Ajax event handlers for 'Create bookmark'
*/
- $(document).on('click', "#saveSearch", function (event) {
+ $(document).on('click', "#saveSearch", function () {
$('#action').val('create');
});
@@ -54,11 +67,11 @@ AJAX.registerOnload('db_qbe.js', function () {
* Ajax event handlers for 'Delete bookmark'
*/
$(document).on('click', "#deleteSearch", function (event) {
- var question = PMA_sprintf(PMA_messages.strConfirmDeleteQBESearch, $("#searchId option:selected").text());
+ var question = PMA_sprintf(PMA_messages.strConfirmDeleteQBESearch, $("#searchId").find("option:selected").text());
if (!confirm(question)) {
return false;
}
$('#action').val('delete');
});
-});
+}); \ No newline at end of file
diff --git a/js/db_structure.js b/js/db_structure.js
index 0b89dd64ea..062867e4ca 100644
--- a/js/db_structure.js
+++ b/js/db_structure.js
@@ -26,6 +26,7 @@ AJAX.registerTeardown('db_structure.js', function () {
$(document).off('click', "a.drop_table_anchor.ajax");
$(document).off('click', '#real_end_input');
$(document).off('click', "a.favorite_table_anchor.ajax");
+ $(document).off('click', '#printView');
$('a.real_row_count').off('click');
$('a.row_count_sum').off('click');
$('select[name=submit_mult]').unbind('change');
@@ -48,7 +49,7 @@ function PMA_adjustTotals() {
/**
* @var $allTr jQuery object that references all the rows in the list of tables
*/
- var $allTr = $("#tablesForm table.data tbody:first tr");
+ var $allTr = $("#tablesForm").find("table.data tbody:first tr");
// New summary values for the table
var tableSum = $allTr.size();
var rowsSum = 0;
@@ -126,7 +127,11 @@ function PMA_adjustTotals() {
// Update summary with new data
var $summary = $("#tbl_summary_row");
$summary.find('.tbl_num').text(PMA_sprintf(PMA_messages.strNTables, tableSum));
- $summary.find('.row_count_sum').text(strRowSum);
+ if (rowSumApproximated) {
+ $summary.find('.row_count_sum').text(strRowSum);
+ } else {
+ $summary.find('.tbl_rows').text(strRowSum);
+ }
$summary.find('.tbl_size').text(sizeSum + " " + byteUnits[size_magnitude]);
$summary.find('.tbl_overhead').text(overheadSum + " " + byteUnits[overhead_magnitude]);
}
@@ -137,7 +142,7 @@ function PMA_adjustTotals() {
*/
function PMA_fetchRealRowCount($target)
{
- var $throbber = $('#pma_navigation .throbber')
+ var $throbber = $('#pma_navigation').find('.throbber')
.first()
.clone()
.css({visibility: 'visible', display: 'inline-block'})
@@ -178,31 +183,6 @@ function PMA_fetchRealRowCount($target)
}
AJAX.registerOnload('db_structure.js', function () {
- /**
- * Handler for the print view multisubmit.
- * All other multi submits can be handled via ajax, but this one needs
- * special treatment as the results need to open in another browser window
- */
- $('#tablesForm').submit(function (event) {
- var $form = $(this);
- if ($form.find('select[name=submit_mult]').val() === 'print') {
- event.preventDefault();
- event.stopPropagation();
- $('form#clone').remove();
- var $clone = $form
- .clone()
- .hide()
- .appendTo('body');
- $clone
- .find('select[name=submit_mult]')
- .val('print');
- $clone
- .attr('target', 'printview')
- .attr('id', 'clone')
- .submit();
- }
- });
-
/**
* function to open the confirmation dialog for making table consistent with central list
*
@@ -264,13 +244,16 @@ AJAX.registerOnload('db_structure.js', function () {
* @var question String containing the question to be asked for confirmation
*/
var question = PMA_messages.strTruncateTableStrongWarning + ' ' +
- PMA_sprintf(PMA_messages.strDoYouReally, 'TRUNCATE ' + escapeHtml(curr_table_name));
+ PMA_sprintf(PMA_messages.strDoYouReally, 'TRUNCATE ' + escapeHtml(curr_table_name)) +
+ getForeignKeyCheckboxLoader();
$this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function (url) {
PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
- $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true}, function (data) {
+ var params = getJSConfirmCommonParam(this);
+
+ $.get(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxShowMessage(data.message);
// Adjust table statistics
@@ -290,7 +273,7 @@ AJAX.registerOnload('db_structure.js', function () {
PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
}
}); // end $.get()
- }); //end $.PMA_confirm()
+ }, loadForeignKeyCheckbox); //end $.PMA_confirm()
}); //end of Truncate Table Ajax action
/**
@@ -325,12 +308,15 @@ AJAX.registerOnload('db_structure.js', function () {
question =
PMA_sprintf(PMA_messages.strDoYouReally, 'DROP VIEW ' + escapeHtml(curr_table_name));
}
+ question += getForeignKeyCheckboxLoader();
$this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function (url) {
var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
- $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true}, function (data) {
+ var params = getJSConfirmCommonParam(this);
+
+ $.get(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxShowMessage(data.message);
toggleRowColors($curr_row.next());
@@ -342,9 +328,19 @@ AJAX.registerOnload('db_structure.js', function () {
PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
}
}); // end $.get()
- }); // end $.PMA_confirm()
+ }, loadForeignKeyCheckbox); // end $.PMA_confirm()
}); //end of Drop Table Ajax action
+ /**
+ * Attach Event Handler for 'Print View'
+ */
+ $(document).on('click', "#printView", function (event) {
+ event.preventDefault();
+
+ // Print the page
+ printPage();
+ }); //end of Print View action
+
//Calculate Real End for InnoDB
/**
* Ajax Event handler for calculating the real end for a InnoDB table
@@ -364,11 +360,6 @@ AJAX.registerOnload('db_structure.js', function () {
return false;
}); //end Calculate Real End for InnoDB
- PMA_tooltip(
- $("select[name*='funcs']"),
- 'select',
- PMA_messages.strFunctionHint
- );
// Add tooltip to favorite icons.
$(".favorite_table_anchor").each(function () {
PMA_tooltip(
diff --git a/js/db_tracking.js b/js/db_tracking.js
index 5b40084bce..934746aa0b 100644
--- a/js/db_tracking.js
+++ b/js/db_tracking.js
@@ -12,8 +12,9 @@ AJAX.registerTeardown('db_tracking.js', function () {
*/
AJAX.registerOnload('db_tracking.js', function () {
- $('#versions tr:first th').append($('<div class="sorticon"></div>'));
- $('#versions').tablesorter({
+ var $versions = $('#versions');
+ $versions.find('tr:first th').append($('<div class="sorticon"></div>'));
+ $versions.tablesorter({
sortList: [[1, 0]],
headers: {
0: {sorter: false},
@@ -24,8 +25,9 @@ AJAX.registerOnload('db_tracking.js', function () {
}
});
- $('#noversions tr:first th').append($('<div class="sorticon"></div>'));
- $('#noversions').tablesorter({
+ var $noVersions = $('#noversions');
+ $noVersions.find('tr:first th').append($('<div class="sorticon"></div>'));
+ $noVersions.tablesorter({
sortList: [[1, 0]],
headers: {
0: {sorter: false},
@@ -33,10 +35,12 @@ AJAX.registerOnload('db_tracking.js', function () {
}
});
+ var $body = $('body');
+
/**
* Handles multi submit for tracked tables
*/
- $('body').on('click', '#trackedForm.ajax button[name="submit_mult"], #trackedForm.ajax input[name="submit_mult"]', function (e) {
+ $body.on('click', '#trackedForm.ajax button[name="submit_mult"], #trackedForm.ajax input[name="submit_mult"]', function (e) {
e.preventDefault();
var $button = $(this);
var $form = $button.parent('form');
@@ -59,7 +63,7 @@ AJAX.registerOnload('db_tracking.js', function () {
/**
* Handles multi submit for untracked tables
*/
- $('body').on('click', '#untrackedForm.ajax button[name="submit_mult"], #untrackedForm.ajax input[name="submit_mult"]', function (e) {
+ $body.on('click', '#untrackedForm.ajax button[name="submit_mult"], #untrackedForm.ajax input[name="submit_mult"]', function (e) {
e.preventDefault();
var $button = $(this);
var $form = $button.parent('form');
@@ -72,7 +76,7 @@ AJAX.registerOnload('db_tracking.js', function () {
/**
* Ajax Event handler for 'Delete tracking'
*/
- $('body').on('click', 'a.delete_tracking_anchor.ajax', function (e) {
+ $body.on('click', 'a.delete_tracking_anchor.ajax', function (e) {
e.preventDefault();
var $anchor = $(this);
var question = PMA_messages.strDeleteTrackingData;
diff --git a/js/error_report.js b/js/error_report.js
index b98993afa7..9c55c83494 100644
--- a/js/error_report.js
+++ b/js/error_report.js
@@ -68,8 +68,8 @@ var ErrorReport = {
var button_options = {};
button_options[PMA_messages.strSendErrorReport] = function () {
- $dialog = $(this);
- post_data = $.extend(report_data, {
+ var $dialog = $(this);
+ var post_data = $.extend(report_data, {
send_error_report: true,
description: $("#report_description").val(),
always_send: $("#always_send_checkbox")[0].checked
@@ -117,16 +117,16 @@ var ErrorReport = {
_showErrorNotification: function () {
ErrorReport._removeErrorNotification();
- $div = $(
+ var $div = $(
'<div style="position:fixed;bottom:0;left:0;right:0;margin:0;' +
'z-index:1000" class="error" id="error_notification"></div>'
).append(
PMA_getImage("s_error.png") + PMA_messages.strErrorOccurred
);
- $buttons = $('<div style="float:right"></div>');
+ var $buttons = $('<div class="floatright"></div>');
- button_html = '<button id="show_error_report">';
+ var button_html = '<button id="show_error_report">';
button_html += PMA_messages.strShowReportDetails;
button_html += '</button>';
@@ -188,35 +188,6 @@ var ErrorReport = {
ErrorReport._showReportDialog(ErrorReport._last_exception);
},
/**
- * Returns the needed info about stored microhistory
- *
- * @return object
- */
- _get_microhistory: function () {
- cached_pages = AJAX.cache.pages.slice(-7);
- remove = ["common_query", "table", "db", "token", "pma_absolute_uri"];
- return {
- pages: cached_pages.map(function (page) {
- simplepage = {
- hash: page.hash
- };
-
- if (page.params) {
- simplepage.params = $.extend({}, page.params);
- $.each(simplepage.params, function (param) {
- if ($.inArray(param, remove) != -1) {
- delete simplepage.params[param];
- }
- });
- }
-
- return simplepage;
- }),
- current_index: AJAX.cache.current -
- (AJAX.cache.pages.length - cached_pages.length)
- };
- },
- /**
* Redirects to the settings page containing error report
* preferences
*
@@ -238,11 +209,10 @@ var ErrorReport = {
"token": PMA_commonParams.get('token'),
"exception": exception,
"current_url": window.location.href,
- "microhistory": ErrorReport._get_microhistory(),
"exception_type": 'js'
};
- if (typeof AJAX.cache.pages[AJAX.cache.current - 1] !== 'undefined') {
- report_data.scripts = AJAX.cache.pages[AJAX.cache.current - 1].scripts.map(
+ if (AJAX.scriptHandler._scripts.length > 0) {
+ report_data.scripts = AJAX.scriptHandler._scripts.map(
function (script) {
return script.name;
}
diff --git a/js/export.js b/js/export.js
index 09b20cd330..f800a9050b 100644
--- a/js/export.js
+++ b/js/export.js
@@ -27,34 +27,265 @@ function enable_dump_some_rows_sub_options()
}
/**
+ * Return template data as a json object
+ *
+ * @returns template data
+ */
+function getTemplateData()
+{
+ var $form = $('form[name="dump"]');
+ var blacklist = ['token', 'server', 'db', 'table', 'single_table',
+ 'export_type', 'export_method', 'sql_query', 'template_id'];
+ var obj = {};
+ var arr = $form.serializeArray();
+ $.each(arr, function () {
+ if ($.inArray(this.name, blacklist) < 0) {
+ if (obj[this.name] !== undefined) {
+ if (! obj[this.name].push) {
+ obj[this.name] = [obj[this.name]];
+ }
+ obj[this.name].push(this.value || '');
+ } else {
+ obj[this.name] = this.value || '';
+ }
+ }
+ });
+ // include unchecked checboxes (which are ignored by serializeArray()) with null
+ // to uncheck them when loading the template
+ $form.find('input[type="checkbox"]:not(:checked)').each(function () {
+ if (obj[this.name] === undefined) {
+ obj[this.name] = null;
+ }
+ });
+ // include empty multiselects
+ $form.find('select').each(function () {
+ if ($(this).find('option:selected').length == 0) {
+ obj[this.name] = [];
+ }
+ });
+ return obj;
+}
+
+/**
+ * Create a template with selected options
+ *
+ * @param name name of the template
+ */
+function createTemplate(name)
+{
+ var templateData = getTemplateData();
+
+ var params = {
+ ajax_request : true,
+ token : PMA_commonParams.get('token'),
+ server : PMA_commonParams.get('server'),
+ db : PMA_commonParams.get('db'),
+ table : PMA_commonParams.get('table'),
+ exportType : $('input[name="export_type"]').val(),
+ templateAction : 'create',
+ templateName : name,
+ templateData : JSON.stringify(templateData)
+ };
+
+ PMA_ajaxShowMessage();
+ $.post('tbl_export.php', params, function (response) {
+ if (response.success === true) {
+ $('#templateName').val('');
+ $('#template').html(response.data);
+ $("#template").find("option").each(function() {
+ if ($(this).text() == name) {
+ $(this).prop('selected', true);
+ }
+ });
+ PMA_ajaxShowMessage(PMA_messages.strTemplateCreated);
+ } else {
+ PMA_ajaxShowMessage(response.error, false);
+ }
+ });
+}
+
+/**
+ * Loads a template
+ *
+ * @param id ID of the template to load
+ */
+function loadTemplate(id)
+{
+ var params = {
+ ajax_request : true,
+ token : PMA_commonParams.get('token'),
+ server : PMA_commonParams.get('server'),
+ db : PMA_commonParams.get('db'),
+ table : PMA_commonParams.get('table'),
+ exportType : $('input[name="export_type"]').val(),
+ templateAction : 'load',
+ templateId : id,
+ };
+
+ PMA_ajaxShowMessage();
+ $.post('tbl_export.php', params, function (response) {
+ if (response.success === true) {
+ var $form = $('form[name="dump"]');
+ var options = $.parseJSON(response.data);
+ $.each(options, function (key, value) {
+ var $element = $form.find('[name="' + key + '"]');
+ if ($element.length) {
+ if (($element.is('input') && $element.attr('type') == 'checkbox') && value === null) {
+ $element.prop('checked', false);
+ } else {
+ if (($element.is('input') && $element.attr('type') == 'checkbox') ||
+ ($element.is('input') && $element.attr('type') == 'radio') ||
+ ($element.is('select') && $element.attr('multiple') == 'multiple')) {
+ if (! value.push) {
+ value = [value];
+ }
+ }
+ $element.val(value);
+ }
+ $element.trigger('change');
+ }
+ });
+ $('input[name="template_id"]').val(id);
+ PMA_ajaxShowMessage(PMA_messages.strTemplateLoaded);
+ } else {
+ PMA_ajaxShowMessage(response.error, false);
+ }
+ });
+}
+
+/**
+ * Updates an existing template with current options
+ *
+ * @param id ID of the template to update
+ */
+function updateTemplate(id)
+{
+ var templateData = getTemplateData();
+
+ var params = {
+ ajax_request : true,
+ token : PMA_commonParams.get('token'),
+ server : PMA_commonParams.get('server'),
+ db : PMA_commonParams.get('db'),
+ table : PMA_commonParams.get('table'),
+ exportType : $('input[name="export_type"]').val(),
+ templateAction : 'update',
+ templateId : id,
+ templateData : JSON.stringify(templateData)
+ };
+
+ PMA_ajaxShowMessage();
+ $.post('tbl_export.php', params, function (response) {
+ if (response.success === true) {
+ PMA_ajaxShowMessage(PMA_messages.strTemplateUpdated);
+ } else {
+ PMA_ajaxShowMessage(response.error, false);
+ }
+ });
+}
+
+/**
+ * Delete a template
+ *
+ * @param id ID of the template to delete
+ */
+function deleteTemplate(id)
+{
+ var params = {
+ ajax_request : true,
+ token : PMA_commonParams.get('token'),
+ server : PMA_commonParams.get('server'),
+ db : PMA_commonParams.get('db'),
+ table : PMA_commonParams.get('table'),
+ exportType : $('input[name="export_type"]').val(),
+ templateAction : 'delete',
+ templateId : id,
+ };
+
+ PMA_ajaxShowMessage();
+ $.post('tbl_export.php', params, function (response) {
+ if (response.success === true) {
+ $('#template').find('option[value="' + id + '"]').remove();
+ PMA_ajaxShowMessage(PMA_messages.strTemplateDeleted);
+ } else {
+ PMA_ajaxShowMessage(response.error, false);
+ }
+ });
+}
+
+/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('export.js', function () {
$("#plugins").unbind('change');
$("input[type='radio'][name='sql_structure_or_data']").unbind('change');
- $("input[type='radio'][name='latex_structure_or_data']").unbind('change');
- $("input[type='radio'][name='odt_structure_or_data']").unbind('change');
- $("input[type='radio'][name='texytext_structure_or_data']").unbind('change');
- $("input[type='radio'][name='htmlword_structure_or_data']").unbind('change');
- $("input[type='radio'][name='sql_structure_or_data']").unbind('change');
+ $("input[type='radio'][name$='_structure_or_data']").off('change');
$("input[type='radio'][name='output_format']").unbind('change');
$("#checkbox_sql_include_comments").unbind('change');
- $("#plugins").unbind('change');
$("input[type='radio'][name='quick_or_custom']").unbind('change');
$("input[type='radio'][name='allrows']").unbind('change');
$('#btn_alias_config').off('click');
$('#db_alias_select').off('change');
$('.table_alias_select').off('change');
+ $('input[name="table_select[]"]').off('change');
+ $('input[name="table_structure[]"]').off('change');
+ $('input[name="table_data[]"]').off('change');
+ $('#table_structure_all').off('change');
+ $('#table_data_all').off('change');
+ $('input[name="createTemplate"]').off('click');
+ $('select[name="template"]').off('change');
+ $('input[name="updateTemplate"]').off('click');
+ $('input[name="deleteTemplate"]').off('click');
});
AJAX.registerOnload('export.js', function () {
+
+ /**
+ * Export template handling code
+ */
+ // create a new template
+ $('input[name="createTemplate"]').on('click', function (e) {
+ e.preventDefault();
+ var name = $('input[name="templateName"]').val();
+ if (name.length) {
+ createTemplate(name);
+ }
+ });
+
+ // load an existing template
+ $('select[name="template"]').on('change', function (e) {
+ e.preventDefault();
+ var id = $(this).val();
+ if (id.length) {
+ loadTemplate(id);
+ }
+ });
+
+ // udpate an existing template with new criteria
+ $('input[name="updateTemplate"]').on('click', function (e) {
+ e.preventDefault();
+ var id = $('select[name="template"]').val();
+ if (id.length) {
+ updateTemplate(id);
+ }
+ });
+
+ // delete an existing template
+ $('input[name="deleteTemplate"]').on('click', function (e) {
+ e.preventDefault();
+ var id = $('select[name="template"]').val();
+ if (id.length) {
+ deleteTemplate(id);
+ }
+ });
+
/**
* Toggles the hiding and showing of each plugin's options
* according to the currently selected plugin from the dropdown list
*/
$("#plugins").change(function () {
- $("#format_specific_opts div.format_specific_options").hide();
- var selected_plugin_name = $("#plugins option:selected").val();
+ $("#format_specific_opts").find("div.format_specific_options").hide();
+ var selected_plugin_name = $("#plugins").find("option:selected").val();
$("#" + selected_plugin_name + "_options").show();
});
@@ -86,15 +317,79 @@ AJAX.registerOnload('export.js', function () {
$("#checkbox_sql_auto_increment").removeProp('disabled').parent().fadeTo('fast', 1);
}
});
+
+ // For separate-file exports only ZIP compression is allowed
+ $('input[type="checkbox"][name="as_separate_files"]').change(function(){
+ if (! $(this).attr('checked')) {
+ $('#compression').val('zip');
+ }
+ });
+
+ $('#compression').change(function(){
+ if ($('option:selected').val() !== 'zip') {
+ $('input[type="checkbox"][name="as_separate_files"]').attr('checked', false);
+ }
+ });
+
});
+function setup_table_structure_or_data() {
+ if ($("input[name='export_type']").val() != 'database') {
+ return;
+ }
+ var pluginName = $("#plugins").find("option:selected").val();
+ var formElemName = pluginName + "_structure_or_data";
+ var force_structure_or_data = !($("input[name='" + formElemName + "_default']").length);
+
+ if (force_structure_or_data === true) {
+ $('input[name="structure_or_data_forced"]').val(1);
+ $('.export_structure input[type="checkbox"], .export_data input[type="checkbox"]')
+ .prop('disabled', true);
+ $('.export_structure, .export_data').fadeTo('fast', 0.4);
+ } else {
+ $('input[name="structure_or_data_forced"]').val(0);
+ $('.export_structure input[type="checkbox"], .export_data input[type="checkbox"]')
+ .removeProp('disabled');
+ $('.export_structure, .export_data').fadeTo('fast', 1);
+
+ var structure_or_data = $('input[name="' + formElemName + '_default"]').val();
+
+ if (structure_or_data == 'structure') {
+ $('.export_data input[type="checkbox"]')
+ .prop('checked', false);
+ } else if (structure_or_data == 'data') {
+ $('.export_structure input[type="checkbox"]')
+ .prop('checked', false);
+ }
+ if (structure_or_data == 'structure' || structure_or_data == 'structure_and_data') {
+ if (!$('.export_structure input[type="checkbox"]:checked').length) {
+ $('input[name="table_select[]"]:checked')
+ .closest('tr')
+ .find('.export_structure input[type="checkbox"]')
+ .prop('checked', true);
+ }
+ }
+ if (structure_or_data == 'data' || structure_or_data == 'structure_and_data') {
+ if (!$('.export_data input[type="checkbox"]:checked').length) {
+ $('input[name="table_select[]"]:checked')
+ .closest('tr')
+ .find('.export_data input[type="checkbox"]')
+ .prop('checked', true);
+ }
+ }
+
+ check_selected_tables();
+ check_table_select_all();
+ }
+}
/**
* Toggles the hiding and showing of plugin structure-specific and data-specific
* options
*/
-function toggle_structure_data_opts(pluginName)
+function toggle_structure_data_opts()
{
+ var pluginName = $("select#plugins").val();
var radioFormName = pluginName + "_structure_or_data";
var dataDiv = "#" + pluginName + "_data";
var structureDiv = "#" + pluginName + "_structure";
@@ -112,37 +407,20 @@ function toggle_structure_data_opts(pluginName)
}
}
-AJAX.registerOnload('export.js', function () {
- $("input[type='radio'][name='latex_structure_or_data']").change(function () {
- toggle_structure_data_opts("latex");
- });
- $("input[type='radio'][name='odt_structure_or_data']").change(function () {
- toggle_structure_data_opts("odt");
- });
- $("input[type='radio'][name='texytext_structure_or_data']").change(function () {
- toggle_structure_data_opts("texytext");
- });
- $("input[type='radio'][name='htmlword_structure_or_data']").change(function () {
- toggle_structure_data_opts("htmlword");
- });
- $("input[type='radio'][name='sql_structure_or_data']").change(function () {
- toggle_structure_data_opts("sql");
- });
-});
-
/**
* Toggles the disabling of the "save to file" options
*/
function toggle_save_to_file()
{
+ var $ulSaveAsfile = $("#ul_save_asfile");
if (!$("#radio_dump_asfile").prop("checked")) {
- $("#ul_save_asfile > li").fadeTo('fast', 0.4);
- $("#ul_save_asfile > li > input").prop('disabled', true);
- $("#ul_save_asfile > li> select").prop('disabled', true);
+ $ulSaveAsfile.find("> li").fadeTo('fast', 0.4);
+ $ulSaveAsfile.find("> li > input").prop('disabled', true);
+ $ulSaveAsfile.find("> li > select").prop('disabled', true);
} else {
- $("#ul_save_asfile > li").fadeTo('fast', 1);
- $("#ul_save_asfile > li > input").prop('disabled', false);
- $("#ul_save_asfile > li> select").prop('disabled', false);
+ $ulSaveAsfile.find("> li").fadeTo('fast', 1);
+ $ulSaveAsfile.find("> li > input").prop('disabled', false);
+ $ulSaveAsfile.find("> li > select").prop('disabled', false);
}
}
@@ -157,27 +435,117 @@ AJAX.registerOnload('export.js', function () {
function toggle_sql_include_comments()
{
$("#checkbox_sql_include_comments").change(function () {
+ var $ulIncludeComments = $("#ul_include_comments");
if (!$("#checkbox_sql_include_comments").prop("checked")) {
- $("#ul_include_comments > li").fadeTo('fast', 0.4);
- $("#ul_include_comments > li > input").prop('disabled', true);
+ $ulIncludeComments.find("> li").fadeTo('fast', 0.4);
+ $ulIncludeComments.find("> li > input").prop('disabled', true);
} else {
// If structure is not being exported, the comment options for structure should not be enabled
if ($("#radio_sql_structure_or_data_data").prop("checked")) {
$("#text_sql_header_comment").removeProp('disabled').parent("li").fadeTo('fast', 1);
} else {
- $("#ul_include_comments > li").fadeTo('fast', 1);
- $("#ul_include_comments > li > input").removeProp('disabled');
+ $ulIncludeComments.find("> li").fadeTo('fast', 1);
+ $ulIncludeComments.find("> li > input").removeProp('disabled');
}
}
});
}
+function check_table_select_all() {
+ var total = $('input[name="table_select[]"]').length;
+ var str_checked = $('input[name="table_structure[]"]:checked').length;
+ var data_checked = $('input[name="table_data[]"]:checked').length;
+ var str_all = $('#table_structure_all');
+ var data_all = $('#table_data_all');
+
+ if (str_checked == total) {
+ str_all
+ .prop("indeterminate", false)
+ .prop('checked', true);
+ } else if (str_checked === 0) {
+ str_all
+ .prop("indeterminate", false)
+ .prop('checked', false);
+ } else {
+ str_all
+ .prop("indeterminate", true)
+ .prop('checked', false);
+ }
+
+ if (data_checked == total) {
+ data_all
+ .prop("indeterminate", false)
+ .prop('checked', true);
+ } else if (data_checked === 0) {
+ data_all
+ .prop("indeterminate", false)
+ .prop('checked', false);
+ } else {
+ data_all
+ .prop("indeterminate", true)
+ .prop('checked', false);
+ }
+}
+
+function toggle_table_select_all_str() {
+ var str_all = $('#table_structure_all').is(':checked');
+ if (str_all) {
+ $('input[name="table_structure[]"]').prop('checked', true);
+ } else {
+ $('input[name="table_structure[]"]').prop('checked', false);
+ }
+}
+
+function toggle_table_select_all_data() {
+ var data_all = $('#table_data_all').is(':checked');
+ if (data_all) {
+ $('input[name="table_data[]"]').prop('checked', true);
+ } else {
+ $('input[name="table_data[]"]').prop('checked', false);
+ }
+}
+
+function check_selected_tables(argument) {
+ $('.export_table_select tbody tr').each(function() {
+ check_table_selected(this);
+ });
+}
+
+function check_table_selected(row) {
+ var $row = $(row);
+ var table_select = $row.find('input[name="table_select[]"]');
+ var str_check = $row.find('input[name="table_structure[]"]');
+ var data_check = $row.find('input[name="table_data[]"]');
+
+ var data = data_check.is(':checked:not(:disabled)');
+ var structure = str_check.is(':checked:not(:disabled)');
+
+ if (data && structure) {
+ table_select.prop({checked: true, indeterminate: false});
+ } else if (data || structure) {
+ table_select.prop({checked: true, indeterminate: true});
+ } else {
+ table_select.prop({checked: false, indeterminate: false});
+ }
+}
+
+function toggle_table_select(row) {
+ var $row = $(row);
+ var table_selected = $row.find('input[name="table_select[]"]').is(':checked');
+
+ if (table_selected) {
+ $row.find('input[type="checkbox"]:not(:disabled)').prop('checked', true);
+ } else {
+ $row.find('input[type="checkbox"]:not(:disabled)').prop('checked', false);
+ }
+}
+
AJAX.registerOnload('export.js', function () {
/**
* For SQL plugin, if "CREATE TABLE options" is checked/unchecked, check/uncheck each of its sub-options
*/
var $create = $("#checkbox_sql_create_table_statements");
- var $create_options = $("#ul_create_table_statements input");
+ var $create_options = $("#ul_create_table_statements").find("input");
$create.change(function () {
$create_options.prop('checked', $(this).prop("checked"));
});
@@ -191,7 +559,7 @@ AJAX.registerOnload('export.js', function () {
* Disables the view output as text option if the output must be saved as a file
*/
$("#plugins").change(function () {
- var active_plugin = $("#plugins option:selected").val();
+ var active_plugin = $("#plugins").find("option:selected").val();
var force_file = $("#force_file_" + active_plugin).val();
if (force_file == "true") {
if ($("#radio_dump_asfile").prop('checked') !== true) {
@@ -203,6 +571,78 @@ AJAX.registerOnload('export.js', function () {
$("#radio_view_as_text").prop('disabled', false).parent().fadeTo('fast', 1);
}
});
+
+ $("input[type='radio'][name$='_structure_or_data']").on('change', function () {
+ toggle_structure_data_opts();
+ });
+
+ $('input[name="table_select[]"]').on('change', function() {
+ toggle_table_select($(this).closest('tr'));
+ check_table_select_all();
+ });
+
+ $('input[name="table_structure[]"]').on('change', function() {
+ check_table_selected($(this).closest('tr'));
+ check_table_select_all();
+ });
+
+ $('input[name="table_data[]"]').on('change', function() {
+ check_table_selected($(this).closest('tr'));
+ check_table_select_all();
+ });
+
+ $('#table_structure_all').on('change', function() {
+ toggle_table_select_all_str();
+ check_selected_tables();
+ });
+
+ $('#table_data_all').on('change', function() {
+ toggle_table_select_all_data();
+ check_selected_tables();
+ });
+
+ if ($("input[name='export_type']").val() == 'database') {
+ // Hide structure or data radio buttons
+ $("input[type='radio'][name$='_structure_or_data']").each(function() {
+ var $this = $(this);
+ var name = $this.prop('name');
+ var val = $('input[name="' + name + '"]:checked').val();
+ var name_default = name + '_default';
+ if (!$('input[name="' + name_default + '"]').length) {
+ $this
+ .after(
+ $('<input type="hidden" name="' + name_default + '" value="' + val + '" disabled>')
+ )
+ .after(
+ $('<input type="hidden" name="' + name + '" value="structure_and_data">')
+ );
+ $this.parent().find('label').remove();
+ } else {
+ $this.parent().remove();
+ }
+ });
+ $("input[type='radio'][name$='_structure_or_data']").remove();
+
+ // Disable CREATE table checkbox for sql
+ var createTableCheckbox = $('#checkbox_sql_create_table');
+ createTableCheckbox.prop('checked', true);
+ var dummyCreateTable = $('#checkbox_sql_create_table')
+ .clone()
+ .removeAttr('id')
+ .attr('type', 'hidden');
+ createTableCheckbox
+ .prop('disabled', true)
+ .after(dummyCreateTable)
+ .parent()
+ .fadeTo('fast', 0.4);
+
+ setup_table_structure_or_data();
+ }
+
+ /**
+ * Handle force structure_or_data
+ */
+ $("#plugins").change(setup_table_structure_or_data);
});
/**
@@ -218,7 +658,7 @@ function toggle_quick_or_custom()
$("#output").show();
$("#format_specific_opts").show();
$("#output_quick_export").hide();
- var selected_plugin_name = $("#plugins option:selected").val();
+ var selected_plugin_name = $("#plugins").find("option:selected").val();
$("#" + selected_plugin_name + "_options").show();
} else { // quick
$("#databases_and_tables").hide();
@@ -320,7 +760,7 @@ function createAliasModal(event) {
});
$('#alias_modal').parent().appendTo($('form[name="dump"]'));
};
- $('#alias_modal input[type="text"]').prop('disabled', false);
+ $('#alias_modal').find('input[type="text"]').prop('disabled', false);
$('#alias_modal').dialog({
width: Math.min($(window).width() - 100, 700),
maxHeight: $(window).height(),
@@ -353,17 +793,17 @@ AJAX.registerOnload('export.js', function () {
$("input[type='radio'][name='quick_or_custom']").change(toggle_quick_or_custom);
$("#scroll_to_options_msg").hide();
- $("#format_specific_opts div.format_specific_options")
- .hide()
- .css({
- "border": 0,
- "margin": 0,
- "padding": 0
- })
- .find("h3")
- .remove();
+ $("#format_specific_opts").find("div.format_specific_options")
+ .hide()
+ .css({
+ "border": 0,
+ "margin": 0,
+ "padding": 0
+ })
+ .find("h3")
+ .remove();
toggle_quick_or_custom();
- toggle_structure_data_opts($("select#plugins").val());
+ toggle_structure_data_opts();
toggle_sql_include_comments();
/**
diff --git a/js/functions.js b/js/functions.js
index d8f5eb61d9..5e6e9d6b48 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -5,11 +5,6 @@
*/
/**
- * @var $table_clone reference to the action links on the tbl_structure page
- */
-var $table_clone = false;
-
-/**
* @var sql_box_locked lock for the sqlbox textarea in the querybox
*/
var sql_box_locked = false;
@@ -80,6 +75,11 @@ var indexes = [];
var fulltext_indexes = [];
/**
+ * @var spatial_indexes array to hold 'Spatial' columns.
+ */
+var spatial_indexes = [];
+
+/**
* Make sure that ajax requests will not be cached
* by appending a random variable to their parameters
*/
@@ -93,6 +93,71 @@ $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
});
/**
+ * Creates an SQL editor which supports auto completing etc.
+ *
+ * @param $textarea jQuery object wrapping the textarea to be made the editor
+ * @param options optional options for CodeMirror
+ * @param resize optional resizing ('vertical', 'horizontal', 'both')
+ */
+function PMA_getSQLEditor($textarea, options, resize) {
+ if ($textarea.length > 0 && typeof CodeMirror !== 'undefined') {
+
+ // merge options for CodeMirror
+ var defaults = {
+ lineNumbers: true,
+ matchBrackets: true,
+ extraKeys: {"Ctrl-Space": "autocomplete"},
+ hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
+ indentUnit: 4,
+ mode: "text/x-mysql",
+ lineWrapping: true
+ };
+
+ if (CodeMirror.sqlLint) {
+ $.extend(defaults, {
+ gutters: ["CodeMirror-lint-markers"],
+ lint: {
+ "getAnnotations": CodeMirror.sqlLint,
+ "async": true,
+ }
+ });
+ }
+
+ $.extend(true, defaults, options);
+
+ // create CodeMirror editor
+ var codemirrorEditor = CodeMirror.fromTextArea($textarea[0], defaults);
+ // allow resizing
+ if (! resize) {
+ resize = 'vertical';
+ }
+ var handles = '';
+ if (resize == 'vertical') {
+ handles = 'n, s';
+ }
+ if (resize == 'both') {
+ handles = 'all';
+ }
+ if (resize == 'horizontal') {
+ handles = 'e, w';
+ }
+ $(codemirrorEditor.getWrapperElement())
+ .css('resize', resize)
+ .resizable({
+ handles: handles,
+ resize: function() {
+ codemirrorEditor.setSize($(this).width(), $(this).height());
+ }
+ });
+ // enable autocomplete
+ codemirrorEditor.on("inputRead", codemirrorAutocompleteOnInputRead);
+
+ return codemirrorEditor;
+ }
+ return null;
+}
+
+/**
* Clear text selection
*/
function PMA_clearSelection() {
@@ -177,6 +242,21 @@ function PMA_hideShowDefaultValue($default_type)
}
/**
+ * Hides/shows the input field for column expression based on whether
+ * VIRTUAL/PERSISTENT is selected
+ *
+ * @param $virtuality virtuality dropdown
+ */
+function PMA_hideShowExpression($virtuality)
+{
+ if ($virtuality.val() == '') {
+ $virtuality.siblings('.expression').hide();
+ } else {
+ $virtuality.siblings('.expression').show();
+ }
+}
+
+/**
* Show notices for ENUM columns; add/hide the default value
*
*/
@@ -188,6 +268,9 @@ function PMA_verifyColumnsProperties()
$("select.default_type").each(function () {
PMA_hideShowDefaultValue($(this));
});
+ $('select.virtuality').each(function () {
+ PMA_hideShowExpression($(this));
+ });
}
/**
@@ -288,8 +371,9 @@ function PMA_current_version(data)
if (latest === current) {
version_information_message = ' (' + PMA_messages.strUpToDate + ')';
}
- $('#li_pma_version span.latest').remove();
- $('#li_pma_version').append(version_information_message);
+ var $liPmaVersion = $('#li_pma_version');
+ $liPmaVersion.find('span.latest').remove();
+ $liPmaVersion.append(version_information_message);
}
}
@@ -306,7 +390,8 @@ function PMA_display_git_revision()
"server": PMA_commonParams.get('server'),
"token": PMA_commonParams.get('token'),
"git_revision": true,
- "ajax_request": true
+ "ajax_request": true,
+ "no_debug": true
},
function (data) {
if (typeof data !== 'undefined' && data.success === true) {
@@ -551,10 +636,6 @@ function checkSqlQuery(theForm)
theForm.elements.sql_file.value.replace(space_re, '') !== '') {
return true;
}
- if (typeof(theForm.elements.sql_localfile) != 'undefined' &&
- theForm.elements.sql_localfile.value.replace(space_re, '') !== '') {
- return true;
- }
if (isEmpty && typeof(theForm.elements.id_bookmark) != 'undefined' &&
(theForm.elements.id_bookmark.value !== null || theForm.elements.id_bookmark.value !== '') &&
theForm.elements.id_bookmark.selectedIndex !== 0) {
@@ -676,9 +757,10 @@ function checkTableEditForm(theForm, fieldsCnt)
}
// at least this section is under jQuery
- if ($("input.textfield[name='table']").val() === "") {
+ var $input = $("input.textfield[name='table']");
+ if ($input.val() === "") {
alert(PMA_messages.strFormEmpty);
- $("input.textfield[name='table']").focus();
+ $input.focus();
return false;
}
@@ -703,9 +785,9 @@ var last_shift_clicked_row = -1;
var _idleSecondsCounter = 0;
var IncInterval;
-var updateInterval;
+var updateTimeout;
AJAX.registerTeardown('functions.js', function () {
- clearInterval(updateInterval);
+ clearTimeout(updateTimeout);
clearInterval(IncInterval);
$(document).off('mousemove');
});
@@ -738,16 +820,15 @@ AJAX.registerOnload('functions.js', function () {
url: href,
data: params,
success: function (data) {
- clearInterval(updateInterval);
if (data.success) {
if (PMA_commonParams.get('LoginCookieValidity')-_idleSecondsCounter > 5) {
var interval = (PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter - 5) * 1000;
if (interval > Math.pow(2, 31) - 1) { // max value for setInterval() function
interval = Math.pow(2, 31) - 1;
}
- updateInterval = window.setInterval(UpdateIdleTime, interval);
+ updateTimeout = window.setTimeout(UpdateIdleTime, interval);
} else {
- updateInterval = window.setInterval(UpdateIdleTime, 2000);
+ updateTimeout = window.setTimeout(UpdateIdleTime, 2000);
}
} else { //timeout occurred
window.location.reload(true);
@@ -762,7 +843,7 @@ AJAX.registerOnload('functions.js', function () {
if (interval > Math.pow(2, 31) - 1) { // max value for setInterval() function
interval = Math.pow(2, 31) - 1;
}
- updateInterval = window.setInterval(UpdateIdleTime, interval);
+ updateTimeout = window.setTimeout(UpdateIdleTime, interval);
}
});
/**
@@ -781,14 +862,11 @@ AJAX.registerOnload('functions.js', function () {
$(document).on('click', 'input:checkbox.checkall', function (e) {
$this = $(this);
var $tr = $this.closest('tr');
-
- // make the table unselectable (to prevent default highlighting when shift+click)
- //$tr.parents('table').noSelect();
+ var $table = $this.closest('table');
if (!e.shiftKey || last_clicked_row == -1) {
// usual click
- // XXX: FF fires two click events for <label> (label and checkbox), so we need to handle this differently
var $checkbox = $tr.find(':checkbox.checkall');
var checked = $this.prop('checked');
$checkbox.prop('checked', checked).trigger('change');
@@ -800,7 +878,7 @@ AJAX.registerOnload('functions.js', function () {
last_click_checked = checked;
// remember the last clicked row
- last_clicked_row = last_click_checked ? $('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr) : -1;
+ last_clicked_row = last_click_checked ? $table.find('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr) : -1;
last_shift_clicked_row = -1;
} else {
// handle the shift click
@@ -825,7 +903,7 @@ AJAX.registerOnload('functions.js', function () {
}
// handle new shift click
- var curr_row = $('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr);
+ var curr_row = $table.find('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr);
if (curr_row >= last_clicked_row) {
start = last_clicked_row;
end = curr_row;
@@ -962,8 +1040,9 @@ function PMA_handleSimulateQueryButton()
query = $('#sqlquery').val();
}
+ var $simulateDml = $('#simulate_dml');
if (update_re.test(query) || delete_re.test(query)) {
- if (! $('#simulate_dml').length) {
+ if (! $simulateDml.length) {
$('#button_submit_query')
.before('<input type="button" id="simulate_dml"' +
'tabindex="199" value="' +
@@ -971,8 +1050,8 @@ function PMA_handleSimulateQueryButton()
'" />');
}
} else {
- if ($('#simulate_dml').length) {
- $('#simulate_dml').remove();
+ if ($simulateDml.length) {
+ $simulateDml.remove();
}
}
}
@@ -988,9 +1067,9 @@ function insertQuery(queryType)
return;
} else if (queryType == "format") {
if (codemirror_editor) {
- $('#querymessage').html(PMA_messages.strFormatting
- + '&nbsp;<img class="ajaxIcon" src="'
- + pmaThemeImage + 'ajax_clock_small.gif" alt="">');
+ $('#querymessage').html(PMA_messages.strFormatting +
+ '&nbsp;<img class="ajaxIcon" src="' +
+ pmaThemeImage + 'ajax_clock_small.gif" alt="">');
var href = 'db_sql_format.php';
var params = {
'ajax_request': true,
@@ -1105,6 +1184,44 @@ function insertValueQuery()
}
/**
+ * Updates the input fields for the parameters based on the query
+ */
+function updateQueryParameters() {
+
+ if ($('#parameterized').is(':checked')) {
+ var query = codemirror_editor ? codemirror_editor.getValue() : $('#sqlquery').val();
+
+ var allParameters = query.match(/:[a-zA-Z0-9_]+/g);
+ var parameters = [];
+ // get unique parameters
+ if (allParameters) {
+ $.each(allParameters, function(i, parameter){
+ if ($.inArray(parameter, parameters) === -1) {
+ parameters.push(parameter);
+ }
+ });
+ }
+
+ var $temp = $('<div />');
+ $temp.append($('#parametersDiv').children());
+ $('#parametersDiv').empty();
+
+ $.each(parameters, function (i, parameter) {
+ var paramName = parameter.substring(1);
+ var $param = $temp.find('#paramSpan_' + paramName );
+ if (! $param.length) {
+ $param = $('<span class="parameter" id="paramSpan_' + paramName + '" />');
+ $('<label for="param_' + paramName + '" />').text(parameter).appendTo($param);
+ $('<input type="text" name="parameters[' + parameter + ']" id="param_' + paramName + '" />').appendTo($param);
+ }
+ $('#parametersDiv').append($param);
+ });
+ } else {
+ $('#parametersDiv').empty();
+ }
+}
+
+/**
* Add a date/time picker to each element that needs it
* (only when jquery-ui-timepicker-addon.js is loaded)
*/
@@ -1146,8 +1263,9 @@ function refreshLayout()
var $elm = $('#pdflayout');
var orientation = $('#orientation_opt').val();
var paper = 'A4';
- if ($('#paper_opt').length == 1) {
- paper = $('#paper_opt').val();
+ var $paperOpt = $('#paper_opt');
+ if ($paperOpt.length == 1) {
+ paper = $paperOpt.val();
}
var posa = 'y';
var posb = 'x';
@@ -1589,6 +1707,46 @@ function pdfPaperSize(format, axis)
}
/**
+ * Get checkbox for foreign key checks
+ *
+ * @return string
+ */
+function getForeignKeyCheckboxLoader() {
+ var html = '';
+ html += '<div>';
+ html += '<div class="load-default-fk-check-value">';
+ html += PMA_getImage('ajax_clock_small.gif');
+ html += '</div>';
+ html += '</div>';
+ return html;
+}
+
+function loadForeignKeyCheckbox() {
+ // Load default foreign key check value
+ var params = {
+ 'ajax_request': true,
+ 'token': PMA_commonParams.get('token'),
+ 'server': PMA_commonParams.get('server'),
+ 'get_default_fk_check_value': true
+ };
+ $.get('sql.php', params, function (data) {
+ var html = '<input type="hidden" name="fk_checks" value="0" />' +
+ '<input type="checkbox" name="fk_checks" id="fk_checks"' +
+ (data.default_fk_check_value ? ' checked="checked"' : '') + ' />' +
+ '<label for="fk_checks">' + PMA_messages.strForeignKeyCheck + '</label>';
+ $('.load-default-fk-check-value').replaceWith(html);
+ });
+}
+
+function getJSConfirmCommonParam(elem) {
+ return {
+ 'is_js_confirmed' : 1,
+ 'ajax_request' : true,
+ 'fk_checks': $(elem).find('#fk_checks').is(':checked') ? 1 : 0
+ };
+}
+
+/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('functions.js', function () {
@@ -1596,7 +1754,12 @@ AJAX.registerTeardown('functions.js', function () {
$(document).off('click', "input#sql_query_edit_save");
$(document).off('click', "input#sql_query_edit_discard");
$('input.sqlbutton').unbind('click');
- $("#export_type").unbind('change');
+ if (codemirror_editor) {
+ codemirror_editor.off('blur');
+ } else {
+ $(document).off('blur', '#sqlquery');
+ }
+ $(document).off('change', '#parameterized');
$('#sqlquery').unbind('keydown');
$('#sql_query_edit').unbind('keydown');
@@ -1632,6 +1795,7 @@ AJAX.registerOnload('functions.js', function () {
var old_text = $inner_sql.html();
var new_content = "<textarea name=\"sql_query_edit\" id=\"sql_query_edit\">" + sql_query + "</textarea>\n";
+ new_content += getForeignKeyCheckboxLoader();
new_content += "<input type=\"submit\" id=\"sql_query_edit_save\" class=\"button btnSave\" value=\"" + PMA_messages.strGo + "\"/>\n";
new_content += "<input type=\"button\" id=\"sql_query_edit_discard\" class=\"button btnDiscard\" value=\"" + PMA_messages.strCancel + "\"/>\n";
var $editor_area = $('div#inline_editor');
@@ -1640,6 +1804,7 @@ AJAX.registerOnload('functions.js', function () {
$editor_area.insertBefore($inner_sql);
}
$editor_area.html(new_content);
+ loadForeignKeyCheckbox();
$inner_sql.hide();
bindCodeMirrorToInlineEditor();
@@ -1654,15 +1819,17 @@ AJAX.registerOnload('functions.js', function () {
codemirror_inline_editor.save();
sql_query = codemirror_inline_editor.getValue();
} else {
- sql_query = $(this).prev().val();
+ sql_query = $(this).parent().find('#sql_query_edit').val();
}
+ var fk_check = $(this).parent().find('#fk_checks').is(':checked');
var $form = $("a.inline_edit_sql").prev('form');
var $fake_form = $('<form>', {action: 'import.php', method: 'post'})
.append($form.find("input[name=server], input[name=db], input[name=table], input[name=token]").clone())
.append($('<input/>', {type: 'hidden', name: 'show_query', value: 1}))
.append($('<input/>', {type: 'hidden', name: 'is_js_confirmed', value: 0}))
- .append($('<input/>', {type: 'hidden', name: 'sql_query', value: sql_query}));
+ .append($('<input/>', {type: 'hidden', name: 'sql_query', value: sql_query}))
+ .append($('<input/>', {type: 'hidden', name: 'fk_checks', value: fk_check ? 1 : 0}));
if (! checkSqlQuery($fake_form[0])) {
return false;
}
@@ -1670,8 +1837,9 @@ AJAX.registerOnload('functions.js', function () {
});
$(document).on('click', "input#sql_query_edit_discard", function () {
- $('div#inline_editor_outer').siblings('code.sql').show();
- $('div#inline_editor_outer').remove();
+ var $divEditor = $('div#inline_editor_outer');
+ $divEditor.siblings('code.sql').show();
+ $divEditor.remove();
});
$('input.sqlbutton').click(function (evt) {
@@ -1680,46 +1848,12 @@ AJAX.registerOnload('functions.js', function () {
return false;
});
- $("#export_type").change(function () {
- if ($("#export_type").val() == 'svg') {
- $("#show_grid_opt").prop("disabled", true);
- $("#orientation_opt").prop("disabled", true);
- $("#with_doc").prop("disabled", true);
- $("#show_table_dim_opt").removeProp("disabled");
- $("#all_tables_same_width").removeProp("disabled");
- $("#paper_opt").removeProp("disabled");
- $("#show_color_opt").removeProp("disabled");
- //$(this).css("background-color","yellow");
- } else if ($("#export_type").val() == 'dia') {
- $("#show_grid_opt").prop("disabled", true);
- $("#with_doc").prop("disabled", true);
- $("#show_table_dim_opt").prop("disabled", true);
- $("#all_tables_same_width").prop("disabled", true);
- $("#paper_opt").removeProp("disabled");
- $("#show_color_opt").removeProp("disabled");
- $("#orientation_opt").removeProp("disabled");
- } else if ($("#export_type").val() == 'eps') {
- $("#show_grid_opt").prop("disabled", true);
- $("#orientation_opt").removeProp("disabled");
- $("#with_doc").prop("disabled", true);
- $("#show_table_dim_opt").prop("disabled", true);
- $("#all_tables_same_width").prop("disabled", true);
- $("#paper_opt").prop("disabled", true);
- $("#show_color_opt").prop("disabled", true);
- } else if ($("#export_type").val() == 'pdf') {
- $("#show_grid_opt").removeProp("disabled");
- $("#orientation_opt").removeProp("disabled");
- $("#with_doc").removeProp("disabled");
- $("#show_table_dim_opt").removeProp("disabled");
- $("#all_tables_same_width").removeProp("disabled");
- $("#paper_opt").removeProp("disabled");
- $("#show_color_opt").removeProp("disabled");
- }
- });
+ $(document).on('change', '#parameterized', updateQueryParameters);
- if ($('#input_username')) {
- if ($('#input_username').val() === '') {
- $('#input_username').focus();
+ var $inputUsername = $('#input_username');
+ if ($inputUsername) {
+ if ($inputUsername.val() === '') {
+ $inputUsername.focus();
} else {
$('#input_password').focus();
}
@@ -1745,8 +1879,19 @@ function codemirrorAutocompleteOnInputRead(instance) {
'ajax_request': true,
'token': PMA_commonParams.get('token'),
'server': PMA_commonParams.get('server'),
- 'db': PMA_commonParams.get('db')
+ 'db': PMA_commonParams.get('db'),
+ 'no_debug': true
+ };
+
+ var columnHintRender = function(elem, self, data) {
+ $('<div class="autocomplete-column-name">')
+ .text(data.columnName)
+ .appendTo(elem);
+ $('<div class="autocomplete-column-hint">')
+ .text(data.columnHint)
+ .appendTo(elem);
};
+
$.ajax({
type: 'POST',
url: href,
@@ -1765,7 +1910,7 @@ function codemirrorAutocompleteOnInputRead(instance) {
};
for (var column in columns) {
if (columns.hasOwnProperty(column)) {
- var displayText = column + ' | ' + columns[column].Type;
+ var displayText = columns[column].Type;
if (columns[column].Key == 'PRI') {
displayText += ' | Primary';
} else if (columns[column].Key == 'UNI') {
@@ -1773,7 +1918,10 @@ function codemirrorAutocompleteOnInputRead(instance) {
}
table.columns.push({
text: column,
- displayText: displayText
+ displayText: column + " | " + displayText,
+ columnName: column,
+ columnHint: displayText,
+ render: columnHintRender
});
}
}
@@ -1823,29 +1971,17 @@ function bindCodeMirrorToInlineEditor() {
var $inline_editor = $('#sql_query_edit');
if ($inline_editor.length > 0) {
if (typeof CodeMirror !== 'undefined') {
- var height = $('#sql_query_edit').css('height');
- codemirror_inline_editor = CodeMirror.fromTextArea($inline_editor[0], {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- });
- codemirror_inline_editor.on("inputRead", codemirrorAutocompleteOnInputRead);
- codemirror_inline_editor.getScrollerElement().style.height = height;
+ var height = $inline_editor.css('height');
+ codemirror_inline_editor = PMA_getSQLEditor($inline_editor);
+ codemirror_inline_editor.getWrapperElement().style.height = height;
codemirror_inline_editor.refresh();
codemirror_inline_editor.focus();
- $(codemirror_inline_editor.getWrapperElement()).bind(
- 'keydown',
- catchKeypressesFromSqlTextboxes
- );
+ $(codemirror_inline_editor.getWrapperElement())
+ .bind('keydown', catchKeypressesFromSqlTextboxes);
} else {
- $inline_editor.focus().bind(
- 'keydown',
- catchKeypressesFromSqlTextboxes
- );
+ $inline_editor
+ .focus()
+ .bind('keydown', catchKeypressesFromSqlTextboxes);
}
}
}
@@ -2492,12 +2628,13 @@ function PMA_SQLPrettyPrint(string)
* return a jQuery object yet and hence cannot be chained
*
* @param string question
- * @param string url URL to be passed to the callbackFn to make
+ * @param string url URL to be passed to the callbackFn to make
* an Ajax call to
- * @param function callbackFn callback to execute after user clicks on OK
+ * @param function callbackFn callback to execute after user clicks on OK
+ * @param function openCallback optional callback to run when dialog is shown
*/
-jQuery.fn.PMA_confirm = function (question, url, callbackFn) {
+jQuery.fn.PMA_confirm = function (question, url, callbackFn, openCallback) {
var confirmState = PMA_commonParams.get('confirm');
if (! confirmState) {
// user does not want to confirm
@@ -2541,6 +2678,7 @@ jQuery.fn.PMA_confirm = function (question, url, callbackFn) {
close: function () {
$(this).remove();
},
+ open: openCallback,
modal: true
});
};
@@ -2645,8 +2783,9 @@ AJAX.registerOnload('functions.js', function () {
.html('');
PMA_ajaxShowMessage(data.message);
// Only if the create table dialog (distinct panel) exists
- if ($("#create_table_dialog").length > 0) {
- $("#create_table_dialog").dialog("close").remove();
+ var $createTableDialog = $("#create_table_dialog");
+ if ($createTableDialog.length > 0) {
+ $createTableDialog.dialog("close").remove();
}
$('#tableslistcontainer').before(data.formatted_sql);
@@ -2697,8 +2836,12 @@ AJAX.registerOnload('functions.js', function () {
PMA_reloadNavigation();
// Redirect to table structure page on creation of new table
var params_12 = 'ajax_request=true&ajax_page_request=true';
- params_12 += AJAX.cache.menus.getRequestParam();
- tblStruct_url = 'tbl_structure.php?server=' + data._params.server + '&db='+ data._params.db + '&token='+data._params.token +'&goto=db_structure.php&table='+data._params.table+'';
+ if (! (history && history.pushState)) {
+ params_12 += PMA_Microhistory.menus.getRequestParam();
+ }
+ tblStruct_url = 'tbl_structure.php?server=' + data._params.server +
+ '&db='+ data._params.db + '&token=' + data._params.token +
+ '&goto=db_structure.php&table=' + data._params.table + '';
$.get(tblStruct_url, params_12, AJAX.responseHandler);
} else {
PMA_ajaxShowMessage(
@@ -2731,8 +2874,9 @@ AJAX.registerOnload('functions.js', function () {
//User wants to add more fields to the table
$.post($form.attr('action'), $form.serialize() + "&submit_num_fields=1", function (data) {
if (typeof data !== 'undefined' && data.success) {
- $("#page_content").html(data.message);
- PMA_highlightSQL($('#page_content'));
+ var $pageContent = $("#page_content");
+ $pageContent.html(data.message);
+ PMA_highlightSQL($pageContent);
PMA_verifyColumnsProperties();
PMA_hideShowConnection($('.create_table_form select[name=tbl_storage_engine]'));
PMA_ajaxRemoveMessage($msgbox);
@@ -2756,9 +2900,9 @@ AJAX.registerOnload('functions.js', function () {
if (this.checked) {
var col = /\d/.exec($(this).attr('name'));
col = col[0];
- var index_val = $('select[name="field_key['+col+']"]').val();
- if (index_val === 'none_'+col) {
- $('select[name="field_key['+col+']"]').val('primary_'+col).change();
+ var $selectFieldKey = $('select[name="field_key[' + col + ']"]');
+ if ($selectFieldKey.val() === 'none_'+col) {
+ $selectFieldKey.val('primary_'+col).change();
}
}
});
@@ -2858,16 +3002,17 @@ AJAX.registerOnload('functions.js', function () {
$the_form.append('<input type="hidden" name="ajax_request" value="true" />');
$.post($the_form.attr('action'), $the_form.serialize() + '&change_pw=' + this_value, function (data) {
- if (typeof data !== 'undefined' && data.success === true) {
- $("#page_content").prepend(data.message);
- PMA_highlightSQL($('#page_content'));
- $("#change_password_dialog").hide().remove();
- $("#edit_user_dialog").dialog("close").remove();
- PMA_ajaxRemoveMessage($msgbox);
- }
- else {
+ if (typeof data === 'undefined' || data.success !== true) {
PMA_ajaxShowMessage(data.error, false);
+ return;
}
+
+ var $pageContent = $("#page_content");
+ $pageContent.prepend(data.message);
+ PMA_highlightSQL($pageContent);
+ $("#change_password_dialog").hide().remove();
+ $("#edit_user_dialog").dialog("close").remove();
+ PMA_ajaxRemoveMessage($msgbox);
}); // end $.post()
};
@@ -2875,37 +3020,38 @@ AJAX.registerOnload('functions.js', function () {
$(this).dialog('close');
};
$.get($(this).attr('href'), {'ajax_request': true}, function (data) {
- if (typeof data !== 'undefined' && data.success) {
- $('<div id="change_password_dialog"></div>')
+ if (typeof data === 'undefined' || !data.success) {
+ PMA_ajaxShowMessage(data.error, false);
+ return;
+ }
+
+ $('<div id="change_password_dialog"></div>')
.dialog({
title: PMA_messages.strChangePassword,
width: 600,
close: function (ev, ui) {
$(this).remove();
},
- buttons : button_options,
+ buttons: button_options,
modal: true
})
.append(data.message);
- // for this dialog, we remove the fieldset wrapping due to double headings
- $("fieldset#fieldset_change_password")
+ // for this dialog, we remove the fieldset wrapping due to double headings
+ $("fieldset#fieldset_change_password")
.find("legend").remove().end()
.find("table.noclick").unwrap().addClass("some-margin")
.find("input#text_pma_pw").focus();
- displayPasswordGenerateButton();
- $('#fieldset_change_password_footer').hide();
- PMA_ajaxRemoveMessage($msgbox);
- $('#change_password_form').bind('submit', function (e) {
- e.preventDefault();
- $(this)
- .closest('.ui-dialog')
- .find('.ui-dialog-buttonpane .ui-button')
- .first()
- .click();
- });
- } else {
- PMA_ajaxShowMessage(data.error, false);
- }
+ displayPasswordGenerateButton();
+ $('#fieldset_change_password_footer').hide();
+ PMA_ajaxRemoveMessage($msgbox);
+ $('#change_password_form').bind('submit', function (e) {
+ e.preventDefault();
+ $(this)
+ .closest('.ui-dialog')
+ .find('.ui-dialog-buttonpane .ui-button')
+ .first()
+ .click();
+ });
}); // end $.get()
}); // end handler for change password anchor
}); // end $() for Change Password
@@ -2916,6 +3062,7 @@ AJAX.registerOnload('functions.js', function () {
AJAX.registerTeardown('functions.js', function () {
$(document).off('change', "select.column_type");
$(document).off('change', "select.default_type");
+ $(document).off('change', "select.virtuality");
$(document).off('change', 'input.allow_null');
$(document).off('change', '.create_table_form select[name=tbl_storage_engine]');
});
@@ -2935,6 +3082,9 @@ AJAX.registerOnload('functions.js', function () {
$(document).on('change', "select.default_type", function () {
PMA_hideShowDefaultValue($(this));
});
+ $(document).on('change', "select.virtuality", function () {
+ PMA_hideShowExpression($(this));
+ });
$(document).on('change', 'input.allow_null', function () {
PMA_validateDefaultValue($(this));
});
@@ -2990,38 +3140,41 @@ function autoPopulate(input_id, offset)
var db = PMA_commonParams.get('db');
var table = PMA_commonParams.get('table');
input_id = input_id.substring(0, input_id.length - 1);
- $('#'+input_id+'1').val(central_column_list[db+'_'+table][offset].col_name);
- var col_type = central_column_list[db+'_'+table][offset].col_type.toUpperCase();
- $('#'+input_id+'2').val(col_type);
- $('#'+input_id+'3').val(central_column_list[db+'_'+table][offset].col_length);
+ $('#' + input_id + '1').val(central_column_list[db + '_' + table][offset].col_name);
+ var col_type = central_column_list[db + '_' + table][offset].col_type.toUpperCase();
+ $('#' + input_id + '2').val(col_type);
+ var $input3 = $('#' + input_id + '3');
+ $input3.val(central_column_list[db + '_' + table][offset].col_length);
if(col_type === 'ENUM' || col_type === 'SET') {
- $('#'+input_id+'3').next().show();
+ $input3.next().show();
} else {
- $('#'+input_id+'3').next().hide();
+ $input3.next().hide();
}
- var col_default = central_column_list[db+'_'+table][offset].col_default.toUpperCase();
+ var col_default = central_column_list[db + '_' + table][offset].col_default.toUpperCase();
+ var $input4 = $('#' + input_id + '4');
if (col_default !== '' && col_default !== 'NULL' && col_default !== 'CURRENT_TIMESTAMP') {
- $('#'+input_id+'4').val("USER_DEFINED");
- $('#'+input_id+'4').next().next().show();
- $('#'+input_id+'4').next().next().val(central_column_list[db+'_'+table][offset].col_default);
+ $input4.val("USER_DEFINED");
+ $input4.next().next().show();
+ $input4.next().next().val(central_column_list[db + '_' + table][offset].col_default);
} else {
- $('#'+input_id+'4').val(central_column_list[db+'_'+table][offset].col_default);
- $('#'+input_id+'4').next().next().hide();
+ $input4.val(central_column_list[db + '_' + table][offset].col_default);
+ $input4.next().next().hide();
}
- $('#'+input_id+'5').val(central_column_list[db+'_'+table][offset].col_collation);
- $('#'+input_id+'6').val(central_column_list[db+'_'+table][offset].col_attribute);
- if(central_column_list[db+'_'+table][offset].col_extra === 'on update CURRENT_TIMESTAMP') {
- $('#'+input_id+'6').val(central_column_list[db+'_'+table][offset].col_extra);
+ $('#' + input_id + '5').val(central_column_list[db + '_' + table][offset].col_collation);
+ var $input6 = $('#' + input_id + '6');
+ $input6.val(central_column_list[db + '_' + table][offset].col_attribute);
+ if(central_column_list[db + '_' + table][offset].col_extra === 'on update CURRENT_TIMESTAMP') {
+ $input6.val(central_column_list[db + '_' + table][offset].col_extra);
}
- if(central_column_list[db+'_'+table][offset].col_extra.toUpperCase() === 'AUTO_INCREMENT') {
- $('#'+input_id+'9').prop("checked",true).change();
+ if(central_column_list[db + '_' + table][offset].col_extra.toUpperCase() === 'AUTO_INCREMENT') {
+ $('#' + input_id + '9').prop("checked",true).change();
} else {
- $('#'+input_id+'9').prop("checked",false);
+ $('#' + input_id + '9').prop("checked",false);
}
- if(central_column_list[db+'_'+table][offset].col_isNull !== '0') {
- $('#'+input_id+'7').prop("checked",true);
+ if(central_column_list[db + '_' + table][offset].col_isNull !== '0') {
+ $('#' + input_id + '7').prop("checked",true);
} else {
- $('#'+input_id+'7').prop("checked",false);
+ $('#' + input_id + '7').prop("checked",false);
}
}
@@ -3228,7 +3381,7 @@ AJAX.registerOnload('functions.js', function () {
var min = (list_size <= maxRows) ? list_size : maxRows;
for (i = 0; i < min; i++) {
- fields += '<tr><td><div><span style="font-size:14px; font-weight:bold">' +
+ fields += '<tr><td><div><span style="font-weight:bold">' +
escapeHtml(central_column_list[db + '_' + table][i].col_name) +
'</span><br><span style="color:gray">' + central_column_list[db + '_' + table][i].col_type;
@@ -3291,7 +3444,7 @@ AJAX.registerOnload('functions.js', function () {
min = (list_size <= maxRows + result_pointer) ? list_size : maxRows + result_pointer;
for (i = result_pointer; i < min; i++) {
- fields += '<tr><td><div><span style="font-size:14px; font-weight:bold">' +
+ fields += '<tr><td><div><span style="font-weight:bold">' +
central_column_list[db + '_' + table][i].col_name +
'</span><br><span style="color:gray">' +
central_column_list[db + '_' + table][i].col_type;
@@ -3417,11 +3570,12 @@ AJAX.registerOnload('functions.js', function () {
};
while (rows_to_add--) {
- var $newrow = $('#index_columns')
+ var $indexColumns = $('#index_columns');
+ var $newrow = $indexColumns
.find('tbody > tr:first')
.clone()
.appendTo(
- $('#index_columns').find('tbody')
+ $indexColumns.find('tbody')
);
$newrow.find(':input').each(tempEmptyVal);
// focus index size input on column picked
@@ -3433,8 +3587,9 @@ AJAX.registerOnload('functions.js', function () {
function indexEditorDialog(url, title, callback_success, callback_failure)
{
/*Remove the hidden dialogs if there are*/
- if ($('#edit_index_dialog').length !== 0) {
- $('#edit_index_dialog').remove();
+ var $editIndexDialog = $('#edit_index_dialog');
+ if ($editIndexDialog.length !== 0) {
+ $editIndexDialog.remove();
}
var $div = $('<div id="edit_index_dialog"></div>');
@@ -3452,13 +3607,15 @@ function indexEditorDialog(url, title, callback_success, callback_failure)
PMA_prepareForAjaxRequest($form);
//User wants to submit the form
$.post($form.attr('action'), $form.serialize() + "&do_save_data=1", function (data) {
- if ($(".sqlqueryresults").length !== 0) {
- $(".sqlqueryresults").remove();
+ var $sqlqueryresults = $(".sqlqueryresults");
+ if ($sqlqueryresults.length !== 0) {
+ $sqlqueryresults.remove();
}
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxShowMessage(data.message);
- if ($('.result_query').length) {
- $('.result_query').remove();
+ var $resultQuery = $('.result_query');
+ if ($resultQuery.length) {
+ $resultQuery.remove();
}
if (data.sql_query) {
$('<div class="result_query"></div>')
@@ -3467,15 +3624,16 @@ function indexEditorDialog(url, title, callback_success, callback_failure)
PMA_highlightSQL($('#page_content'));
}
$(".result_query .notice").remove();
- $(".result_query").prepend(data.message);
+ $resultQuery.prepend(data.message);
/*Reload the field form*/
$("#table_index").remove();
$("<div id='temp_div'><div>")
.append(data.index_table)
.find("#table_index")
.insertAfter("#index_header");
- if ($("#edit_index_dialog").length > 0) {
- $("#edit_index_dialog").dialog("close");
+ var $editIndexDialog = $("#edit_index_dialog");
+ if ($editIndexDialog.length > 0) {
+ $editIndexDialog.dialog("close");
}
$('div.no_indexes_defined').hide();
if (callback_success) {
@@ -3536,12 +3694,13 @@ function showIndexEditDialog($outer)
{
checkIndexType();
checkIndexName("index_frm");
- $('#index_columns td').each(function () {
+ var $indexColumns = $('#index_columns');
+ $indexColumns.find('td').each(function () {
$(this).css("width", $(this).width() + 'px');
});
- $('#index_columns tbody').sortable({
+ $indexColumns.find('tbody').sortable({
axis: 'y',
- containment: $("#index_columns tbody"),
+ containment: $indexColumns.find("tbody"),
tolerance: 'pointer'
});
PMA_showHints($outer);
@@ -3834,9 +3993,11 @@ AJAX.registerOnload('functions.js', function () {
}
});
- if ($('#update_recent_tables').length) {
+ var $updateRecentTables = $('#update_recent_tables');
+ if ($updateRecentTables.length) {
$.get(
- $('#update_recent_tables').attr('href'),
+ $updateRecentTables.attr('href'),
+ {no_debug: true},
function (data) {
if (typeof data !== 'undefined' && data.success === true) {
$('#pma_recent_list').html(data.list);
@@ -3852,15 +4013,15 @@ AJAX.registerOnload('functions.js', function () {
cache: false,
type: 'POST',
data: {
- favorite_tables: (isStorageSupported('localStorage'))
- ? window.localStorage['favorite_tables']
- : ''
+ favorite_tables: (isStorageSupported('localStorage') && typeof window.localStorage.favorite_tables !== 'undefined')
+ ? window.localStorage.favorite_tables
+ : '',
+ no_debug: true
},
success: function (data) {
// Update localStorage.
if (isStorageSupported('localStorage')) {
- window.localStorage.favorite_tables
- = data.favorite_tables;
+ window.localStorage.favorite_tables = data.favorite_tables;
}
$('#pma_favorite_list').html(data.list);
}
@@ -3896,7 +4057,7 @@ function PMA_init_slider()
var $wrapper = $('<div>', {'class': 'slide-wrapper'});
$wrapper.toggle($this.is(':visible'));
$('<a>', {href: '#' + this.id, "class": 'ajax'})
- .text(this.title)
+ .text($this.attr('title'))
.prepend($('<span>'))
.insertBefore($this)
.click(function () {
@@ -3907,11 +4068,13 @@ function PMA_init_slider()
}
$this[visible ? 'hide' : 'show']('blind', function () {
$wrapper.toggle(!visible);
+ $wrapper.parent().toggleClass("print_ignore", visible);
PMA_set_status_label($this);
});
return false;
});
$this.wrap($wrapper);
+ $this.removeAttr('title');
PMA_set_status_label($this);
$this.data('slider_init_done', 1);
});
@@ -4031,25 +4194,16 @@ AJAX.registerOnload('functions.js', function () {
var $elm = $('#sqlquery');
if ($elm.length > 0) {
if (typeof CodeMirror != 'undefined') {
- // for codemirror
- codemirror_editor = CodeMirror.fromTextArea($elm[0], {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- });
- codemirror_editor.on("inputRead", codemirrorAutocompleteOnInputRead);
+ codemirror_editor = PMA_getSQLEditor($elm);
codemirror_editor.focus();
- $(codemirror_editor.getWrapperElement()).bind(
- 'keydown',
- catchKeypressesFromSqlTextboxes
- );
+ $(codemirror_editor.getWrapperElement())
+ .bind('keydown', catchKeypressesFromSqlTextboxes);
+ codemirror_editor.on("blur", updateQueryParameters);
} else {
// without codemirror
- $elm.focus().bind('keydown', catchKeypressesFromSqlTextboxes);
+ $elm.focus()
+ .bind('keydown', catchKeypressesFromSqlTextboxes)
+ .bind('blur', updateQueryParameters);
}
}
PMA_highlightSQL($('body'));
@@ -4065,13 +4219,23 @@ AJAX.registerOnload('functions.js', function () {
// initializes all lock-page elements lock-id and
// val-hash data property
$('#page_content form.lock-page textarea, ' +
- '#page_content form.lock-page input[type="text"]').each(function (i) {
+ '#page_content form.lock-page input[type="text"], '+
+ '#page_content form.lock-page input[type="number"], '+
+ '#page_content form.lock-page select').each(function (i) {
$(this).data('lock-id', i);
// val-hash is the hash of default value of the field
// so that it can be compared with new value hash
// to check whether field was modified or not.
$(this).data('val-hash', AJAX.hash($(this).val()));
});
+
+ // initializes lock-page elements (input types checkbox and radio buttons)
+ // lock-id and val-hash data property
+ $('#page_content form.lock-page input[type="checkbox"], ' +
+ '#page_content form.lock-page input[type="radio"]').each(function (i) {
+ $(this).data('lock-id', i);
+ $(this).data('val-hash', AJAX.hash($(this).is(":checked")));
+ });
});
/**
* jQuery plugin to cancel selection in HTML code.
@@ -4234,32 +4398,8 @@ AJAX.registerOnload('functions.js', function () {
}); // end $(document).on()
}
- var $elm = $('textarea[name="view[as]"]');
- if ($elm.length > 0) {
- if (typeof CodeMirror != 'undefined') {
- syntaxHighlighter = CodeMirror.fromTextArea(
- $elm[0],
- {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- }
- );
- syntaxHighlighter.on("inputRead", codemirrorAutocompleteOnInputRead);
- }
- }
+ syntaxHighlighter = PMA_getSQLEditor($('textarea[name="view[as]"]'));
- $(document).on('change', '#fkc_checkbox', function () {
- if ($(this).prop("checked")) {
- $("#fkc_status").html(PMA_messages.strForeignKeyCheckEnabled);
- } else {
- $("#fkc_status").html(PMA_messages.strForeignKeyCheckDisabled);
- }
- }); // End of event handler for 'Foreign Key Check'
});
function PMA_createViewDialog($this)
@@ -4300,19 +4440,7 @@ function PMA_createViewDialog($this)
}
});
// Attach syntax highlighted editor
- if (typeof CodeMirror !== 'undefined') {
- var $elm = $dialog.find('textarea');
- syntaxHighlighter = CodeMirror.fromTextArea($elm[0], {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- });
- syntaxHighlighter.on("inputRead", codemirrorAutocompleteOnInputRead);
- }
+ syntaxHighlighter = PMA_getSQLEditor($dialog.find('textarea'));
$('input:visible[type=text]', $dialog).first().focus();
} else {
PMA_ajaxShowMessage(data.error);
@@ -4388,6 +4516,35 @@ $(document).on("change", "input.checkall_box", function () {
});
/**
+ * Watches checkboxes in a sub form to set the sub checkall box accordingly
+ */
+var sub_checkboxes_changed = function () {
+ var $form = $(this).parent().parent();
+ // total number of checkboxes in current sub form
+ var total_boxes = $form.find(checkboxes_sel).length;
+ // number of checkboxes checked in current sub form
+ var checked_boxes = $form.find(checkboxes_sel + ":checked").length;
+ var $checkall = $form.find("input.sub_checkall_box");
+ if (total_boxes == checked_boxes) {
+ $checkall.prop({checked: true, indeterminate: false});
+ }
+ else if (checked_boxes > 0) {
+ $checkall.prop({checked: true, indeterminate: true});
+ }
+ else {
+ $checkall.prop({checked: false, indeterminate: false});
+ }
+};
+$(document).on("change", checkboxes_sel + ", input.checkall_box:checkbox:enabled", sub_checkboxes_changed);
+
+$(document).on("change", "input.sub_checkall_box", function () {
+ var is_checked = $(this).is(":checked");
+ var $form = $(this).parent().parent();
+ $form.find(checkboxes_sel).prop("checked", is_checked)
+ .parents("tr").toggleClass("marked", is_checked);
+});
+
+/**
* Toggles row colors of a set of 'tr' elements starting from a given element
*
* @param $start Starting element
@@ -4530,21 +4687,23 @@ function checkNumberOfFields() {
*
*/
function PMA_ignorePhpErrors(clearPrevErrors){
- if (typeof(clearPrevErrors) === "undefined"
- || clearPrevErrors === null
+ if (typeof(clearPrevErrors) === "undefined" ||
+ clearPrevErrors === null
) {
str = false;
}
// send AJAX request to error_report.php with send_error_report=0, exception_type=php & token.
// It clears the prev_errors stored in session.
if(clearPrevErrors){
- $('#pma_report_errors_form input[name="send_error_report"]').val(0); // change send_error_report to '0'
- $('#pma_report_errors_form').submit();
+ var $pmaReportErrorsForm = $('#pma_report_errors_form');
+ $pmaReportErrorsForm.find('input[name="send_error_report"]').val(0); // change send_error_report to '0'
+ $pmaReportErrorsForm.submit();
}
// remove displayed errors
- $('#pma_errors').fadeOut( "slow");
- $('#pma_errors').remove();
+ var $pmaErrors = $('#pma_errors');
+ $pmaErrors.fadeOut( "slow");
+ $pmaErrors.remove();
}
/**
@@ -4570,3 +4729,48 @@ function isStorageSupported(type)
}
return false;
}
+
+/**
+ * Unbind all event handlers before tearing down a page
+ */
+AJAX.registerTeardown('functions.js', function(){
+ $(document).off('keydown', 'form input, form textarea, form select');
+});
+
+AJAX.registerOnload('functions.js', function () {
+ /**
+ * Handle 'Ctrl/Alt + Enter' form submits
+ */
+ $('form input, form textarea, form select').on('keydown', function(e){
+ if((e.ctrlKey && e.which == 13) || (e.altKey && e.which == 13)) {
+ $form = $(this).closest('form');
+ if (! $form.find('input[type="submit"]') ||
+ ! $form.find('input[type="submit"]').click()
+ ) {
+ $form.submit();
+ }
+ }
+ });
+});
+
+/**
+ * Unbind all event handlers before tearing down a page
+ */
+AJAX.registerTeardown('functions.js', function(){
+ $(document).off('change', 'input[type=radio][name="pw_hash"]');
+});
+
+AJAX.registerOnload('functions.js', function(){
+ /*
+ * Display warning regarding SSL when sha256_password
+ * method is selected
+ * Used in user_password.php (Change Password link on index.php)
+ */
+ $(document).on("change", 'input[type=radio][name="pw_hash"]', function() {
+ if (this.value === 'sha256_password') {
+ $('#ssl_reqd_warning_cp').show();
+ } else {
+ $('#ssl_reqd_warning_cp').hide();
+ }
+ });
+});
diff --git a/js/get_image.js.php b/js/get_image.js.php
index 7ac1ffd410..8dfce6b8fb 100644
--- a/js/get_image.js.php
+++ b/js/get_image.js.php
@@ -20,9 +20,11 @@ require_once './libraries/common.inc.php';
require_once './libraries/OutputBuffering.class.php';
$buffer = PMA_OutputBuffering::getInstance();
$buffer->start();
-register_shutdown_function(function() {
- echo PMA_OutputBuffering::getInstance()->getContents();
-});
+register_shutdown_function(
+ function () {
+ echo PMA_OutputBuffering::getInstance()->getContents();
+ }
+);
// Get the data for the sprites, if it's available
if (is_readable($_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php')) {
@@ -136,7 +138,9 @@ function PMA_getImage(image, alternate, attributes) {
if (i == 'src') {
// do not allow to override the 'src' attribute
continue;
- } else if (i == 'class') {
+ }
+
+ if (i == 'class') {
retval.attr(i, retval.attr('class') + ' ' + attributes[i]);
} else {
retval.attr(i, attributes[i]);
diff --git a/js/get_scripts.js.php b/js/get_scripts.js.php
index 742213e0f1..b6ad2b4006 100644
--- a/js/get_scripts.js.php
+++ b/js/get_scripts.js.php
@@ -26,12 +26,14 @@ $_GET['scripts'] = json_encode($_GET['scripts']);
define('PMA_MINIMUM_COMMON', true);
require_once './libraries/common.inc.php';
-include_once './libraries/OutputBuffering.class.php';
+require_once './libraries/OutputBuffering.class.php';
$buffer = PMA_OutputBuffering::getInstance();
$buffer->start();
-register_shutdown_function(function() {
- echo PMA_OutputBuffering::getInstance()->getContents();
-});
+register_shutdown_function(
+ function () {
+ echo PMA_OutputBuffering::getInstance()->getContents();
+ }
+);
$_GET['scripts'] = json_decode($_GET['scripts']);
if (! empty($_GET['scripts']) && is_array($_GET['scripts'])) {
@@ -59,4 +61,3 @@ if (! empty($_GET['scripts']) && is_array($_GET['scripts'])) {
if (isset($_GET['call_done'])) {
echo "AJAX.scriptHandler.done();";
}
-?>
diff --git a/js/gis_data_editor.js b/js/gis_data_editor.js
index 0fb39d7a75..565e1ebba6 100644
--- a/js/gis_data_editor.js
+++ b/js/gis_data_editor.js
@@ -19,11 +19,11 @@ function closeGISEditor() {
}
/**
- * Prepares the HTML recieved via AJAX.
+ * Prepares the HTML received via AJAX.
*/
function prepareJSVersion() {
// Change the text on the submit button
- $("#gis_editor input[name='gis_data[save]']")
+ $("#gis_editor").find("input[name='gis_data[save]']")
.val(PMA_messages.strCopy)
.insertAfter($('#gis_data_textarea'))
.before('<br/><br/>');
@@ -37,7 +37,7 @@ function prepareJSVersion() {
$('div#gis_data_output p').remove();
// Remove 'add' buttons and add links
- $('#gis_editor input.add').each(function (e) {
+ $('#gis_editor').find('input.add').each(function (e) {
var $button = $(this);
$button.addClass('addJs').removeClass('add');
var classes = $button.attr('class');
diff --git a/js/import.js b/js/import.js
index ab3f17c449..61bd9dbac5 100644
--- a/js/import.js
+++ b/js/import.js
@@ -11,10 +11,10 @@
*/
function changePluginOpts()
{
- $("#format_specific_opts div.format_specific_options").each(function () {
+ $("#format_specific_opts").find("div.format_specific_options").each(function () {
$(this).hide();
});
- var selected_plugin_name = $("#plugins option:selected").val();
+ var selected_plugin_name = $("#plugins").find("option:selected").val();
$("#" + selected_plugin_name + "_options").fadeIn('slow');
if (selected_plugin_name == "csv") {
$("#import_notification").text(PMA_messages.strImportCSV);
@@ -141,7 +141,7 @@ AJAX.registerOnload('import.js', function () {
* Javascript-disabled browsers
*/
$("#scroll_to_options_msg").hide();
- $("#format_specific_opts div.format_specific_options")
+ $("#format_specific_opts").find("div.format_specific_options")
.css({
"border": 0,
"margin": 0,
diff --git a/js/indexes.js b/js/indexes.js
index 57f9d743b9..00ef9db463 100644
--- a/js/indexes.js
+++ b/js/indexes.js
@@ -17,27 +17,27 @@ function checkIndexType()
/**
* @var Object Dropdown to select the index choice.
*/
- $select_index_choice = $('#select_index_choice');
+ var $select_index_choice = $('#select_index_choice');
/**
* @var Object Dropdown to select the index type.
*/
- $select_index_type = $('#select_index_type');
+ var $select_index_type = $('#select_index_type');
/**
* @var Object Table header for the size column.
*/
- $size_header = $('#index_columns thead tr th:nth-child(2)');
+ var $size_header = $('#index_columns').find('thead tr th:nth-child(2)');
/**
* @var Object Inputs to specify the columns for the index.
*/
- $column_inputs = $('select[name="index[columns][names][]"]');
+ var $column_inputs = $('select[name="index[columns][names][]"]');
/**
* @var Object Inputs to specify sizes for columns of the index.
*/
- $size_inputs = $('input[name="index[columns][sub_parts][]"]');
+ var $size_inputs = $('input[name="index[columns][sub_parts][]"]');
/**
* @var Object Footer containg the controllers to add more columns
*/
- $add_more = $('#index_frm .add_more');
+ var $add_more = $('#index_frm').find('.add_more');
if ($select_index_choice.val() == 'SPATIAL') {
// Disable and hide the size column
@@ -122,20 +122,8 @@ function PMA_removeColumnFromIndex(col_index)
.attr('data-index');
if (previous_index.length) {
previous_index = previous_index.split(',');
- switch (previous_index[0].toLowerCase()) {
- case 'primary':
- source_array = primary_indexes;
- break;
- case 'unique':
- source_array = unique_indexes;
- break;
- case 'index':
- source_array = indexes;
- break;
- case 'fulltext':
- source_array = fulltext_indexes;
- break;
- default:
+ var source_array = PMA_getIndexArray(previous_index[0]);
+ if (source_array == null) {
return;
}
@@ -171,15 +159,17 @@ function PMA_removeColumnFromIndex(col_index)
*/
function PMA_addColumnToIndex(source_array, array_index, index_choice, col_index)
{
- // Remove column from other indexes (if any).
- PMA_removeColumnFromIndex(col_index);
+ if (col_index >= 0) {
+ // Remove column from other indexes (if any).
+ PMA_removeColumnFromIndex(col_index);
+ }
var index_name = $('input[name="index[Key_name]"]').val();
var index_comment = $('input[name="index[Index_comment]"]').val();
var key_block_size = $('input[name="index[Key_block_size]"]').val();
var parser = $('input[name="index[Parser]"]').val();
var index_type = $('select[name="index[Index_type]"]').val();
var columns = [];
- $('#index_columns tbody').find('tr').each(function () {
+ $('#index_columns').find('tbody').find('tr').each(function () {
// Get columns in particular order.
var col_index = $(this).find('select[name="index[columns][names][]"]').val();
var size = $(this).find('input[name="index[columns][sub_parts][]"]').val();
@@ -200,9 +190,31 @@ function PMA_addColumnToIndex(source_array, array_index, index_choice, col_index
'columns': columns
};
- // Update index details on form.
- $('select[name="field_key[' + col_index + ']"]')
- .attr('data-index', index_choice + ',' + array_index);
+ // Display index name (or column list)
+ var displayName = index_name;
+ if (displayName == '') {
+ var columnNames = [];
+ $.each(columns, function () {
+ columnNames.push($('input[name="field_name[' + this.col_index + ']"]').val());
+ });
+ displayName = '[' + columnNames.join(', ') + ']';
+ }
+ $.each(columns, function () {
+ var id = 'index_name_' + this.col_index + '_8';
+ var $name = $('#' + id);
+ if ($name.length == 0) {
+ $name = $('<a id="' + id + '" href="#" class="ajax show_index_dialog"></a>');
+ $name.insertAfter($('select[name="field_key[' + this.col_index + ']"]'));
+ }
+ var $text = $('<small>').text(displayName);
+ $name.html($text);
+ });
+
+ if (col_index >= 0) {
+ // Update index details on form.
+ $('select[name="field_key[' + col_index + ']"]')
+ .attr('data-index', index_choice + ',' + array_index);
+ }
PMA_setIndexFormParameters(source_array, index_choice.toLowerCase());
}
@@ -292,7 +304,7 @@ function PMA_showAddIndexDialog(source_array, array_index, target_columns, col_i
}
post_data.columns = JSON.stringify(columns);
- button_options = {};
+ var button_options = {};
button_options[PMA_messages.strGo] = function () {
var is_missing_value = false;
$('select[name="index[columns][names][]"]').each(function () {
@@ -321,14 +333,16 @@ function PMA_showAddIndexDialog(source_array, array_index, target_columns, col_i
$(this).dialog('close');
};
button_options[PMA_messages.strCancel] = function () {
- // Handle state on 'Cancel'.
- var $select_list = $('select[name="field_key[' + col_index + ']"]');
- if (! $select_list.attr('data-index').length) {
- $select_list.find('option[value*="none"]').attr('selected', 'selected');
- } else {
- var previous_index = $select_list.attr('data-index').split(',');
- $select_list.find('option[value*="' + previous_index[0].toLowerCase() + '"]')
- .attr('selected', 'selected');
+ if (col_index >= 0) {
+ // Handle state on 'Cancel'.
+ var $select_list = $('select[name="field_key[' + col_index + ']"]');
+ if (! $select_list.attr('data-index').length) {
+ $select_list.find('option[value*="none"]').attr('selected', 'selected');
+ } else {
+ var previous_index = $select_list.attr('data-index').split(',');
+ $select_list.find('option[value*="' + previous_index[0].toLowerCase() + '"]')
+ .attr('selected', 'selected');
+ }
}
$(this).dialog('close');
};
@@ -340,7 +354,7 @@ function PMA_showAddIndexDialog(source_array, array_index, target_columns, col_i
} else {
PMA_ajaxRemoveMessage($msgbox);
// Show dialog if the request was successful
- $div = $('<div/>');
+ var $div = $('<div/>');
$div
.append(data.message)
.dialog({
@@ -351,12 +365,12 @@ function PMA_showAddIndexDialog(source_array, array_index, target_columns, col_i
checkIndexName("index_frm");
PMA_showHints($div);
PMA_init_slider();
- $('#index_columns td').each(function () {
+ $('#index_columns').find('td').each(function () {
$(this).css("width", $(this).width() + 'px');
});
- $('#index_columns tbody').sortable({
+ $('#index_columns').find('tbody').sortable({
axis: 'y',
- containment: $("#index_columns tbody"),
+ containment: $("#index_columns").find("tbody"),
tolerance: 'pointer'
});
// We dont need the slider at this moment.
@@ -477,6 +491,38 @@ function PMA_indexTypeSelectionDialog(source_array, index_choice, col_index)
}
/**
+ * Returns the array of indexes based on the index choice
+ *
+ * @param index_choice index choice
+ */
+function PMA_getIndexArray(index_choice)
+{
+ var source_array = null;
+
+ switch (index_choice.toLowerCase()) {
+ case 'primary':
+ source_array = primary_indexes;
+ break;
+ case 'unique':
+ source_array = unique_indexes;
+ break;
+ case 'index':
+ source_array = indexes;
+ break;
+ case 'fulltext':
+ source_array = fulltext_indexes;
+ break;
+ case 'spatial':
+ source_array = spatial_indexes;
+ break;
+ default:
+ return null;
+ }
+ return source_array;
+}
+
+
+/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('indexes.js', function () {
@@ -487,6 +533,7 @@ AJAX.registerTeardown('indexes.js', function () {
$(document).off('click', "#table_index tbody tr td.edit_index.ajax, #indexes .add_index.ajax");
$(document).off('click', '#index_frm input[type=submit]');
$('body').off('change', 'select[name*="field_key"]');
+ $(document).off('click', '.show_index_dialog');
});
/**
@@ -504,6 +551,7 @@ AJAX.registerOnload('indexes.js', function () {
unique_indexes = [];
indexes = [];
fulltext_indexes = [];
+ spatial_indexes = [];
// for table creation form
var $engine_selector = $('.create_table_form select[name=tbl_storage_engine]');
@@ -655,19 +703,9 @@ AJAX.registerOnload('indexes.js', function () {
}
// Select a source array.
- switch (index_choice) {
- case 'primary':
- source_array = primary_indexes;
- break;
- case 'unique':
- source_array = unique_indexes;
- break;
- case 'index':
- source_array = indexes;
- break;
- case 'fulltext':
- source_array = fulltext_indexes;
- break;
+ var source_array = PMA_getIndexArray(index_choice);
+ if (source_array == null) {
+ return;
}
if (source_array.length === 0) {
@@ -694,4 +732,26 @@ AJAX.registerOnload('indexes.js', function () {
}
}
});
+
+ $(document).on('click', '.show_index_dialog', function (e) {
+ e.preventDefault();
+
+ // Get index details.
+ var previous_index = $(this).prev('select')
+ .attr('data-index')
+ .split(',');
+
+ var index_choice = previous_index[0];
+ var array_index = previous_index[1];
+
+ var source_array = PMA_getIndexArray(index_choice);
+ var source_length = source_array[array_index].columns.length;
+
+ var target_columns = [];
+ for (var i = 0; i < source_length; i++) {
+ target_columns.push(source_array[array_index].columns[i].col_index);
+ }
+
+ PMA_showAddIndexDialog(source_array, array_index, target_columns, -1, source_array[array_index]);
+ })
});
diff --git a/js/jquery/additional-methods.js b/js/jquery/additional-methods.js
new file mode 100644
index 0000000000..fc254b7d76
--- /dev/null
+++ b/js/jquery/additional-methods.js
@@ -0,0 +1,940 @@
+/*!
+ * jQuery Validation Plugin v1.13.1
+ *
+ * http://jqueryvalidation.org/
+ *
+ * Copyright (c) 2014 Jörn Zaefferer
+ * Released under the MIT license
+ */
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+ define( ["jquery", "./jquery.validate"], factory );
+ } else {
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+(function() {
+
+ function stripHtml(value) {
+ // remove html tags and space chars
+ return value.replace(/<.[^<>]*?>/g, " ").replace(/&nbsp;|&#160;/gi, " ")
+ // remove punctuation
+ .replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "");
+ }
+
+ $.validator.addMethod("maxWords", function(value, element, params) {
+ return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params;
+ }, $.validator.format("Please enter {0} words or less."));
+
+ $.validator.addMethod("minWords", function(value, element, params) {
+ return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params;
+ }, $.validator.format("Please enter at least {0} words."));
+
+ $.validator.addMethod("rangeWords", function(value, element, params) {
+ var valueStripped = stripHtml(value),
+ regex = /\b\w+\b/g;
+ return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];
+ }, $.validator.format("Please enter between {0} and {1} words."));
+
+}());
+
+// Accept a value from a file input based on a required mimetype
+$.validator.addMethod("accept", function(value, element, param) {
+ // Split mime on commas in case we have multiple types we can accept
+ var typeParam = typeof param === "string" ? param.replace(/\s/g, "").replace(/,/g, "|") : "image/*",
+ optionalValue = this.optional(element),
+ i, file;
+
+ // Element is optional
+ if (optionalValue) {
+ return optionalValue;
+ }
+
+ if ($(element).attr("type") === "file") {
+ // If we are using a wildcard, make it regex friendly
+ typeParam = typeParam.replace(/\*/g, ".*");
+
+ // Check if the element has a FileList before checking each file
+ if (element.files && element.files.length) {
+ for (i = 0; i < element.files.length; i++) {
+ file = element.files[i];
+
+ // Grab the mimetype from the loaded file, verify it matches
+ if (!file.type.match(new RegExp( ".?(" + typeParam + ")$", "i"))) {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Either return true because we've validated each file, or because the
+ // browser does not support element.files and the FileList feature
+ return true;
+}, $.validator.format("Please enter a value with a valid mimetype."));
+
+$.validator.addMethod("alphanumeric", function(value, element) {
+ return this.optional(element) || /^\w+$/i.test(value);
+}, "Letters, numbers, and underscores only please");
+
+/*
+ * Dutch bank account numbers (not 'giro' numbers) have 9 digits
+ * and pass the '11 check'.
+ * We accept the notation with spaces, as that is common.
+ * acceptable: 123456789 or 12 34 56 789
+ */
+$.validator.addMethod("bankaccountNL", function(value, element) {
+ if (this.optional(element)) {
+ return true;
+ }
+ if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {
+ return false;
+ }
+ // now '11 check'
+ var account = value.replace(/ /g, ""), // remove spaces
+ sum = 0,
+ len = account.length,
+ pos, factor, digit;
+ for ( pos = 0; pos < len; pos++ ) {
+ factor = len - pos;
+ digit = account.substring(pos, pos + 1);
+ sum = sum + factor * digit;
+ }
+ return sum % 11 === 0;
+}, "Please specify a valid bank account number");
+
+$.validator.addMethod("bankorgiroaccountNL", function(value, element) {
+ return this.optional(element) ||
+ ($.validator.methods.bankaccountNL.call(this, value, element)) ||
+ ($.validator.methods.giroaccountNL.call(this, value, element));
+}, "Please specify a valid bank or giro account number");
+
+/**
+ * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
+ *
+ * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
+ *
+ * BIC definition in detail:
+ * - First 4 characters - bank code (only letters)
+ * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
+ * - Next 2 characters - location code (letters and digits)
+ * a. shall not start with '0' or '1'
+ * b. second character must be a letter ('O' is not allowed) or one of the following digits ('0' for test (therefore not allowed), '1' for passive participant and '2' for active participant)
+ * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
+ */
+$.validator.addMethod("bic", function(value, element) {
+ return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value );
+}, "Please specify a valid BIC code");
+
+/*
+ * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
+ * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
+ */
+$.validator.addMethod( "cifES", function( value ) {
+ "use strict";
+
+ var num = [],
+ controlDigit, sum, i, count, tmp, secondDigit;
+
+ value = value.toUpperCase();
+
+ // Quick format test
+ if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
+ return false;
+ }
+
+ for ( i = 0; i < 9; i++ ) {
+ num[ i ] = parseInt( value.charAt( i ), 10 );
+ }
+
+ // Algorithm for checking CIF codes
+ sum = num[ 2 ] + num[ 4 ] + num[ 6 ];
+ for ( count = 1; count < 8; count += 2 ) {
+ tmp = ( 2 * num[ count ] ).toString();
+ secondDigit = tmp.charAt( 1 );
+
+ sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) );
+ }
+
+ /* The first (position 1) is a letter following the following criteria:
+ * A. Corporations
+ * B. LLCs
+ * C. General partnerships
+ * D. Companies limited partnerships
+ * E. Communities of goods
+ * F. Cooperative Societies
+ * G. Associations
+ * H. Communities of homeowners in horizontal property regime
+ * J. Civil Societies
+ * K. Old format
+ * L. Old format
+ * M. Old format
+ * N. Nonresident entities
+ * P. Local authorities
+ * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
+ * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
+ * S. Organs of State Administration and regions
+ * V. Agrarian Transformation
+ * W. Permanent establishments of non-resident in Spain
+ */
+ if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {
+ sum += "";
+ controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );
+ value += controlDigit;
+ return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );
+ }
+
+ return false;
+
+}, "Please specify a valid CIF number." );
+
+/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
+ * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
+ * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
+ */
+$.validator.addMethod("creditcardtypes", function(value, element, param) {
+ if (/[^0-9\-]+/.test(value)) {
+ return false;
+ }
+
+ value = value.replace(/\D/g, "");
+
+ var validTypes = 0x0000;
+
+ if (param.mastercard) {
+ validTypes |= 0x0001;
+ }
+ if (param.visa) {
+ validTypes |= 0x0002;
+ }
+ if (param.amex) {
+ validTypes |= 0x0004;
+ }
+ if (param.dinersclub) {
+ validTypes |= 0x0008;
+ }
+ if (param.enroute) {
+ validTypes |= 0x0010;
+ }
+ if (param.discover) {
+ validTypes |= 0x0020;
+ }
+ if (param.jcb) {
+ validTypes |= 0x0040;
+ }
+ if (param.unknown) {
+ validTypes |= 0x0080;
+ }
+ if (param.all) {
+ validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
+ }
+ if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard
+ return value.length === 16;
+ }
+ if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa
+ return value.length === 16;
+ }
+ if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex
+ return value.length === 15;
+ }
+ if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub
+ return value.length === 14;
+ }
+ if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute
+ return value.length === 15;
+ }
+ if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover
+ return value.length === 16;
+ }
+ if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb
+ return value.length === 16;
+ }
+ if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb
+ return value.length === 15;
+ }
+ if (validTypes & 0x0080) { //unknown
+ return true;
+ }
+ return false;
+}, "Please enter a valid credit card number.");
+
+/**
+ * Validates currencies with any given symbols by @jameslouiz
+ * Symbols can be optional or required. Symbols required by default
+ *
+ * Usage examples:
+ * currency: ["£", false] - Use false for soft currency validation
+ * currency: ["$", false]
+ * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
+ *
+ * <input class="currencyInput" name="currencyInput">
+ *
+ * Soft symbol checking
+ * currencyInput: {
+ * currency: ["$", false]
+ * }
+ *
+ * Strict symbol checking (default)
+ * currencyInput: {
+ * currency: "$"
+ * //OR
+ * currency: ["$", true]
+ * }
+ *
+ * Multiple Symbols
+ * currencyInput: {
+ * currency: "$,£,¢"
+ * }
+ */
+$.validator.addMethod("currency", function(value, element, param) {
+ var isParamString = typeof param === "string",
+ symbol = isParamString ? param : param[0],
+ soft = isParamString ? true : param[1],
+ regex;
+
+ symbol = symbol.replace(/,/g, "");
+ symbol = soft ? symbol + "]" : symbol + "]?";
+ regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$";
+ regex = new RegExp(regex);
+ return this.optional(element) || regex.test(value);
+
+}, "Please specify a valid currency");
+
+$.validator.addMethod("dateFA", function(value, element) {
+ return this.optional(element) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(value);
+}, "Please enter a correct date");
+
+/**
+ * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
+ *
+ * @example $.validator.methods.date("01/01/1900")
+ * @result true
+ *
+ * @example $.validator.methods.date("01/13/1990")
+ * @result false
+ *
+ * @example $.validator.methods.date("01.01.1900")
+ * @result false
+ *
+ * @example <input name="pippo" class="{dateITA:true}" />
+ * @desc Declares an optional input element whose value must be a valid date.
+ *
+ * @name $.validator.methods.dateITA
+ * @type Boolean
+ * @cat Plugins/Validate/Methods
+ */
+$.validator.addMethod("dateITA", function(value, element) {
+ var check = false,
+ re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
+ adata, gg, mm, aaaa, xdata;
+ if ( re.test(value)) {
+ adata = value.split("/");
+ gg = parseInt(adata[0], 10);
+ mm = parseInt(adata[1], 10);
+ aaaa = parseInt(adata[2], 10);
+ xdata = new Date(aaaa, mm - 1, gg, 12, 0, 0, 0);
+ if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth () === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
+ check = true;
+ } else {
+ check = false;
+ }
+ } else {
+ check = false;
+ }
+ return this.optional(element) || check;
+}, "Please enter a correct date");
+
+$.validator.addMethod("dateNL", function(value, element) {
+ return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
+}, "Please enter a correct date");
+
+// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
+$.validator.addMethod("extension", function(value, element, param) {
+ param = typeof param === "string" ? param.replace(/,/g, "|") : "png|jpe?g|gif";
+ return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
+}, $.validator.format("Please enter a value with a valid extension."));
+
+/**
+ * Dutch giro account numbers (not bank numbers) have max 7 digits
+ */
+$.validator.addMethod("giroaccountNL", function(value, element) {
+ return this.optional(element) || /^[0-9]{1,7}$/.test(value);
+}, "Please specify a valid giro account number");
+
+/**
+ * IBAN is the international bank account number.
+ * It has a country - specific format, that is checked here too
+ */
+$.validator.addMethod("iban", function(value, element) {
+ // some quick simple tests to prevent needless work
+ if (this.optional(element)) {
+ return true;
+ }
+
+ // remove spaces and to upper case
+ var iban = value.replace(/ /g, "").toUpperCase(),
+ ibancheckdigits = "",
+ leadingZeroes = true,
+ cRest = "",
+ cOperator = "",
+ countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
+
+ if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(iban))) {
+ return false;
+ }
+
+ // check the country code and find the country specific format
+ countrycode = iban.substring(0, 2);
+ bbancountrypatterns = {
+ "AL": "\\d{8}[\\dA-Z]{16}",
+ "AD": "\\d{8}[\\dA-Z]{12}",
+ "AT": "\\d{16}",
+ "AZ": "[\\dA-Z]{4}\\d{20}",
+ "BE": "\\d{12}",
+ "BH": "[A-Z]{4}[\\dA-Z]{14}",
+ "BA": "\\d{16}",
+ "BR": "\\d{23}[A-Z][\\dA-Z]",
+ "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
+ "CR": "\\d{17}",
+ "HR": "\\d{17}",
+ "CY": "\\d{8}[\\dA-Z]{16}",
+ "CZ": "\\d{20}",
+ "DK": "\\d{14}",
+ "DO": "[A-Z]{4}\\d{20}",
+ "EE": "\\d{16}",
+ "FO": "\\d{14}",
+ "FI": "\\d{14}",
+ "FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
+ "GE": "[\\dA-Z]{2}\\d{16}",
+ "DE": "\\d{18}",
+ "GI": "[A-Z]{4}[\\dA-Z]{15}",
+ "GR": "\\d{7}[\\dA-Z]{16}",
+ "GL": "\\d{14}",
+ "GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
+ "HU": "\\d{24}",
+ "IS": "\\d{22}",
+ "IE": "[\\dA-Z]{4}\\d{14}",
+ "IL": "\\d{19}",
+ "IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
+ "KZ": "\\d{3}[\\dA-Z]{13}",
+ "KW": "[A-Z]{4}[\\dA-Z]{22}",
+ "LV": "[A-Z]{4}[\\dA-Z]{13}",
+ "LB": "\\d{4}[\\dA-Z]{20}",
+ "LI": "\\d{5}[\\dA-Z]{12}",
+ "LT": "\\d{16}",
+ "LU": "\\d{3}[\\dA-Z]{13}",
+ "MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
+ "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
+ "MR": "\\d{23}",
+ "MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
+ "MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
+ "MD": "[\\dA-Z]{2}\\d{18}",
+ "ME": "\\d{18}",
+ "NL": "[A-Z]{4}\\d{10}",
+ "NO": "\\d{11}",
+ "PK": "[\\dA-Z]{4}\\d{16}",
+ "PS": "[\\dA-Z]{4}\\d{21}",
+ "PL": "\\d{24}",
+ "PT": "\\d{21}",
+ "RO": "[A-Z]{4}[\\dA-Z]{16}",
+ "SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
+ "SA": "\\d{2}[\\dA-Z]{18}",
+ "RS": "\\d{18}",
+ "SK": "\\d{20}",
+ "SI": "\\d{15}",
+ "ES": "\\d{20}",
+ "SE": "\\d{20}",
+ "CH": "\\d{5}[\\dA-Z]{12}",
+ "TN": "\\d{20}",
+ "TR": "\\d{5}[\\dA-Z]{17}",
+ "AE": "\\d{3}\\d{16}",
+ "GB": "[A-Z]{4}\\d{14}",
+ "VG": "[\\dA-Z]{4}\\d{16}"
+ };
+
+ bbanpattern = bbancountrypatterns[countrycode];
+ // As new countries will start using IBAN in the
+ // future, we only check if the countrycode is known.
+ // This prevents false negatives, while almost all
+ // false positives introduced by this, will be caught
+ // by the checksum validation below anyway.
+ // Strict checking should return FALSE for unknown
+ // countries.
+ if (typeof bbanpattern !== "undefined") {
+ ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
+ if (!(ibanregexp.test(iban))) {
+ return false; // invalid country specific format
+ }
+ }
+
+ // now check the checksum, first convert to digits
+ ibancheck = iban.substring(4, iban.length) + iban.substring(0, 4);
+ for (i = 0; i < ibancheck.length; i++) {
+ charAt = ibancheck.charAt(i);
+ if (charAt !== "0") {
+ leadingZeroes = false;
+ }
+ if (!leadingZeroes) {
+ ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(charAt);
+ }
+ }
+
+ // calculate the result of: ibancheckdigits % 97
+ for (p = 0; p < ibancheckdigits.length; p++) {
+ cChar = ibancheckdigits.charAt(p);
+ cOperator = "" + cRest + "" + cChar;
+ cRest = cOperator % 97;
+ }
+ return cRest === 1;
+}, "Please specify a valid IBAN");
+
+$.validator.addMethod("integer", function(value, element) {
+ return this.optional(element) || /^-?\d+$/.test(value);
+}, "A positive or negative non-decimal number please");
+
+$.validator.addMethod("ipv4", function(value, element) {
+ return this.optional(element) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(value);
+}, "Please enter a valid IP v4 address.");
+
+$.validator.addMethod("ipv6", function(value, element) {
+ return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);
+}, "Please enter a valid IP v6 address.");
+
+$.validator.addMethod("lettersonly", function(value, element) {
+ return this.optional(element) || /^[a-z]+$/i.test(value);
+}, "Letters only please");
+
+$.validator.addMethod("letterswithbasicpunc", function(value, element) {
+ return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value);
+}, "Letters or punctuation only please");
+
+$.validator.addMethod("mobileNL", function(value, element) {
+ return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
+}, "Please specify a valid mobile number");
+
+/* For UK phone functions, do the following server side processing:
+ * Compare original input with this RegEx pattern:
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
+ */
+$.validator.addMethod("mobileUK", function(phone_number, element) {
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/);
+}, "Please specify a valid mobile number");
+
+/*
+ * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain
+ */
+$.validator.addMethod( "nieES", function( value ) {
+ "use strict";
+
+ value = value.toUpperCase();
+
+ // Basic format test
+ if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
+ return false;
+ }
+
+ // Test NIE
+ //T
+ if ( /^[T]{1}/.test( value ) ) {
+ return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );
+ }
+
+ //XYZ
+ if ( /^[XYZ]{1}/.test( value ) ) {
+ return (
+ value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt(
+ value.replace( "X", "0" )
+ .replace( "Y", "1" )
+ .replace( "Z", "2" )
+ .substring( 0, 8 ) % 23
+ )
+ );
+ }
+
+ return false;
+
+}, "Please specify a valid NIE number." );
+
+/*
+ * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
+ */
+$.validator.addMethod( "nifES", function( value ) {
+ "use strict";
+
+ value = value.toUpperCase();
+
+ // Basic format test
+ if ( !value.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)") ) {
+ return false;
+ }
+
+ // Test NIF
+ if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
+ return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
+ }
+ // Test specials NIF (starts with K, L or M)
+ if ( /^[KLM]{1}/.test( value ) ) {
+ return ( value[ 8 ] === String.fromCharCode( 64 ) );
+ }
+
+ return false;
+
+}, "Please specify a valid NIF number." );
+
+$.validator.addMethod("nowhitespace", function(value, element) {
+ return this.optional(element) || /^\S+$/i.test(value);
+}, "No white space please");
+
+/**
+* Return true if the field value matches the given format RegExp
+*
+* @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
+* @result true
+*
+* @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
+* @result false
+*
+* @name $.validator.methods.pattern
+* @type Boolean
+* @cat Plugins/Validate/Methods
+*/
+$.validator.addMethod("pattern", function(value, element, param) {
+ if (this.optional(element)) {
+ return true;
+ }
+ if (typeof param === "string") {
+ param = new RegExp("^(?:" + param + ")$");
+ }
+ return param.test(value);
+}, "Invalid format.");
+
+/**
+ * Dutch phone numbers have 10 digits (or 11 and start with +31).
+ */
+$.validator.addMethod("phoneNL", function(value, element) {
+ return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
+}, "Please specify a valid phone number.");
+
+/* For UK phone functions, do the following server side processing:
+ * Compare original input with this RegEx pattern:
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
+ */
+$.validator.addMethod("phoneUK", function(phone_number, element) {
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/);
+}, "Please specify a valid phone number");
+
+/**
+ * matches US phone number format
+ *
+ * where the area code may not start with 1 and the prefix may not start with 1
+ * allows '-' or ' ' as a separator and allows parens around area code
+ * some people may want to put a '1' in front of their number
+ *
+ * 1(212)-999-2345 or
+ * 212 999 2344 or
+ * 212-999-0983
+ *
+ * but not
+ * 111-123-5434
+ * and not
+ * 212 123 4567
+ */
+$.validator.addMethod("phoneUS", function(phone_number, element) {
+ phone_number = phone_number.replace(/\s+/g, "");
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/);
+}, "Please specify a valid phone number");
+
+/* For UK phone functions, do the following server side processing:
+ * Compare original input with this RegEx pattern:
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
+ */
+//Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
+$.validator.addMethod("phonesUK", function(phone_number, element) {
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/);
+}, "Please specify a valid uk phone number");
+
+/**
+ * Matches a valid Canadian Postal Code
+ *
+ * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
+ * @result true
+ *
+ * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
+ * @result false
+ *
+ * @name jQuery.validator.methods.postalCodeCA
+ * @type Boolean
+ * @cat Plugins/Validate/Methods
+ */
+$.validator.addMethod( "postalCodeCA", function( value, element ) {
+ return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test( value );
+}, "Please specify a valid postal code" );
+
+/*
+* Valida CEPs do brasileiros:
+*
+* Formatos aceitos:
+* 99999-999
+* 99.999-999
+* 99999999
+*/
+$.validator.addMethod("postalcodeBR", function(cep_value, element) {
+ return this.optional(element) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
+}, "Informe um CEP válido.");
+
+/* Matches Italian postcode (CAP) */
+$.validator.addMethod("postalcodeIT", function(value, element) {
+ return this.optional(element) || /^\d{5}$/.test(value);
+}, "Please specify a valid postal code");
+
+$.validator.addMethod("postalcodeNL", function(value, element) {
+ return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
+}, "Please specify a valid postal code");
+
+// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
+$.validator.addMethod("postcodeUK", function(value, element) {
+ return this.optional(element) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(value);
+}, "Please specify a valid UK postcode");
+
+/*
+ * Lets you say "at least X inputs that match selector Y must be filled."
+ *
+ * The end result is that neither of these inputs:
+ *
+ * <input class="productinfo" name="partnumber">
+ * <input class="productinfo" name="description">
+ *
+ * ...will validate unless at least one of them is filled.
+ *
+ * partnumber: {require_from_group: [1,".productinfo"]},
+ * description: {require_from_group: [1,".productinfo"]}
+ *
+ * options[0]: number of fields that must be filled in the group
+ * options[1]: CSS selector that defines the group of conditionally required fields
+ */
+$.validator.addMethod("require_from_group", function(value, element, options) {
+ var $fields = $(options[1], element.form),
+ $fieldsFirst = $fields.eq(0),
+ validator = $fieldsFirst.data("valid_req_grp") ? $fieldsFirst.data("valid_req_grp") : $.extend({}, this),
+ isValid = $fields.filter(function() {
+ return validator.elementValue(this);
+ }).length >= options[0];
+
+ // Store the cloned validator for future validation
+ $fieldsFirst.data("valid_req_grp", validator);
+
+ // If element isn't being validated, run each require_from_group field's validation rules
+ if (!$(element).data("being_validated")) {
+ $fields.data("being_validated", true);
+ $fields.each(function() {
+ validator.element(this);
+ });
+ $fields.data("being_validated", false);
+ }
+ return isValid;
+}, $.validator.format("Please fill at least {0} of these fields."));
+
+/*
+ * Lets you say "either at least X inputs that match selector Y must be filled,
+ * OR they must all be skipped (left blank)."
+ *
+ * The end result, is that none of these inputs:
+ *
+ * <input class="productinfo" name="partnumber">
+ * <input class="productinfo" name="description">
+ * <input class="productinfo" name="color">
+ *
+ * ...will validate unless either at least two of them are filled,
+ * OR none of them are.
+ *
+ * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
+ * description: {skip_or_fill_minimum: [2,".productinfo"]},
+ * color: {skip_or_fill_minimum: [2,".productinfo"]}
+ *
+ * options[0]: number of fields that must be filled in the group
+ * options[1]: CSS selector that defines the group of conditionally required fields
+ *
+ */
+$.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
+ var $fields = $(options[1], element.form),
+ $fieldsFirst = $fields.eq(0),
+ validator = $fieldsFirst.data("valid_skip") ? $fieldsFirst.data("valid_skip") : $.extend({}, this),
+ numberFilled = $fields.filter(function() {
+ return validator.elementValue(this);
+ }).length,
+ isValid = numberFilled === 0 || numberFilled >= options[0];
+
+ // Store the cloned validator for future validation
+ $fieldsFirst.data("valid_skip", validator);
+
+ // If element isn't being validated, run each skip_or_fill_minimum field's validation rules
+ if (!$(element).data("being_validated")) {
+ $fields.data("being_validated", true);
+ $fields.each(function() {
+ validator.element(this);
+ });
+ $fields.data("being_validated", false);
+ }
+ return isValid;
+}, $.validator.format("Please either skip these fields or fill at least {0} of them."));
+
+/* Validates US States and/or Territories by @jdforsythe
+ * Can be case insensitive or require capitalization - default is case insensitive
+ * Can include US Territories or not - default does not
+ * Can include US Military postal abbreviations (AA, AE, AP) - default does not
+ *
+ * Note: "States" always includes DC (District of Colombia)
+ *
+ * Usage examples:
+ *
+ * This is the default - case insensitive, no territories, no military zones
+ * stateInput: {
+ * caseSensitive: false,
+ * includeTerritories: false,
+ * includeMilitary: false
+ * }
+ *
+ * Only allow capital letters, no territories, no military zones
+ * stateInput: {
+ * caseSensitive: false
+ * }
+ *
+ * Case insensitive, include territories but not military zones
+ * stateInput: {
+ * includeTerritories: true
+ * }
+ *
+ * Only allow capital letters, include territories and military zones
+ * stateInput: {
+ * caseSensitive: true,
+ * includeTerritories: true,
+ * includeMilitary: true
+ * }
+ *
+ *
+ *
+ */
+
+jQuery.validator.addMethod("stateUS", function(value, element, options) {
+ var isDefault = typeof options === "undefined",
+ caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
+ includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
+ includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
+ regex;
+
+ if (!includeTerritories && !includeMilitary) {
+ regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
+ } else if (includeTerritories && includeMilitary) {
+ regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
+ } else if (includeTerritories) {
+ regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
+ } else {
+ regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
+ }
+
+ regex = caseSensitive ? new RegExp(regex) : new RegExp(regex, "i");
+ return this.optional(element) || regex.test(value);
+},
+"Please specify a valid state");
+
+// TODO check if value starts with <, otherwise don't try stripping anything
+$.validator.addMethod("strippedminlength", function(value, element, param) {
+ return $(value).text().length >= param;
+}, $.validator.format("Please enter at least {0} characters"));
+
+$.validator.addMethod("time", function(value, element) {
+ return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(value);
+}, "Please enter a valid time, between 00:00 and 23:59");
+
+$.validator.addMethod("time12h", function(value, element) {
+ return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
+}, "Please enter a valid time in 12-hour am/pm format");
+
+// same as url, but TLD is optional
+$.validator.addMethod("url2", function(value, element) {
+ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+}, $.validator.messages.url);
+
+/**
+ * Return true, if the value is a valid vehicle identification number (VIN).
+ *
+ * Works with all kind of text inputs.
+ *
+ * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
+ * @desc Declares a required input element whose value must be a valid vehicle identification number.
+ *
+ * @name $.validator.methods.vinUS
+ * @type Boolean
+ * @cat Plugins/Validate/Methods
+ */
+$.validator.addMethod("vinUS", function(v) {
+ if (v.length !== 17) {
+ return false;
+ }
+
+ var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ],
+ VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
+ FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
+ rs = 0,
+ i, n, d, f, cd, cdv;
+
+ for (i = 0; i < 17; i++) {
+ f = FL[i];
+ d = v.slice(i, i + 1);
+ if (i === 8) {
+ cdv = d;
+ }
+ if (!isNaN(d)) {
+ d *= f;
+ } else {
+ for (n = 0; n < LL.length; n++) {
+ if (d.toUpperCase() === LL[n]) {
+ d = VL[n];
+ d *= f;
+ if (isNaN(cdv) && n === 8) {
+ cdv = LL[n];
+ }
+ break;
+ }
+ }
+ }
+ rs += d;
+ }
+ cd = rs % 11;
+ if (cd === 10) {
+ cd = "X";
+ }
+ if (cd === cdv) {
+ return true;
+ }
+ return false;
+}, "The specified vehicle identification number (VIN) is invalid.");
+
+$.validator.addMethod("zipcodeUS", function(value, element) {
+ return this.optional(element) || /^\d{5}(-\d{4})?$/.test(value);
+}, "The specified US ZIP Code is invalid");
+
+$.validator.addMethod("ziprange", function(value, element) {
+ return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value);
+}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx");
+
+})); \ No newline at end of file
diff --git a/js/jquery/jquery.validate.js b/js/jquery/jquery.validate.js
new file mode 100644
index 0000000000..2f18b6c21a
--- /dev/null
+++ b/js/jquery/jquery.validate.js
@@ -0,0 +1,1365 @@
+/*!
+ * jQuery Validation Plugin v1.13.1
+ *
+ * http://jqueryvalidation.org/
+ *
+ * Copyright (c) 2014 Jörn Zaefferer
+ * Released under the MIT license
+ */
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+ define( ["jquery"], factory );
+ } else {
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+$.extend($.fn, {
+ // http://jqueryvalidation.org/validate/
+ validate: function( options ) {
+
+ // if nothing is selected, return nothing; can't chain anyway
+ if ( !this.length ) {
+ if ( options && options.debug && window.console ) {
+ console.warn( "Nothing selected, can't validate, returning nothing." );
+ }
+ return;
+ }
+
+ // check if a validator for this form was already created
+ var validator = $.data( this[ 0 ], "validator" );
+ if ( validator ) {
+ return validator;
+ }
+
+ // Add novalidate tag if HTML5.
+ this.attr( "novalidate", "novalidate" );
+
+ validator = new $.validator( options, this[ 0 ] );
+ $.data( this[ 0 ], "validator", validator );
+
+ if ( validator.settings.onsubmit ) {
+
+ this.validateDelegate( ":submit", "click", function( event ) {
+ if ( validator.settings.submitHandler ) {
+ validator.submitButton = event.target;
+ }
+ // allow suppressing validation by adding a cancel class to the submit button
+ if ( $( event.target ).hasClass( "cancel" ) ) {
+ validator.cancelSubmit = true;
+ }
+
+ // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
+ if ( $( event.target ).attr( "formnovalidate" ) !== undefined ) {
+ validator.cancelSubmit = true;
+ }
+ });
+
+ // validate the form on submit
+ this.submit( function( event ) {
+ if ( validator.settings.debug ) {
+ // prevent form submit to be able to see console output
+ event.preventDefault();
+ }
+ function handle() {
+ var hidden, result;
+ if ( validator.settings.submitHandler ) {
+ if ( validator.submitButton ) {
+ // insert a hidden input as a replacement for the missing submit button
+ hidden = $( "<input type='hidden'/>" )
+ .attr( "name", validator.submitButton.name )
+ .val( $( validator.submitButton ).val() )
+ .appendTo( validator.currentForm );
+ }
+ result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
+ if ( validator.submitButton ) {
+ // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
+ hidden.remove();
+ }
+ if ( result !== undefined ) {
+ return result;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // prevent submit for invalid forms or custom submit handlers
+ if ( validator.cancelSubmit ) {
+ validator.cancelSubmit = false;
+ return handle();
+ }
+ if ( validator.form() ) {
+ if ( validator.pendingRequest ) {
+ validator.formSubmitted = true;
+ return false;
+ }
+ return handle();
+ } else {
+ validator.focusInvalid();
+ return false;
+ }
+ });
+ }
+
+ return validator;
+ },
+ // http://jqueryvalidation.org/valid/
+ valid: function() {
+ var valid, validator;
+
+ if ( $( this[ 0 ] ).is( "form" ) ) {
+ valid = this.validate().form();
+ } else {
+ valid = true;
+ validator = $( this[ 0 ].form ).validate();
+ this.each( function() {
+ valid = validator.element( this ) && valid;
+ });
+ }
+ return valid;
+ },
+ // attributes: space separated list of attributes to retrieve and remove
+ removeAttrs: function( attributes ) {
+ var result = {},
+ $element = this;
+ $.each( attributes.split( /\s/ ), function( index, value ) {
+ result[ value ] = $element.attr( value );
+ $element.removeAttr( value );
+ });
+ return result;
+ },
+ // http://jqueryvalidation.org/rules/
+ rules: function( command, argument ) {
+ var element = this[ 0 ],
+ settings, staticRules, existingRules, data, param, filtered;
+
+ if ( command ) {
+ settings = $.data( element.form, "validator" ).settings;
+ staticRules = settings.rules;
+ existingRules = $.validator.staticRules( element );
+ switch ( command ) {
+ case "add":
+ $.extend( existingRules, $.validator.normalizeRule( argument ) );
+ // remove messages from rules, but allow them to be set separately
+ delete existingRules.messages;
+ staticRules[ element.name ] = existingRules;
+ if ( argument.messages ) {
+ settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
+ }
+ break;
+ case "remove":
+ if ( !argument ) {
+ delete staticRules[ element.name ];
+ return existingRules;
+ }
+ filtered = {};
+ $.each( argument.split( /\s/ ), function( index, method ) {
+ filtered[ method ] = existingRules[ method ];
+ delete existingRules[ method ];
+ if ( method === "required" ) {
+ $( element ).removeAttr( "aria-required" );
+ }
+ });
+ return filtered;
+ }
+ }
+
+ data = $.validator.normalizeRules(
+ $.extend(
+ {},
+ $.validator.classRules( element ),
+ $.validator.attributeRules( element ),
+ $.validator.dataRules( element ),
+ $.validator.staticRules( element )
+ ), element );
+
+ // make sure required is at front
+ if ( data.required ) {
+ param = data.required;
+ delete data.required;
+ data = $.extend( { required: param }, data );
+ $( element ).attr( "aria-required", "true" );
+ }
+
+ // make sure remote is at back
+ if ( data.remote ) {
+ param = data.remote;
+ delete data.remote;
+ data = $.extend( data, { remote: param });
+ }
+
+ return data;
+ }
+});
+
+// Custom selectors
+$.extend( $.expr[ ":" ], {
+ // http://jqueryvalidation.org/blank-selector/
+ blank: function( a ) {
+ return !$.trim( "" + $( a ).val() );
+ },
+ // http://jqueryvalidation.org/filled-selector/
+ filled: function( a ) {
+ return !!$.trim( "" + $( a ).val() );
+ },
+ // http://jqueryvalidation.org/unchecked-selector/
+ unchecked: function( a ) {
+ return !$( a ).prop( "checked" );
+ }
+});
+
+// constructor for validator
+$.validator = function( options, form ) {
+ this.settings = $.extend( true, {}, $.validator.defaults, options );
+ this.currentForm = form;
+ this.init();
+};
+
+// http://jqueryvalidation.org/jQuery.validator.format/
+$.validator.format = function( source, params ) {
+ if ( arguments.length === 1 ) {
+ return function() {
+ var args = $.makeArray( arguments );
+ args.unshift( source );
+ return $.validator.format.apply( this, args );
+ };
+ }
+ if ( arguments.length > 2 && params.constructor !== Array ) {
+ params = $.makeArray( arguments ).slice( 1 );
+ }
+ if ( params.constructor !== Array ) {
+ params = [ params ];
+ }
+ $.each( params, function( i, n ) {
+ source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
+ return n;
+ });
+ });
+ return source;
+};
+
+$.extend( $.validator, {
+
+ defaults: {
+ messages: {},
+ groups: {},
+ rules: {},
+ errorClass: "error",
+ validClass: "valid",
+ errorElement: "label",
+ focusCleanup: false,
+ focusInvalid: true,
+ errorContainer: $( [] ),
+ errorLabelContainer: $( [] ),
+ onsubmit: true,
+ ignore: ":hidden",
+ ignoreTitle: false,
+ onfocusin: function( element ) {
+ this.lastActive = element;
+
+ // Hide error label and remove error class on focus if enabled
+ if ( this.settings.focusCleanup ) {
+ if ( this.settings.unhighlight ) {
+ this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
+ }
+ this.hideThese( this.errorsFor( element ) );
+ }
+ },
+ onfocusout: function( element ) {
+ if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
+ this.element( element );
+ }
+ },
+ onkeyup: function( element, event ) {
+ if ( event.which === 9 && this.elementValue( element ) === "" ) {
+ return;
+ } else if ( element.name in this.submitted || element === this.lastElement ) {
+ this.element( element );
+ }
+ },
+ onclick: function( element ) {
+ // click on selects, radiobuttons and checkboxes
+ if ( element.name in this.submitted ) {
+ this.element( element );
+
+ // or option elements, check parent select in that case
+ } else if ( element.parentNode.name in this.submitted ) {
+ this.element( element.parentNode );
+ }
+ },
+ highlight: function( element, errorClass, validClass ) {
+ if ( element.type === "radio" ) {
+ this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
+ } else {
+ $( element ).addClass( errorClass ).removeClass( validClass );
+ }
+ },
+ unhighlight: function( element, errorClass, validClass ) {
+ if ( element.type === "radio" ) {
+ this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
+ } else {
+ $( element ).removeClass( errorClass ).addClass( validClass );
+ }
+ }
+ },
+
+ // http://jqueryvalidation.org/jQuery.validator.setDefaults/
+ setDefaults: function( settings ) {
+ $.extend( $.validator.defaults, settings );
+ },
+
+ messages: {
+ required: "This field is required.",
+ remote: "Please fix this field.",
+ email: "Please enter a valid email address.",
+ url: "Please enter a valid URL.",
+ date: "Please enter a valid date.",
+ dateISO: "Please enter a valid date ( ISO ).",
+ number: "Please enter a valid number.",
+ digits: "Please enter only digits.",
+ creditcard: "Please enter a valid credit card number.",
+ equalTo: "Please enter the same value again.",
+ maxlength: $.validator.format( "Please enter no more than {0} characters." ),
+ minlength: $.validator.format( "Please enter at least {0} characters." ),
+ rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
+ range: $.validator.format( "Please enter a value between {0} and {1}." ),
+ max: $.validator.format( "Please enter a value less than or equal to {0}." ),
+ min: $.validator.format( "Please enter a value greater than or equal to {0}." )
+ },
+
+ autoCreateRanges: false,
+
+ prototype: {
+
+ init: function() {
+ this.labelContainer = $( this.settings.errorLabelContainer );
+ this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
+ this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
+ this.submitted = {};
+ this.valueCache = {};
+ this.pendingRequest = 0;
+ this.pending = {};
+ this.invalid = {};
+ this.reset();
+
+ var groups = ( this.groups = {} ),
+ rules;
+ $.each( this.settings.groups, function( key, value ) {
+ if ( typeof value === "string" ) {
+ value = value.split( /\s/ );
+ }
+ $.each( value, function( index, name ) {
+ groups[ name ] = key;
+ });
+ });
+ rules = this.settings.rules;
+ $.each( rules, function( key, value ) {
+ rules[ key ] = $.validator.normalizeRule( value );
+ });
+
+ function delegate( event ) {
+ var validator = $.data( this[ 0 ].form, "validator" ),
+ eventType = "on" + event.type.replace( /^validate/, "" ),
+ settings = validator.settings;
+ if ( settings[ eventType ] && !this.is( settings.ignore ) ) {
+ settings[ eventType ].call( validator, this[ 0 ], event );
+ }
+ }
+ $( this.currentForm )
+ .validateDelegate( ":text, [type='password'], [type='file'], select, textarea, " +
+ "[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
+ "[type='email'], [type='datetime'], [type='date'], [type='month'], " +
+ "[type='week'], [type='time'], [type='datetime-local'], " +
+ "[type='range'], [type='color'], [type='radio'], [type='checkbox']",
+ "focusin focusout keyup", delegate)
+ // Support: Chrome, oldIE
+ // "select" is provided as event.target when clicking a option
+ .validateDelegate("select, option, [type='radio'], [type='checkbox']", "click", delegate);
+
+ if ( this.settings.invalidHandler ) {
+ $( this.currentForm ).bind( "invalid-form.validate", this.settings.invalidHandler );
+ }
+
+ // Add aria-required to any Static/Data/Class required fields before first validation
+ // Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html
+ $( this.currentForm ).find( "[required], [data-rule-required], .required" ).attr( "aria-required", "true" );
+ },
+
+ // http://jqueryvalidation.org/Validator.form/
+ form: function() {
+ this.checkForm();
+ $.extend( this.submitted, this.errorMap );
+ this.invalid = $.extend({}, this.errorMap );
+ if ( !this.valid() ) {
+ $( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
+ }
+ this.showErrors();
+ return this.valid();
+ },
+
+ checkForm: function() {
+ this.prepareForm();
+ for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
+ this.check( elements[ i ] );
+ }
+ return this.valid();
+ },
+
+ // http://jqueryvalidation.org/Validator.element/
+ element: function( element ) {
+ var cleanElement = this.clean( element ),
+ checkElement = this.validationTargetFor( cleanElement ),
+ result = true;
+
+ this.lastElement = checkElement;
+
+ if ( checkElement === undefined ) {
+ delete this.invalid[ cleanElement.name ];
+ } else {
+ this.prepareElement( checkElement );
+ this.currentElements = $( checkElement );
+
+ result = this.check( checkElement ) !== false;
+ if ( result ) {
+ delete this.invalid[ checkElement.name ];
+ } else {
+ this.invalid[ checkElement.name ] = true;
+ }
+ }
+ // Add aria-invalid status for screen readers
+ $( element ).attr( "aria-invalid", !result );
+
+ if ( !this.numberOfInvalids() ) {
+ // Hide error containers on last error
+ this.toHide = this.toHide.add( this.containers );
+ }
+ this.showErrors();
+ return result;
+ },
+
+ // http://jqueryvalidation.org/Validator.showErrors/
+ showErrors: function( errors ) {
+ if ( errors ) {
+ // add items to error list and map
+ $.extend( this.errorMap, errors );
+ this.errorList = [];
+ for ( var name in errors ) {
+ this.errorList.push({
+ message: errors[ name ],
+ element: this.findByName( name )[ 0 ]
+ });
+ }
+ // remove items from success list
+ this.successList = $.grep( this.successList, function( element ) {
+ return !( element.name in errors );
+ });
+ }
+ if ( this.settings.showErrors ) {
+ this.settings.showErrors.call( this, this.errorMap, this.errorList );
+ } else {
+ this.defaultShowErrors();
+ }
+ },
+
+ // http://jqueryvalidation.org/Validator.resetForm/
+ resetForm: function() {
+ if ( $.fn.resetForm ) {
+ $( this.currentForm ).resetForm();
+ }
+ this.submitted = {};
+ this.lastElement = null;
+ this.prepareForm();
+ this.hideErrors();
+ this.elements()
+ .removeClass( this.settings.errorClass )
+ .removeData( "previousValue" )
+ .removeAttr( "aria-invalid" );
+ },
+
+ numberOfInvalids: function() {
+ return this.objectLength( this.invalid );
+ },
+
+ objectLength: function( obj ) {
+ /* jshint unused: false */
+ var count = 0,
+ i;
+ for ( i in obj ) {
+ count++;
+ }
+ return count;
+ },
+
+ hideErrors: function() {
+ this.hideThese( this.toHide );
+ },
+
+ hideThese: function( errors ) {
+ errors.not( this.containers ).text( "" );
+ this.addWrapper( errors ).hide();
+ },
+
+ valid: function() {
+ return this.size() === 0;
+ },
+
+ size: function() {
+ return this.errorList.length;
+ },
+
+ focusInvalid: function() {
+ if ( this.settings.focusInvalid ) {
+ try {
+ $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [])
+ .filter( ":visible" )
+ .focus()
+ // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
+ .trigger( "focusin" );
+ } catch ( e ) {
+ // ignore IE throwing errors when focusing hidden elements
+ }
+ }
+ },
+
+ findLastActive: function() {
+ var lastActive = this.lastActive;
+ return lastActive && $.grep( this.errorList, function( n ) {
+ return n.element.name === lastActive.name;
+ }).length === 1 && lastActive;
+ },
+
+ elements: function() {
+ var validator = this,
+ rulesCache = {};
+
+ // select all valid inputs inside the form (no submit or reset buttons)
+ return $( this.currentForm )
+ .find( "input, select, textarea" )
+ .not( ":submit, :reset, :image, [disabled], [readonly]" )
+ .not( this.settings.ignore )
+ .filter( function() {
+ if ( !this.name && validator.settings.debug && window.console ) {
+ console.error( "%o has no name assigned", this );
+ }
+
+ // select only the first element for each name, and only those with rules specified
+ if ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
+ return false;
+ }
+
+ rulesCache[ this.name ] = true;
+ return true;
+ });
+ },
+
+ clean: function( selector ) {
+ return $( selector )[ 0 ];
+ },
+
+ errors: function() {
+ var errorClass = this.settings.errorClass.split( " " ).join( "." );
+ return $( this.settings.errorElement + "." + errorClass, this.errorContext );
+ },
+
+ reset: function() {
+ this.successList = [];
+ this.errorList = [];
+ this.errorMap = {};
+ this.toShow = $( [] );
+ this.toHide = $( [] );
+ this.currentElements = $( [] );
+ },
+
+ prepareForm: function() {
+ this.reset();
+ this.toHide = this.errors().add( this.containers );
+ },
+
+ prepareElement: function( element ) {
+ this.reset();
+ this.toHide = this.errorsFor( element );
+ },
+
+ elementValue: function( element ) {
+ var val,
+ $element = $( element ),
+ type = element.type;
+
+ if ( type === "radio" || type === "checkbox" ) {
+ return $( "input[name='" + element.name + "']:checked" ).val();
+ } else if ( type === "number" && typeof element.validity !== "undefined" ) {
+ return element.validity.badInput ? false : $element.val();
+ }
+
+ val = $element.val();
+ if ( typeof val === "string" ) {
+ return val.replace(/\r/g, "" );
+ }
+ return val;
+ },
+
+ check: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+
+ var rules = $( element ).rules(),
+ rulesCount = $.map( rules, function( n, i ) {
+ return i;
+ }).length,
+ dependencyMismatch = false,
+ val = this.elementValue( element ),
+ result, method, rule;
+
+ for ( method in rules ) {
+ rule = { method: method, parameters: rules[ method ] };
+ try {
+
+ result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
+
+ // if a method indicates that the field is optional and therefore valid,
+ // don't mark it as valid when there are no other rules
+ if ( result === "dependency-mismatch" && rulesCount === 1 ) {
+ dependencyMismatch = true;
+ continue;
+ }
+ dependencyMismatch = false;
+
+ if ( result === "pending" ) {
+ this.toHide = this.toHide.not( this.errorsFor( element ) );
+ return;
+ }
+
+ if ( !result ) {
+ this.formatAndAdd( element, rule );
+ return false;
+ }
+ } catch ( e ) {
+ if ( this.settings.debug && window.console ) {
+ console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
+ }
+ throw e;
+ }
+ }
+ if ( dependencyMismatch ) {
+ return;
+ }
+ if ( this.objectLength( rules ) ) {
+ this.successList.push( element );
+ }
+ return true;
+ },
+
+ // return the custom message for the given element and validation method
+ // specified in the element's HTML5 data attribute
+ // return the generic message if present and no method specific message is present
+ customDataMessage: function( element, method ) {
+ return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
+ method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
+ },
+
+ // return the custom message for the given element name and validation method
+ customMessage: function( name, method ) {
+ var m = this.settings.messages[ name ];
+ return m && ( m.constructor === String ? m : m[ method ]);
+ },
+
+ // return the first defined argument, allowing empty strings
+ findDefined: function() {
+ for ( var i = 0; i < arguments.length; i++) {
+ if ( arguments[ i ] !== undefined ) {
+ return arguments[ i ];
+ }
+ }
+ return undefined;
+ },
+
+ defaultMessage: function( element, method ) {
+ return this.findDefined(
+ this.customMessage( element.name, method ),
+ this.customDataMessage( element, method ),
+ // title is never undefined, so handle empty string as undefined
+ !this.settings.ignoreTitle && element.title || undefined,
+ $.validator.messages[ method ],
+ "<strong>Warning: No message defined for " + element.name + "</strong>"
+ );
+ },
+
+ formatAndAdd: function( element, rule ) {
+ var message = this.defaultMessage( element, rule.method ),
+ theregex = /\$?\{(\d+)\}/g;
+ if ( typeof message === "function" ) {
+ message = message.call( this, rule.parameters, element );
+ } else if ( theregex.test( message ) ) {
+ message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
+ }
+ this.errorList.push({
+ message: message,
+ element: element,
+ method: rule.method
+ });
+
+ this.errorMap[ element.name ] = message;
+ this.submitted[ element.name ] = message;
+ },
+
+ addWrapper: function( toToggle ) {
+ if ( this.settings.wrapper ) {
+ toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
+ }
+ return toToggle;
+ },
+
+ defaultShowErrors: function() {
+ var i, elements, error;
+ for ( i = 0; this.errorList[ i ]; i++ ) {
+ error = this.errorList[ i ];
+ if ( this.settings.highlight ) {
+ this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
+ }
+ this.showLabel( error.element, error.message );
+ }
+ if ( this.errorList.length ) {
+ this.toShow = this.toShow.add( this.containers );
+ }
+ if ( this.settings.success ) {
+ for ( i = 0; this.successList[ i ]; i++ ) {
+ this.showLabel( this.successList[ i ] );
+ }
+ }
+ if ( this.settings.unhighlight ) {
+ for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
+ this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
+ }
+ }
+ this.toHide = this.toHide.not( this.toShow );
+ this.hideErrors();
+ this.addWrapper( this.toShow ).show();
+ },
+
+ validElements: function() {
+ return this.currentElements.not( this.invalidElements() );
+ },
+
+ invalidElements: function() {
+ return $( this.errorList ).map(function() {
+ return this.element;
+ });
+ },
+
+ showLabel: function( element, message ) {
+ var place, group, errorID,
+ error = this.errorsFor( element ),
+ elementID = this.idOrName( element ),
+ describedBy = $( element ).attr( "aria-describedby" );
+ if ( error.length ) {
+ // refresh error/success class
+ error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
+ // replace message on existing label
+ error.html( message );
+ } else {
+ // create error element
+ error = $( "<" + this.settings.errorElement + ">" )
+ .attr( "id", elementID + "-error" )
+ .addClass( this.settings.errorClass )
+ .html( message || "" );
+
+ // Maintain reference to the element to be placed into the DOM
+ place = error;
+ if ( this.settings.wrapper ) {
+ // make sure the element is visible, even in IE
+ // actually showing the wrapped element is handled elsewhere
+ place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
+ }
+ if ( this.labelContainer.length ) {
+ this.labelContainer.append( place );
+ } else if ( this.settings.errorPlacement ) {
+ this.settings.errorPlacement( place, $( element ) );
+ } else {
+ place.insertAfter( element );
+ }
+
+ // Link error back to the element
+ if ( error.is( "label" ) ) {
+ // If the error is a label, then associate using 'for'
+ error.attr( "for", elementID );
+ } else if ( error.parents( "label[for='" + elementID + "']" ).length === 0 ) {
+ // If the element is not a child of an associated label, then it's necessary
+ // to explicitly apply aria-describedby
+
+ errorID = error.attr( "id" ).replace( /(:|\.|\[|\])/g, "\\$1");
+ // Respect existing non-error aria-describedby
+ if ( !describedBy ) {
+ describedBy = errorID;
+ } else if ( !describedBy.match( new RegExp( "\\b" + errorID + "\\b" ) ) ) {
+ // Add to end of list if not already present
+ describedBy += " " + errorID;
+ }
+ $( element ).attr( "aria-describedby", describedBy );
+
+ // If this element is grouped, then assign to all elements in the same group
+ group = this.groups[ element.name ];
+ if ( group ) {
+ $.each( this.groups, function( name, testgroup ) {
+ if ( testgroup === group ) {
+ $( "[name='" + name + "']", this.currentForm )
+ .attr( "aria-describedby", error.attr( "id" ) );
+ }
+ });
+ }
+ }
+ }
+ if ( !message && this.settings.success ) {
+ error.text( "" );
+ if ( typeof this.settings.success === "string" ) {
+ error.addClass( this.settings.success );
+ } else {
+ this.settings.success( error, element );
+ }
+ }
+ this.toShow = this.toShow.add( error );
+ },
+
+ errorsFor: function( element ) {
+ var name = this.idOrName( element ),
+ describer = $( element ).attr( "aria-describedby" ),
+ selector = "label[for='" + name + "'], label[for='" + name + "'] *";
+
+ // aria-describedby should directly reference the error element
+ if ( describer ) {
+ selector = selector + ", #" + describer.replace( /\s+/g, ", #" );
+ }
+ return this
+ .errors()
+ .filter( selector );
+ },
+
+ idOrName: function( element ) {
+ return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
+ },
+
+ validationTargetFor: function( element ) {
+
+ // If radio/checkbox, validate first element in group instead
+ if ( this.checkable( element ) ) {
+ element = this.findByName( element.name );
+ }
+
+ // Always apply ignore filter
+ return $( element ).not( this.settings.ignore )[ 0 ];
+ },
+
+ checkable: function( element ) {
+ return ( /radio|checkbox/i ).test( element.type );
+ },
+
+ findByName: function( name ) {
+ return $( this.currentForm ).find( "[name='" + name + "']" );
+ },
+
+ getLength: function( value, element ) {
+ switch ( element.nodeName.toLowerCase() ) {
+ case "select":
+ return $( "option:selected", element ).length;
+ case "input":
+ if ( this.checkable( element ) ) {
+ return this.findByName( element.name ).filter( ":checked" ).length;
+ }
+ }
+ return value.length;
+ },
+
+ depend: function( param, element ) {
+ return this.dependTypes[typeof param] ? this.dependTypes[typeof param]( param, element ) : true;
+ },
+
+ dependTypes: {
+ "boolean": function( param ) {
+ return param;
+ },
+ "string": function( param, element ) {
+ return !!$( param, element.form ).length;
+ },
+ "function": function( param, element ) {
+ return param( element );
+ }
+ },
+
+ optional: function( element ) {
+ var val = this.elementValue( element );
+ return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
+ },
+
+ startRequest: function( element ) {
+ if ( !this.pending[ element.name ] ) {
+ this.pendingRequest++;
+ this.pending[ element.name ] = true;
+ }
+ },
+
+ stopRequest: function( element, valid ) {
+ this.pendingRequest--;
+ // sometimes synchronization fails, make sure pendingRequest is never < 0
+ if ( this.pendingRequest < 0 ) {
+ this.pendingRequest = 0;
+ }
+ delete this.pending[ element.name ];
+ if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
+ $( this.currentForm ).submit();
+ this.formSubmitted = false;
+ } else if (!valid && this.pendingRequest === 0 && this.formSubmitted ) {
+ $( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
+ this.formSubmitted = false;
+ }
+ },
+
+ previousValue: function( element ) {
+ return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
+ old: null,
+ valid: true,
+ message: this.defaultMessage( element, "remote" )
+ });
+ }
+
+ },
+
+ classRuleSettings: {
+ required: { required: true },
+ email: { email: true },
+ url: { url: true },
+ date: { date: true },
+ dateISO: { dateISO: true },
+ number: { number: true },
+ digits: { digits: true },
+ creditcard: { creditcard: true }
+ },
+
+ addClassRules: function( className, rules ) {
+ if ( className.constructor === String ) {
+ this.classRuleSettings[ className ] = rules;
+ } else {
+ $.extend( this.classRuleSettings, className );
+ }
+ },
+
+ classRules: function( element ) {
+ var rules = {},
+ classes = $( element ).attr( "class" );
+
+ if ( classes ) {
+ $.each( classes.split( " " ), function() {
+ if ( this in $.validator.classRuleSettings ) {
+ $.extend( rules, $.validator.classRuleSettings[ this ]);
+ }
+ });
+ }
+ return rules;
+ },
+
+ attributeRules: function( element ) {
+ var rules = {},
+ $element = $( element ),
+ type = element.getAttribute( "type" ),
+ method, value;
+
+ for ( method in $.validator.methods ) {
+
+ // support for <input required> in both html5 and older browsers
+ if ( method === "required" ) {
+ value = element.getAttribute( method );
+ // Some browsers return an empty string for the required attribute
+ // and non-HTML5 browsers might have required="" markup
+ if ( value === "" ) {
+ value = true;
+ }
+ // force non-HTML5 browsers to return bool
+ value = !!value;
+ } else {
+ value = $element.attr( method );
+ }
+
+ // convert the value to a number for number inputs, and for text for backwards compability
+ // allows type="date" and others to be compared as strings
+ if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
+ value = Number( value );
+ }
+
+ if ( value || value === 0 ) {
+ rules[ method ] = value;
+ } else if ( type === method && type !== "range" ) {
+ // exception: the jquery validate 'range' method
+ // does not test for the html5 'range' type
+ rules[ method ] = true;
+ }
+ }
+
+ // maxlength may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
+ if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
+ delete rules.maxlength;
+ }
+
+ return rules;
+ },
+
+ dataRules: function( element ) {
+ var method, value,
+ rules = {}, $element = $( element );
+ for ( method in $.validator.methods ) {
+ value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
+ if ( value !== undefined ) {
+ rules[ method ] = value;
+ }
+ }
+ return rules;
+ },
+
+ staticRules: function( element ) {
+ var rules = {},
+ validator = $.data( element.form, "validator" );
+
+ if ( validator.settings.rules ) {
+ rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
+ }
+ return rules;
+ },
+
+ normalizeRules: function( rules, element ) {
+ // handle dependency check
+ $.each( rules, function( prop, val ) {
+ // ignore rule when param is explicitly false, eg. required:false
+ if ( val === false ) {
+ delete rules[ prop ];
+ return;
+ }
+ if ( val.param || val.depends ) {
+ var keepRule = true;
+ switch ( typeof val.depends ) {
+ case "string":
+ keepRule = !!$( val.depends, element.form ).length;
+ break;
+ case "function":
+ keepRule = val.depends.call( element, element );
+ break;
+ }
+ if ( keepRule ) {
+ rules[ prop ] = val.param !== undefined ? val.param : true;
+ } else {
+ delete rules[ prop ];
+ }
+ }
+ });
+
+ // evaluate parameters
+ $.each( rules, function( rule, parameter ) {
+ rules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;
+ });
+
+ // clean number parameters
+ $.each([ "minlength", "maxlength" ], function() {
+ if ( rules[ this ] ) {
+ rules[ this ] = Number( rules[ this ] );
+ }
+ });
+ $.each([ "rangelength", "range" ], function() {
+ var parts;
+ if ( rules[ this ] ) {
+ if ( $.isArray( rules[ this ] ) ) {
+ rules[ this ] = [ Number( rules[ this ][ 0 ]), Number( rules[ this ][ 1 ] ) ];
+ } else if ( typeof rules[ this ] === "string" ) {
+ parts = rules[ this ].replace(/[\[\]]/g, "" ).split( /[\s,]+/ );
+ rules[ this ] = [ Number( parts[ 0 ]), Number( parts[ 1 ] ) ];
+ }
+ }
+ });
+
+ if ( $.validator.autoCreateRanges ) {
+ // auto-create ranges
+ if ( rules.min != null && rules.max != null ) {
+ rules.range = [ rules.min, rules.max ];
+ delete rules.min;
+ delete rules.max;
+ }
+ if ( rules.minlength != null && rules.maxlength != null ) {
+ rules.rangelength = [ rules.minlength, rules.maxlength ];
+ delete rules.minlength;
+ delete rules.maxlength;
+ }
+ }
+
+ return rules;
+ },
+
+ // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
+ normalizeRule: function( data ) {
+ if ( typeof data === "string" ) {
+ var transformed = {};
+ $.each( data.split( /\s/ ), function() {
+ transformed[ this ] = true;
+ });
+ data = transformed;
+ }
+ return data;
+ },
+
+ // http://jqueryvalidation.org/jQuery.validator.addMethod/
+ addMethod: function( name, method, message ) {
+ $.validator.methods[ name ] = method;
+ $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
+ if ( method.length < 3 ) {
+ $.validator.addClassRules( name, $.validator.normalizeRule( name ) );
+ }
+ },
+
+ methods: {
+
+ // http://jqueryvalidation.org/required-method/
+ required: function( value, element, param ) {
+ // check if dependency is met
+ if ( !this.depend( param, element ) ) {
+ return "dependency-mismatch";
+ }
+ if ( element.nodeName.toLowerCase() === "select" ) {
+ // could be an array for select-multiple or a string, both are fine this way
+ var val = $( element ).val();
+ return val && val.length > 0;
+ }
+ if ( this.checkable( element ) ) {
+ return this.getLength( value, element ) > 0;
+ }
+ return $.trim( value ).length > 0;
+ },
+
+ // http://jqueryvalidation.org/email-method/
+ email: function( value, element ) {
+ // From http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#e-mail-state-%28type=email%29
+ // Retrieved 2014-01-14
+ // If you have a problem with this implementation, report a bug against the above spec
+ // Or use custom methods to implement your own email validation
+ return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
+ },
+
+ // http://jqueryvalidation.org/url-method/
+ url: function( value, element ) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
+ return this.optional( element ) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value );
+ },
+
+ // http://jqueryvalidation.org/date-method/
+ date: function( value, element ) {
+ return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
+ },
+
+ // http://jqueryvalidation.org/dateISO-method/
+ dateISO: function( value, element ) {
+ return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
+ },
+
+ // http://jqueryvalidation.org/number-method/
+ number: function( value, element ) {
+ return this.optional( element ) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
+ },
+
+ // http://jqueryvalidation.org/digits-method/
+ digits: function( value, element ) {
+ return this.optional( element ) || /^\d+$/.test( value );
+ },
+
+ // http://jqueryvalidation.org/creditcard-method/
+ // based on http://en.wikipedia.org/wiki/Luhn/
+ creditcard: function( value, element ) {
+ if ( this.optional( element ) ) {
+ return "dependency-mismatch";
+ }
+ // accept only spaces, digits and dashes
+ if ( /[^0-9 \-]+/.test( value ) ) {
+ return false;
+ }
+ var nCheck = 0,
+ nDigit = 0,
+ bEven = false,
+ n, cDigit;
+
+ value = value.replace( /\D/g, "" );
+
+ // Basing min and max length on
+ // http://developer.ean.com/general_info/Valid_Credit_Card_Types
+ if ( value.length < 13 || value.length > 19 ) {
+ return false;
+ }
+
+ for ( n = value.length - 1; n >= 0; n--) {
+ cDigit = value.charAt( n );
+ nDigit = parseInt( cDigit, 10 );
+ if ( bEven ) {
+ if ( ( nDigit *= 2 ) > 9 ) {
+ nDigit -= 9;
+ }
+ }
+ nCheck += nDigit;
+ bEven = !bEven;
+ }
+
+ return ( nCheck % 10 ) === 0;
+ },
+
+ // http://jqueryvalidation.org/minlength-method/
+ minlength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength( value, element );
+ return this.optional( element ) || length >= param;
+ },
+
+ // http://jqueryvalidation.org/maxlength-method/
+ maxlength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength( value, element );
+ return this.optional( element ) || length <= param;
+ },
+
+ // http://jqueryvalidation.org/rangelength-method/
+ rangelength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength( value, element );
+ return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
+ },
+
+ // http://jqueryvalidation.org/min-method/
+ min: function( value, element, param ) {
+ return this.optional( element ) || value >= param;
+ },
+
+ // http://jqueryvalidation.org/max-method/
+ max: function( value, element, param ) {
+ return this.optional( element ) || value <= param;
+ },
+
+ // http://jqueryvalidation.org/range-method/
+ range: function( value, element, param ) {
+ return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
+ },
+
+ // http://jqueryvalidation.org/equalTo-method/
+ equalTo: function( value, element, param ) {
+ // bind to the blur event of the target in order to revalidate whenever the target field is updated
+ // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
+ var target = $( param );
+ if ( this.settings.onfocusout ) {
+ target.unbind( ".validate-equalTo" ).bind( "blur.validate-equalTo", function() {
+ $( element ).valid();
+ });
+ }
+ return value === target.val();
+ },
+
+ // http://jqueryvalidation.org/remote-method/
+ remote: function( value, element, param ) {
+ if ( this.optional( element ) ) {
+ return "dependency-mismatch";
+ }
+
+ var previous = this.previousValue( element ),
+ validator, data;
+
+ if (!this.settings.messages[ element.name ] ) {
+ this.settings.messages[ element.name ] = {};
+ }
+ previous.originalMessage = this.settings.messages[ element.name ].remote;
+ this.settings.messages[ element.name ].remote = previous.message;
+
+ param = typeof param === "string" && { url: param } || param;
+
+ if ( previous.old === value ) {
+ return previous.valid;
+ }
+
+ previous.old = value;
+ validator = this;
+ this.startRequest( element );
+ data = {};
+ data[ element.name ] = value;
+ $.ajax( $.extend( true, {
+ url: param,
+ mode: "abort",
+ port: "validate" + element.name,
+ dataType: "json",
+ data: data,
+ context: validator.currentForm,
+ success: function( response ) {
+ var valid = response === true || response === "true",
+ errors, message, submitted;
+
+ validator.settings.messages[ element.name ].remote = previous.originalMessage;
+ if ( valid ) {
+ submitted = validator.formSubmitted;
+ validator.prepareElement( element );
+ validator.formSubmitted = submitted;
+ validator.successList.push( element );
+ delete validator.invalid[ element.name ];
+ validator.showErrors();
+ } else {
+ errors = {};
+ message = response || validator.defaultMessage( element, "remote" );
+ errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;
+ validator.invalid[ element.name ] = true;
+ validator.showErrors( errors );
+ }
+ previous.valid = valid;
+ validator.stopRequest( element, valid );
+ }
+ }, param ) );
+ return "pending";
+ }
+
+ }
+
+});
+
+$.format = function deprecated() {
+ throw "$.format has been deprecated. Please use $.validator.format instead.";
+};
+
+// ajax mode: abort
+// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
+// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
+
+var pendingRequests = {},
+ ajax;
+// Use a prefilter if available (1.5+)
+if ( $.ajaxPrefilter ) {
+ $.ajaxPrefilter(function( settings, _, xhr ) {
+ var port = settings.port;
+ if ( settings.mode === "abort" ) {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = xhr;
+ }
+ });
+} else {
+ // Proxy ajax
+ ajax = $.ajax;
+ $.ajax = function( settings ) {
+ var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
+ port = ( "port" in settings ? settings : $.ajaxSettings ).port;
+ if ( mode === "abort" ) {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = ajax.apply(this, arguments);
+ return pendingRequests[port];
+ }
+ return ajax.apply(this, arguments);
+ };
+}
+
+// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
+// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
+
+$.extend($.fn, {
+ validateDelegate: function( delegate, type, handler ) {
+ return this.bind(type, function( event ) {
+ var target = $(event.target);
+ if ( target.is(delegate) ) {
+ return handler.apply(target, arguments);
+ }
+ });
+ }
+});
+
+})); \ No newline at end of file
diff --git a/js/line_counts.php b/js/line_counts.php
index 91d3988f93..1dc3c1a170 100644
--- a/js/line_counts.php
+++ b/js/line_counts.php
@@ -14,18 +14,29 @@ define('LINE_COUNTS', true);
$LINE_COUNT = array();
$LINE_COUNT["OpenStreetMap.js"] = 126;
+$LINE_COUNT["ajax.js"] = 805;
$LINE_COUNT["big_ints.js"] = 67;
$LINE_COUNT["canvg/canvg.js"] = 2508;
$LINE_COUNT["chart.js"] = 664;
-$LINE_COUNT["codemirror/addon/hint/show-hint.js"] = 394;
-$LINE_COUNT["codemirror/addon/hint/sql-hint.js"] = 248;
+$LINE_COUNT["codemirror/addon/hint/show-hint.js"] = 383;
+$LINE_COUNT["codemirror/addon/hint/sql-hint.js"] = 254;
+$LINE_COUNT["codemirror/addon/lint/lint.js"] = 209;
+$LINE_COUNT["codemirror/addon/lint/sql-lint.js"] = 39;
$LINE_COUNT["codemirror/addon/runmode/runmode.js"] = 72;
-$LINE_COUNT["codemirror/lib/codemirror.js"] = 8645;
-$LINE_COUNT["codemirror/mode/javascript/javascript.js"] = 692;
+$LINE_COUNT["codemirror/lib/codemirror.js"] = 8735;
+$LINE_COUNT["codemirror/mode/javascript/javascript.js"] = 704;
$LINE_COUNT["codemirror/mode/sql/sql.js"] = 391;
$LINE_COUNT["codemirror/mode/xml/xml.js"] = 384;
+$LINE_COUNT["common.js"] = 518;
+$LINE_COUNT["config.js"] = 838;
+$LINE_COUNT["console.js"] = 1536;
$LINE_COUNT["cross_framing_protection.js"] = 10;
+$LINE_COUNT["db_central_columns.js"] = 239;
+$LINE_COUNT["db_qbe.js"] = 76;
$LINE_COUNT["doclinks.js"] = 365;
+$LINE_COUNT["export.js"] = 841;
+$LINE_COUNT["gis_data_editor.js"] = 396;
+$LINE_COUNT["import.js"] = 167;
$LINE_COUNT["jqplot/excanvas.js"] = 1438;
$LINE_COUNT["jqplot/jquery.jqplot.js"] = 11411;
$LINE_COUNT["jqplot/plugins/jqplot.barRenderer.js"] = 800;
@@ -38,6 +49,7 @@ $LINE_COUNT["jqplot/plugins/jqplot.dateAxisRenderer.js"] = 741;
$LINE_COUNT["jqplot/plugins/jqplot.highlighter.js"] = 464;
$LINE_COUNT["jqplot/plugins/jqplot.pieRenderer.js"] = 903;
$LINE_COUNT["jqplot/plugins/jqplot.pointLabels.js"] = 376;
+$LINE_COUNT["jquery/additional-methods.js"] = 939;
$LINE_COUNT["jquery/jquery-1.11.1.min.js"] = 4;
$LINE_COUNT["jquery/jquery-ui-1.11.2.min.js"] = 12;
$LINE_COUNT["jquery/jquery-ui-timepicker-addon.js"] = 2223;
@@ -51,6 +63,7 @@ $LINE_COUNT["jquery/jquery.sortableTable.js"] = 271;
$LINE_COUNT["jquery/jquery.svg.js"] = 1352;
$LINE_COUNT["jquery/jquery.tablesorter.js"] = 1032;
$LINE_COUNT["jquery/jquery.uitablefilter.js"] = 117;
+$LINE_COUNT["jquery/jquery.validate.js"] = 1364;
$LINE_COUNT["jquery/src/jquery-ui/accordion.js"] = 584;
$LINE_COUNT["jquery/src/jquery-ui/autocomplete.js"] = 628;
$LINE_COUNT["jquery/src/jquery-ui/button.js"] = 411;
@@ -175,6 +188,9 @@ $LINE_COUNT["jquery/src/jquery/var/support.js"] = 4;
$LINE_COUNT["jquery/src/jquery/var/toString.js"] = 5;
$LINE_COUNT["jquery/src/jquery/wrap.js"] = 75;
$LINE_COUNT["keyhandler.js"] = 145;
+$LINE_COUNT["makegrid.js"] = 2224;
+$LINE_COUNT["menu-resizer.js"] = 183;
+$LINE_COUNT["microhistory.js"] = 330;
$LINE_COUNT["multi_column_sort.js"] = 81;
$LINE_COUNT["openlayers/OpenLayers.js"] = 2680;
$LINE_COUNT["openlayers/src/openlayers/lib/Firebug/firebug.js"] = 674;
@@ -462,62 +478,52 @@ $LINE_COUNT["openlayers/src/openlayers/lib/OpenLayers/Tween.js"] = 318;
$LINE_COUNT["openlayers/src/openlayers/lib/OpenLayers/Util.js"] = 1797;
$LINE_COUNT["openlayers/src/openlayers/lib/Rico/Color.js"] = 244;
$LINE_COUNT["openlayers/src/openlayers/lib/Rico/Corner.js"] = 329;
+$LINE_COUNT["page_settings.js"] = 59;
$LINE_COUNT["pmd/designer_db.js"] = 136;
$LINE_COUNT["pmd/designer_objects.js"] = 17;
-$LINE_COUNT["pmd/designer_page.js"] = 164;
-$LINE_COUNT["pmd/history.js"] = 813;
+$LINE_COUNT["pmd/designer_page.js"] = 172;
+$LINE_COUNT["pmd/history.js"] = 850;
$LINE_COUNT["pmd/iecanvas.js"] = 147;
-$LINE_COUNT["pmd/init.js"] = 40;
-$LINE_COUNT["pmd/move.js"] = 2004;
+$LINE_COUNT["pmd/init.js"] = 41;
+$LINE_COUNT["pmd/move.js"] = 2096;
+$LINE_COUNT["replication.js"] = 78;
+$LINE_COUNT["server_databases.js"] = 139;
+$LINE_COUNT["server_status_advisor.js"] = 99;
+$LINE_COUNT["server_status_monitor.js"] = 2173;
+$LINE_COUNT["server_status_processes.js"] = 188;
$LINE_COUNT["server_status_queries.js"] = 34;
+$LINE_COUNT["server_status_sorter.js"] = 83;
+$LINE_COUNT["server_status_variables.js"] = 103;
$LINE_COUNT["server_user_groups.js"] = 42;
$LINE_COUNT["sprintf.js"] = 211;
+$LINE_COUNT["tbl_change.js"] = 712;
+$LINE_COUNT["tbl_chart.js"] = 419;
$LINE_COUNT["tbl_find_replace.js"] = 47;
+$LINE_COUNT["tbl_gis_visualization.js"] = 358;
+$LINE_COUNT["tbl_zoom_plot_jqplot.js"] = 646;
$LINE_COUNT["tracekit/tracekit.js"] = 1114;
$LINE_COUNT["transformations/image_upload.js"] = 28;
$LINE_COUNT["transformations/json.js"] = 17;
-$LINE_COUNT["transformations/xml.js"] = 18;
$LINE_COUNT["transformations/json_editor.js"] = 17;
-$LINE_COUNT["transformations/sql_editor.js"] = 30;
+$LINE_COUNT["transformations/sql_editor.js"] = 12;
+$LINE_COUNT["transformations/xml.js"] = 18;
$LINE_COUNT["transformations/xml_editor.js"] = 16;
-$LINE_COUNT["ajax.js"] = 1031;
-$LINE_COUNT["common.js"] = 515;
-$LINE_COUNT["config.js"] = 798;
-$LINE_COUNT["console.js"] = 1033;
-$LINE_COUNT["db_central_columns.js"] = 201;
$LINE_COUNT["db_operations.js"] = 157;
-$LINE_COUNT["db_qbe.js"] = 64;
$LINE_COUNT["db_search.js"] = 239;
-$LINE_COUNT["db_structure.js"] = 391;
-$LINE_COUNT["db_tracking.js"] = 84;
-$LINE_COUNT["error_report.js"] = 340;
-$LINE_COUNT["export.js"] = 401;
-$LINE_COUNT["functions.js"] = 4572;
-$LINE_COUNT["gis_data_editor.js"] = 396;
-$LINE_COUNT["import.js"] = 167;
-$LINE_COUNT["indexes.js"] = 697;
-$LINE_COUNT["makegrid.js"] = 1962;
-$LINE_COUNT["menu-resizer.js"] = 182;
-$LINE_COUNT["navigation.js"] = 1507;
-$LINE_COUNT["normalization.js"] = 707;
-$LINE_COUNT["replication.js"] = 73;
-$LINE_COUNT["rte.js"] = 944;
-$LINE_COUNT["server_databases.js"] = 137;
-$LINE_COUNT["server_plugins.js"] = 30;
-$LINE_COUNT["server_privileges.js"] = 451;
-$LINE_COUNT["server_status_advisor.js"] = 93;
-$LINE_COUNT["server_status_monitor.js"] = 2172;
-$LINE_COUNT["server_status_processes.js"] = 189;
-$LINE_COUNT["server_status_sorter.js"] = 89;
-$LINE_COUNT["server_status_variables.js"] = 103;
+$LINE_COUNT["db_structure.js"] = 382;
+$LINE_COUNT["db_tracking.js"] = 88;
+$LINE_COUNT["error_report.js"] = 310;
+$LINE_COUNT["functions.js"] = 4776;
+$LINE_COUNT["indexes.js"] = 757;
+$LINE_COUNT["navigation.js"] = 1557;
+$LINE_COUNT["normalization.js"] = 710;
+$LINE_COUNT["rte.js"] = 1047;
+$LINE_COUNT["server_plugins.js"] = 14;
+$LINE_COUNT["server_privileges.js"] = 431;
$LINE_COUNT["server_variables.js"] = 147;
-$LINE_COUNT["sql.js"] = 843;
-$LINE_COUNT["tbl_change.js"] = 754;
-$LINE_COUNT["tbl_chart.js"] = 429;
-$LINE_COUNT["tbl_gis_visualization.js"] = 353;
-$LINE_COUNT["tbl_operations.js"] = 243;
+$LINE_COUNT["sql.js"] = 892;
+$LINE_COUNT["tbl_operations.js"] = 303;
$LINE_COUNT["tbl_relation.js"] = 234;
-$LINE_COUNT["tbl_select.js"] = 395;
-$LINE_COUNT["tbl_structure.js"] = 397;
-$LINE_COUNT["tbl_tracking.js"] = 95;
-$LINE_COUNT["tbl_zoom_plot_jqplot.js"] = 638;
+$LINE_COUNT["tbl_select.js"] = 407;
+$LINE_COUNT["tbl_structure.js"] = 492;
+$LINE_COUNT["tbl_tracking.js"] = 99;
diff --git a/js/makegrid.js b/js/makegrid.js
index 4a5046b26e..9ea188c5b2 100644
--- a/js/makegrid.js
+++ b/js/makegrid.js
@@ -440,9 +440,11 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
text += text.length > 0 ? '<br />' : '';
text += '- ' + g.strMultiSortHint;
}
- if (g.showMarkHint && g.markHint
- && !g.showSortHint // we do not show mark hint, when sort hint is shown
- && g.showReorderHint && g.reorderHint
+ if (g.showMarkHint &&
+ g.markHint &&
+ ! g.showSortHint && // we do not show mark hint, when sort hint is shown
+ g.showReorderHint &&
+ g.reorderHint
) {
text += text.length > 0 ? '<br />' : '';
text += '- ' + g.reorderHint;
@@ -575,9 +577,8 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
if (!g.isCellEditActive) {
var $cell = $(cell);
- if (
- 'string' === $cell.attr('data-type')
- || 'blob' === $cell.attr('data-type')
+ if ('string' === $cell.attr('data-type') ||
+ 'blob' === $cell.attr('data-type')
) {
g.cEdit = g.cEditTextarea;
} else {
@@ -603,9 +604,18 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
g.currentEditCell = cell;
$(g.cEdit).find('.edit_box').focus();
+ moveCursorToEnd($(g.cEdit).find('.edit_box'));
$(g.cEdit).find('*').removeProp('disabled');
}
}
+
+ function moveCursorToEnd(input) {
+ var originalValue = input.val();
+ var originallength = originalValue.length;
+ input.val('');
+ input.blur().focus().val(originalValue);
+ input[0].setSelectionRange(originallength, originallength);
+ }
},
/**
@@ -616,11 +626,17 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
* or just specify "true", if we want to replace the edited field with the new value.
* @param field Optional, the edited <td>. If not specified, the function will
* use currently edited <td> from g.currentEditCell.
+ * @param field Optional, this object contains a boolean named move (true, if called from move* functions)
+ * and a <td> to which the grid_edit should move
*/
- hideEditCell: function (force, data, field) {
+ hideEditCell: function (force, data, field, options) {
if (g.isCellEditActive && !force) {
// cell is being edited, save or post the edited data
- g.saveOrPostEditedCell();
+ if (options !== undefined) {
+ g.saveOrPostEditedCell(options);
+ } else {
+ g.saveOrPostEditedCell();
+ }
return;
}
@@ -1040,10 +1056,6 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
datepicker_div.css({'top': 0, 'left': 0, 'position': 'relative'});
$(g.cEdit).append(datepicker_div);
- if (is_null){
- $(g.cEdit).find('.edit_area').hide();
- }
-
// cancel any click on the datepicker element
$editArea.find('> *').click(function (e) {
e.stopPropagation();
@@ -1057,7 +1069,7 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
$editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>');
}
}
- if ($editArea.children().length > 0 && !is_null) {
+ if ($editArea.children().length > 0) {
$editArea.show();
}
}
@@ -1065,8 +1077,11 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
/**
* Post the content of edited cell.
+ *
+ * @param field Optional, this object contains a boolean named move (true, if called from move* functions)
+ * and a <td> to which the grid_edit should move
*/
- postEditedCell: function () {
+ postEditedCell: function (options) {
if (g.isSaving) {
return;
}
@@ -1273,7 +1288,9 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
.find('input').removeProp('disabled'); // enable the save button back
}
if (typeof data !== 'undefined' && data.success === true) {
- PMA_ajaxShowMessage(data.message);
+ if (typeof options === 'undefined' || ! options.move) {
+ PMA_ajaxShowMessage(data.message);
+ }
// update where_clause related data in each edited row
$(g.t).find('td.to_be_saved').parents('tr').each(function () {
@@ -1315,7 +1332,7 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
var tools = $result_query.find('.tools').wrap('<p>').parent().html();
// sqlOuter and tools will not be present if 'Show SQL queries' configuration is off
if (typeof sqlOuter != 'undefined' && typeof tools != 'undefined') {
- $existing_query = $(g.o).find('.result_query');
+ var $existing_query = $(g.o).find('.result_query');
// If two query box exists update query in second else add a second box
if ($existing_query.find('div.sqlOuter').length > 1) {
$existing_query.children(":nth-child(4)").remove();
@@ -1347,6 +1364,10 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
}
}
}
+ }).done(function(){
+ if (options !== undefined && options.move) {
+ g.showEditCell(options.cell);
+ }
}); // end $.ajax()
},
@@ -1430,20 +1451,54 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
/**
* Save or post currently edited cell, depending on the "saveCellsAtOnce" configuration.
+ *
+ * @param field Optional, this object contains a boolean named move (true, if called from move* functions)
+ * and a <td> to which the grid_edit should move
*/
- saveOrPostEditedCell: function () {
+ saveOrPostEditedCell: function (options) {
var saved = g.saveEditedCell();
+ // Check if $cfg['SaveCellsAtOnce'] is false
if (!g.saveCellsAtOnce) {
+ // Check if need_to_post is true
if (saved) {
- g.postEditedCell();
+ // Check if this function called from 'move' functions
+ if (options !== undefined && options.move) {
+ g.postEditedCell(options);
+ } else {
+ g.postEditedCell();
+ }
+ // need_to_post is false
} else {
- g.hideEditCell(true);
+ // Check if this function called from 'move' functions
+ if (options !== undefined && options.move) {
+ g.hideEditCell(true);
+ g.showEditCell(options.cell);
+ // NOT called from 'move' functions
+ } else {
+ g.hideEditCell(true);
+ }
}
+ // $cfg['SaveCellsAtOnce'] is true
} else {
+ // If need_to_post
if (saved) {
- g.hideEditCell(true, true);
+ // If this function called from 'move' functions
+ if (options !== undefined && options.move) {
+ g.hideEditCell(true, true, false, options);
+ g.showEditCell(options.cell);
+ // NOT called from 'move' functions
+ } else {
+ g.hideEditCell(true, true);
+ }
} else {
- g.hideEditCell(true);
+ // If this function called from 'move' functions
+ if (options !== undefined && options.move) {
+ g.hideEditCell(true, false, false, options);
+ g.showEditCell(options.cell);
+ // NOT called from 'move' functions
+ } else {
+ g.hideEditCell(true);
+ }
}
}
},
@@ -1589,16 +1644,17 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
// get data columns in the first row of the table
var $firstRowCols = $(g.t).find('tr:first th.draggable');
+ var i;
// initialize column visibility
var $col_visib = $(g.o).find('.col_visib'); // check if column visibility is passed from PHP
if ($col_visib.length > 0) {
g.colVisib = $col_visib.val().split(',');
- for (var i = 0; i < g.colVisib.length; i++) {
+ for (i = 0; i < g.colVisib.length; i++) {
g.colVisib[i] = parseInt(g.colVisib[i], 10);
}
} else {
g.colVisib = [];
- for (var i = 0; i < $firstRowCols.length; i++) {
+ for (i = 0; i < $firstRowCols.length; i++) {
g.colVisib.push(1);
}
}
@@ -1638,7 +1694,7 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
}
};
- for (var i = 0; i < $firstRowCols.length; i++) {
+ for (i = 0; i < $firstRowCols.length; i++) {
var currHeader = $firstRowCols[i];
var listElmt = document.createElement('div');
$(listElmt).text($(currHeader).text())
@@ -1679,6 +1735,187 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
},
/**
+ * Move currently Editing Cell to Up
+ */
+ moveUp: function(e) {
+ e.preventDefault();
+ var $this_field = $(g.currentEditCell);
+ var field_name = getFieldName($(g.t), $this_field);
+
+ var where_clause = $this_field.parents('tr').first().find('.where_clause').val();
+ if (typeof where_clause === 'undefined') {
+ where_clause = '';
+ }
+ where_clause = PMA_urldecode(where_clause);
+ var found = false;
+ var $found_row;
+ var $prev_row;
+ var j = 0;
+
+ $this_field.parents('tr').first().parents('tbody').children().each(function(){
+ if (PMA_urldecode($(this).find('.where_clause').val()) == where_clause) {
+ found = true;
+ $found_row = $(this);
+ }
+ if (!found) {
+ $prev_row = $(this);
+ }
+ });
+
+ var new_cell;
+
+ if (found && $prev_row) {
+ $prev_row.children('td').each(function(){
+ if (getFieldName($(g.t), $(this)) == field_name) {
+ new_cell = this;
+ }
+ });
+ }
+
+ if (new_cell) {
+ g.hideEditCell(false, false, false, {move : true, cell : new_cell});
+ }
+ },
+
+ /**
+ * Move currently Editing Cell to Down
+ */
+ moveDown: function(e) {
+ e.preventDefault();
+
+ var $this_field = $(g.currentEditCell);
+ var field_name = getFieldName($(g.t), $this_field);
+
+ var where_clause = $this_field.parents('tr').first().find('.where_clause').val();
+ if (typeof where_clause === 'undefined') {
+ where_clause = '';
+ }
+ where_clause = PMA_urldecode(where_clause);
+ var found = false;
+ var $found_row;
+ var $next_row;
+ var j = 0;
+ var next_row_found = false;
+ $this_field.parents('tr').first().parents('tbody').children().each(function(){
+ if (PMA_urldecode($(this).find('.where_clause').val()) == where_clause) {
+ found = true;
+ $found_row = $(this);
+ }
+ if (found) {
+ if (j >= 1 && ! next_row_found) {
+ $next_row = $(this);
+ next_row_found = true;
+ } else {
+ j++;
+ }
+ }
+ });
+
+ var new_cell;
+ if (found && $next_row) {
+ $next_row.children('td').each(function(){
+ if (getFieldName($(g.t), $(this)) == field_name) {
+ new_cell = this;
+ }
+ });
+ }
+
+ if (new_cell) {
+ g.hideEditCell(false, false, false, {move : true, cell : new_cell});
+ }
+ },
+
+ /**
+ * Move currently Editing Cell to Left
+ */
+ moveLeft: function(e) {
+ e.preventDefault();
+
+ var $this_field = $(g.currentEditCell);
+ var field_name = getFieldName($(g.t), $this_field);
+
+ var where_clause = $this_field.parents('tr').first().find('.where_clause').val();
+ if (typeof where_clause === 'undefined') {
+ where_clause = '';
+ }
+ where_clause = PMA_urldecode(where_clause);
+ var found = false;
+ var $found_row;
+ var j = 0;
+ $this_field.parents('tr').first().parents('tbody').children().each(function(){
+ if (PMA_urldecode($(this).find('.where_clause').val()) == where_clause) {
+ found = true;
+ $found_row = $(this);
+ }
+ });
+
+ var left_cell;
+ var cell_found = false;
+ if (found) {
+ $found_row.children('td.grid_edit').each(function(){
+ if (getFieldName($(g.t), $(this)) === field_name) {
+ cell_found = true;
+ }
+ if (!cell_found) {
+ left_cell = this;
+ }
+ });
+ }
+
+ if (left_cell) {
+ g.hideEditCell(false, false, false, {move : true, cell : left_cell});
+ }
+ },
+
+ /**
+ * Move currently Editing Cell to Right
+ */
+ moveRight: function(e) {
+ e.preventDefault();
+
+ var $this_field = $(g.currentEditCell);
+ var field_name = getFieldName($(g.t), $this_field);
+
+ var where_clause = $this_field.parents('tr').first().find('.where_clause').val();
+ if (typeof where_clause === 'undefined') {
+ where_clause = '';
+ }
+ where_clause = PMA_urldecode(where_clause);
+ var found = false;
+ var $found_row;
+ var j = 0;
+ $this_field.parents('tr').first().parents('tbody').children().each(function(){
+ if (PMA_urldecode($(this).find('.where_clause').val()) == where_clause) {
+ found = true;
+ $found_row = $(this);
+ }
+ });
+
+ var right_cell;
+ var cell_found = false;
+ var next_cell_found = false;
+ if (found) {
+ $found_row.children('td.grid_edit').each(function(){
+ if (getFieldName($(g.t), $(this)) === field_name) {
+ cell_found = true;
+ }
+ if (cell_found) {
+ if (j >= 1 && ! next_cell_found) {
+ right_cell = this;
+ next_cell_found = true;
+ } else {
+ j++;
+ }
+ }
+ });
+ }
+
+ if (right_cell) {
+ g.hideEditCell(false, false, false, {move : true, cell : right_cell});
+ }
+ },
+
+ /**
* Initialize grid editing feature.
*/
initGridEdit: function () {
@@ -1692,6 +1929,18 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
e.stopPropagation();
}
+ function handleCtrlNavigation(e) {
+ if ((e.ctrlKey && e.which == 38 ) || (e.altKey && e.which == 38)) {
+ g.moveUp(e);
+ } else if ((e.ctrlKey && e.which == 40) || (e.altKey && e.which == 40)) {
+ g.moveDown(e);
+ } else if ((e.ctrlKey && e.which == 37 ) || (e.altKey && e.which == 37)) {
+ g.moveLeft(e);
+ } else if ((e.ctrlKey && e.which == 39) || (e.altKey && e.which == 39)) {
+ g.moveRight(e);
+ }
+ }
+
// create cell edit wrapper element
g.cEditStd = document.createElement('div');
g.cEdit = g.cEditStd;
@@ -1729,7 +1978,7 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
$(g.t).find('td.data.click2')
.click(function (e) {
- $cell = $(this);
+ var $cell = $(this);
// In the case of relational link, We want single click on the link
// to goto the link and double click to start grid-editing.
var $link = $(e.target);
@@ -1742,7 +1991,7 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
if (clicks == 1) {
// if there are no previous clicks,
// start the single click timer
- timer = setTimeout(function () {
+ var timer = setTimeout(function () {
// temporarily remove ajax class so the page loader will not handle it,
// submit and then add it back
$link.removeClass('ajax');
@@ -1770,6 +2019,8 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
}
});
+ $(g.cEditStd).on('keydown', 'input.edit_box, select', handleCtrlNavigation);
+
$(g.cEditStd).find('.edit_box').focus(function (e) {
g.showEditArea();
});
@@ -1786,6 +2037,9 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
e.preventDefault();
}
});
+
+ $(g.cEditTextarea).on('keydown', 'textarea.edit_box, select', handleCtrlNavigation);
+
$(g.cEditTextarea).find('.edit_box').focus(function (e) {
g.showEditArea();
});
@@ -1846,7 +2100,15 @@ function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdi
* Initialize grid
******************/
- // wrap all data cells, except actions cell, with span
+ // wrap all truncated data cells with span indicating the original length
+ // todo update the original length after a grid edit
+ $(t).find('td.data.truncated:not(:has(span))')
+ .wrapInner(function() {
+ return '<span title="' + PMA_messages.strOriginalLength + ' ' +
+ $(this).data('originallength') + '"></span>';
+ });
+
+ // wrap remaining cells, except actions cell, with span
$(t).find('th, td:not(:has(span))')
.wrapInner('<span />');
diff --git a/js/menu-resizer.js b/js/menu-resizer.js
index eb68083008..392f94be34 100644
--- a/js/menu-resizer.js
+++ b/js/menu-resizer.js
@@ -68,7 +68,8 @@
// Calculate the total width used by all the shown tabs
var total_len = more_shown ? submenu_w : 0;
var l = $li.length - 1;
- for (var i = 0; i < l; i++) {
+ var i;
+ for (i = 0; i < l; i++) {
total_len += $($li[i]).outerWidth(true);
}
// Now hide menu elements that don't fit into the menubar
@@ -91,7 +92,7 @@
// If we didn't hide any tabs, then there might be some space to show some
if (! hidden) {
// Show menu elements that do fit into the menubar
- for (var i = 0, l = $li2.length; i < l; i++) {
+ for (i = 0, l = $li2.length; i < l; i++) {
total_len += $($li2[i]).data('width');
// item fits or (it is the last item
// and it would fit if More got removed)
diff --git a/js/messages.php b/js/messages.php
index 07fd963c51..61f72654b4 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -29,9 +29,11 @@ require_once './libraries/Util.class.php';
require_once './libraries/OutputBuffering.class.php';
$buffer = PMA_OutputBuffering::getInstance();
$buffer->start();
-register_shutdown_function(function() {
- echo PMA_OutputBuffering::getInstance()->getContents();
-});
+register_shutdown_function(
+ function () {
+ echo PMA_OutputBuffering::getInstance()->getContents();
+ }
+);
$js_messages['strNoDropDatabases'] = __('"DROP DATABASE" statements are disabled.');
if ($cfg['AllowUserDropDatabase']) {
@@ -58,19 +60,42 @@ $js_messages['strConfirmDeleteQBESearch'] = __('Do you really want to delete the
$js_messages['strConfirmNavigation'] = __('You have unsaved changes; are you sure you want to leave this page?');
$js_messages['strDropUserWarning'] = __('Do you really want to revoke the selected user(s) ?');
$js_messages['strDeleteCentralColumnWarning'] = __('Do you really want to delete this central column?');
+$js_messages['strDropRTEitems'] = __('Do you really want to delete the selected items?');
+$js_messages['strDropPartitionWarning'] = __('Do you really want to DROP the selected partition(s)? This will also DELETE the data related to the selected partition(s)!');
+$js_messages['strTruncatePartitionWarning'] = __('Do you really want to TRUNCATE the selected partition(s)?');
+$js_messages['strChangeColumnCollation'] = __(
+ 'This operation will attempt to convert your data to the new collation. In '
+ . 'rare cases, especially where a character doesn\'t exist in the new '
+ . 'collation, this process could cause the data to appear incorrectly under '
+ . 'the new collation; in this case we suggest you revert to the original '
+ . 'collation and refer to the tips at '
+)
+ . '<a href="%s" target="garbled_data_wiki">' . __('Garbled Data') . '</a>.'
+ . '<br/><br/>'
+ . __('Are you sure you wish to change the collation and convert the data?');
+$js_messages['strChangeAllColumnCollationsWarning'] = __(
+ 'Through this operation, MySQL attempts to map the data values between collations. '
+ . 'If the character sets are incompatible, '
+ . 'there may be data loss and this lost data may <b>NOT</b> be recoverable simply '
+ . 'by changing back the column collation(s).'
+ . '<b> To convert existing data, it is suggested to use the column(s) editing feature '
+ . '(the "Change" Link) on the table structure page. </b>'
+)
+. '<br/><br/>'
+. __('Are you sure you wish to change all the column collations and convert the data?');
/* For modal dialog buttons */
-$js_messages['strSaveAndClose'] = __('Save & Close');
+$js_messages['strSaveAndClose'] = __('Save & close');
$js_messages['strReset'] = __('Reset');
-$js_messages['strResetAll'] = __('Reset All');
+$js_messages['strResetAll'] = __('Reset all');
/* For indexes */
$js_messages['strFormEmpty'] = __('Missing value in the form!');
$js_messages['strRadioUnchecked'] = __('Select at least one of the options!');
$js_messages['strEnterValidNumber'] = __('Please enter a valid number!');
$js_messages['strEnterValidLength'] = __('Please enter a valid length!');
-$js_messages['strAddIndex'] = __('Add Index');
-$js_messages['strEditIndex'] = __('Edit Index');
+$js_messages['strAddIndex'] = __('Add index');
+$js_messages['strEditIndex'] = __('Edit index');
$js_messages['strAddToIndex'] = __('Add %s column(s) to index');
$js_messages['strCreateSingleColumnIndex'] = __('Create single-column index');
$js_messages['strCreateCompositeIndex'] = __('Create composite index');
@@ -90,7 +115,7 @@ $js_messages['strSQLQuery'] = __('SQL query:');
/* Charts */
/* l10n: Default label for the y-Axis of Charts */
-$js_messages['strYValues'] = __('Y Values');
+$js_messages['strYValues'] = __('Y values');
/* For server_privileges.js */
$js_messages['strHostEmpty'] = __('The host name is empty!');
@@ -100,6 +125,12 @@ $js_messages['strPasswordNotSame'] = __('The passwords aren\'t the same!');
$js_messages['strRemovingSelectedUsers'] = __('Removing Selected Users');
$js_messages['strClose'] = __('Close');
+/* For export.js */
+$js_messages['strTemplateCreated'] = __('Template was created.');
+$js_messages['strTemplateLoaded'] = __('Template was loaded.');
+$js_messages['strTemplateUpdated'] = __('Template was updated.');
+$js_messages['strTemplateDeleted'] = __('Template was deleted.');
+
/* l10n: Other, small valued, queries */
$js_messages['strOther'] = __('Other');
/* l10n: Thousands separator */
@@ -117,7 +148,7 @@ $js_messages['strQueryCacheEfficiency'] = __('Query cache efficiency');
$js_messages['strQueryCacheUsage'] = __('Query cache usage');
$js_messages['strQueryCacheUsed'] = __('Query cache used');
-$js_messages['strSystemCPUUsage'] = __('System CPU Usage');
+$js_messages['strSystemCPUUsage'] = __('System CPU usage');
$js_messages['strSystemMemory'] = __('System memory');
$js_messages['strSystemSwap'] = __('System swap');
@@ -128,10 +159,10 @@ $js_messages['strBufferedMemory'] = __('Buffered memory');
$js_messages['strFreeMemory'] = __('Free memory');
$js_messages['strUsedMemory'] = __('Used memory');
-$js_messages['strTotalSwap'] = __('Total Swap');
-$js_messages['strCachedSwap'] = __('Cached Swap');
-$js_messages['strUsedSwap'] = __('Used Swap');
-$js_messages['strFreeSwap'] = __('Free Swap');
+$js_messages['strTotalSwap'] = __('Total swap');
+$js_messages['strCachedSwap'] = __('Cached swap');
+$js_messages['strUsedSwap'] = __('Used swap');
+$js_messages['strFreeSwap'] = __('Free swap');
$js_messages['strBytesSent'] = __('Bytes sent');
$js_messages['strBytesReceived'] = __('Bytes received');
@@ -185,7 +216,7 @@ $js_messages['strNoSuperUser'] = __(
$js_messages['strChangeSettings'] = __('Change settings');
$js_messages['strCurrentSettings'] = __('Current settings');
-$js_messages['strChartTitle'] = __('Chart Title');
+$js_messages['strChartTitle'] = __('Chart title');
/* l10n: As in differential values */
$js_messages['strDifferential'] = __('Differential');
$js_messages['strDividedBy'] = __('Divided by %s');
@@ -241,7 +272,7 @@ $js_messages['strImportDialogTitle'] = __('Import monitor configuration');
$js_messages['strImportDialogMessage'] = __('Please select the file you want to import.');
$js_messages['strNoImportFile'] = __('No files available on server for import!');
-$js_messages['strAnalyzeQuery'] = __('Analyse Query');
+$js_messages['strAnalyzeQuery'] = __('Analyse query');
/* Server status advisor */
@@ -255,36 +286,40 @@ $js_messages['strFormula'] = __('Used variable / formula');
$js_messages['strTest'] = __('Test');
/* For query editor */
-$js_messages['strFormatting'] = __('Formatting SQL...');
+$js_messages['strFormatting'] = __('Formatting SQL…');
/* For inline query editing */
$js_messages['strGo'] = __('Go');
$js_messages['strCancel'] = __('Cancel');
+/* For page-related settings */
+$js_messages['strPageSettings'] = _('Page-related settings');
+$js_messages['strApply'] = _('Apply');
+
/* For Ajax Notifications */
$js_messages['strLoading'] = __('Loading…');
-$js_messages['strAbortedRequest'] = __('Request Aborted!!');
-$js_messages['strProcessingRequest'] = __('Processing Request');
-$js_messages['strRequestFailed'] = __('Request Failed!!');
-$js_messages['strErrorProcessingRequest'] = __('Error in Processing Request');
+$js_messages['strAbortedRequest'] = __('Request aborted!!');
+$js_messages['strProcessingRequest'] = __('Processing request');
+$js_messages['strRequestFailed'] = __('Request failed!!');
+$js_messages['strErrorProcessingRequest'] = __('Error in processing request');
$js_messages['strErrorCode'] = __('Error code: %s');
$js_messages['strErrorText'] = __('Error text: %s');
$js_messages['strNoDatabasesSelected'] = __('No databases selected.');
-$js_messages['strDroppingColumn'] = __('Dropping Column');
-$js_messages['strAddingPrimaryKey'] = __('Adding Primary Key');
+$js_messages['strDroppingColumn'] = __('Dropping column');
+$js_messages['strAddingPrimaryKey'] = __('Adding primary key');
$js_messages['strOK'] = __('OK');
$js_messages['strDismiss'] = __('Click to dismiss this notification');
/* For db_operations.js */
-$js_messages['strRenamingDatabases'] = __('Renaming Databases');
-$js_messages['strCopyingDatabase'] = __('Copying Database');
-$js_messages['strChangingCharset'] = __('Changing Charset');
+$js_messages['strRenamingDatabases'] = __('Renaming databases');
+$js_messages['strCopyingDatabase'] = __('Copying database');
+$js_messages['strChangingCharset'] = __('Changing charset');
$js_messages['strNo'] = __('No');
+/* For Foreign key checks */
+$js_messages['strForeignKeyCheck'] = __('Enable foreign key checks');
+
/* For db_stucture.js */
-$js_messages['strForeignKeyCheck'] = __('Foreign key check:');
-$js_messages['strForeignKeyCheckEnabled'] = __('(Enabled)');
-$js_messages['strForeignKeyCheckDisabled'] = __('(Disabled)');
$js_messages['strErrorRealRowCount'] = __('Failed to get real row count.');
/* For db_search.js */
@@ -296,6 +331,7 @@ $js_messages['strDeleting'] = __('Deleting');
/* For db_routines.js */
$js_messages['MissingReturn'] = __('The definition of a stored function must contain a RETURN statement!');
+$js_messages['strExport'] = __('Export');
/* For ENUM/SET editor*/
$js_messages['enum_editor'] = __('ENUM/SET editor');
@@ -311,9 +347,11 @@ $js_messages['strImportCSV'] = __('Note: If the file contains multiple tables, t
$js_messages['strHideQueryBox'] = __('Hide query box');
$js_messages['strShowQueryBox'] = __('Show query box');
$js_messages['strEdit'] = __('Edit');
+$js_messages['strDelete'] = __('Delete');
$js_messages['strNotValidRowNumber'] = __('%d is not valid row number.');
$js_messages['strBrowseForeignValues'] = __('Browse foreign values');
$js_messages['strNoAutoSavedQuery'] = __('No auto-saved query');
+$js_messages['strBookmarkVariable'] = __('Variable %d:');
/* For Central list of columns */
$js_messages['pickColumn'] = __('Pick');
@@ -382,6 +420,7 @@ $js_messages['strDisplayHelp'] = '<ul><li>'
. '</li><li>'
. __('The plot can be resized by dragging it along the bottom right corner.')
. '</li></ul>';
+$js_messages['strHelpTitle'] = 'Zoom search instructions';
$js_messages['strInputNull'] = '<strong>' . __('Select two columns') . '</strong>';
$js_messages['strSameInputs'] = '<strong>'
. __('Select two different columns')
@@ -398,11 +437,10 @@ $js_messages['strPointN'] = __('Point %d');
$js_messages['strLineString'] = __('Linestring');
$js_messages['strPolygon'] = __('Polygon');
$js_messages['strGeometry'] = __('Geometry');
-$js_messages['strInnerRing'] = __('Inner Ring');
-$js_messages['strOuterRing'] = __('Outer Ring');
+$js_messages['strInnerRing'] = __('Inner ring');
+$js_messages['strOuterRing'] = __('Outer ring');
$js_messages['strAddPoint'] = __('Add a point');
$js_messages['strAddInnerRing'] = __('Add an inner ring');
-$js_messages['strFunctionHint'] = __('Shift + Click on function name to apply to all rows.');
$js_messages['strYes'] = __('Yes');
$js_messages['strCopyEncryptionKey'] = __('Do you want to copy encryption key?');
$js_messages['strEncryptionKey'] = __('Encryption key');
@@ -424,6 +462,7 @@ $js_messages['strLeavingDesigner'] = __(
);
$js_messages['strPageName'] = __('Page name');
$js_messages['strSavePage'] = __('Save page');
+$js_messages['strSavePageAs'] = __('Save page as');
$js_messages['strOpenPage'] = __('Open page');
$js_messages['strDeletePage'] = __('Delete page');
$js_messages['strUntitled'] = __('Untitled');
@@ -437,6 +476,7 @@ $js_messages['strModificationSaved'] = __('Modifications have been saved');
/* Visual query builder (js/pmd/move.js) */
$js_messages['strAddOption'] = __('Add an option for column "%s".');
$js_messages['strObjectsCreated'] = __('%d object(s) created.');
+$js_messages['strSubmit'] = __('Submit');
/* For makegrid.js (column reordering, show/hide column, grid editing) */
$js_messages['strCellEditHint'] = __('Press escape to cancel editing.');
@@ -453,6 +493,7 @@ $js_messages['strShowAllCol'] = __('Show all');
$js_messages['strAlertNonUnique'] = __('This table does not contain a unique column. Features related to the grid edit, checkbox, Edit, Copy and Delete links may not work after saving.');
$js_messages['strEnterValidHex'] = __('Please enter a valid hexadecimal string. Valid characters are 0-9, A-F.');
$js_messages['strShowAllRowsWarning'] = __('Do you really want to see all of the rows? For a big table this could crash the browser.');
+$js_messages['strOriginalLength'] = __('Original length');
/** Drag & Drop sql import messages */
$js_messages['dropImportMessageCancel'] = __('cancel');
@@ -481,14 +522,14 @@ $js_messages['strColNameCopyText'] = __('Right-click the column name to copy it
/* password generation */
$js_messages['strGeneratePassword'] = __('Generate password');
$js_messages['strGenerate'] = __('Generate');
-$js_messages['strChangePassword'] = __('Change Password');
+$js_messages['strChangePassword'] = __('Change password');
/* navigation tabs */
$js_messages['strMore'] = __('More');
/* navigation panel */
-$js_messages['strShowPanel'] = __('Show Panel');
-$js_messages['strHidePanel'] = __('Hide Panel');
+$js_messages['strShowPanel'] = __('Show panel');
+$js_messages['strHidePanel'] = __('Hide panel');
$js_messages['strUnhideNavItem'] = __('Show hidden navigation tree items.');
$js_messages['linkWithMain'] = __('Link with main panel');
$js_messages['unlinkWithMain'] = __('Unlink from main panel');
@@ -512,13 +553,13 @@ $js_messages['strUpToDate'] = __('up to date');
$js_messages['strCreateView'] = __('Create view');
/* Error Reporting */
-$js_messages['strSendErrorReport'] = __("Send Error Report");
-$js_messages['strSubmitErrorReport'] = __("Submit Error Report");
+$js_messages['strSendErrorReport'] = __("Send error report");
+$js_messages['strSubmitErrorReport'] = __("Submit error report");
$js_messages['strErrorOccurred'] = __(
"A fatal JavaScript error has occurred. Would you like to send an error report?"
);
-$js_messages['strChangeReportSettings'] = __("Change Report Settings");
-$js_messages['strShowReportDetails'] = __("Show Report Details");
+$js_messages['strChangeReportSettings'] = __("Change report settings");
+$js_messages['strShowReportDetails'] = __("Show report details");
$js_messages['strIgnore'] = __("Ignore");
$js_messages['strTimeOutError'] = __(
"Your export is incomplete, due to a low execution time limit at the PHP level!"
@@ -532,14 +573,15 @@ $js_messages['strTooManyInputs'] = __(
$js_messages['phpErrorsFound'] = '<div class="error">'
. __('Some errors have been detected on the server!')
- . '<div>'
+ . '<br/>'
. __('Please look at the bottom of this window.')
+ . '<div>'
. '<input id="pma_ignore_errors_popup" type="submit" value="'
. __('Ignore')
- . '" style="float: right; margin: 20px;">'
+ . '" class="floatright" style="margin-top: 20px;">'
. '<input id="pma_ignore_all_errors_popup" type="submit" value="'
. __('Ignore All')
- . '" style="float: right; margin: 20px;">'
+ . '" class="floatright" style="margin-top: 20px;">'
. '</div></div>';
$js_messages['phpErrorsBeingSubmitted'] = '<div class="error">'
@@ -552,8 +594,15 @@ $js_messages['phpErrorsBeingSubmitted'] = '<div class="error">'
. '" width="16" height="16" alt="ajax clock"/>'
. '</div>';
+// For console
$js_messages['strConsoleRequeryConfirm'] = __('Execute this query again?');
$js_messages['strConsoleDeleteBookmarkConfirm'] = __('Do you really want to delete this bookmark?');
+$js_messages['strConsoleDebugError'] = __('Some error occurred while getting SQL debug info.');
+$js_messages['strConsoleDebugSummary'] = __('%s queries executed %s times in %s seconds.');
+$js_messages['strConsoleDebugArgsSummary'] = __('%s argument(s) passed');
+$js_messages['strConsoleDebugShowArgs'] = __('Show arguments');
+$js_messages['strConsoleDebugHideArgs'] = __('Hide arguments');
+$js_messages['strConsoleDebugTimeTaken'] = __('Time taken:');
$js_messages['strNoLocalStorage'] = __('Your web browser does not support local storage of settings or the quota limit has been reached, some features may not work properly for you. In Safari, such problem is commonly caused by "Private Mode Browsing".');
echo "var PMA_messages = new Array();\n";
@@ -611,29 +660,29 @@ PMA_printJsValue(
PMA_printJsValue(
"$.datepicker.regional['']['monthNamesShort']",
array(
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Jan'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Feb'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Mar'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Apr'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
_pgettext('Short month name', 'May'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Jun'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Jul'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Aug'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Sep'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Oct'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Nov'),
-/* l10n: Short month name */
+ /* l10n: Short month name */
__('Dec')
)
);
@@ -652,38 +701,38 @@ PMA_printJsValue(
PMA_printJsValue(
"$.datepicker.regional['']['dayNamesShort']",
array(
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Sun'),
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Mon'),
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Tue'),
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Wed'),
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Thu'),
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Fri'),
-/* l10n: Short week day name */
+ /* l10n: Short week day name */
__('Sat')
)
);
PMA_printJsValue(
"$.datepicker.regional['']['dayNamesMin']",
array(
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('Su'),
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('Mo'),
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('Tu'),
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('We'),
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('Th'),
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('Fr'),
-/* l10n: Minimal week day name */
+ /* l10n: Minimal week day name */
__('Sa')
)
);
@@ -716,3 +765,33 @@ PMA_printJsValue("$.timepicker.regional['']['secondText']", __('Second'));
?>
$.extend($.timepicker._defaults, $.timepicker.regional['']);
} /* if ($.timepicker) */
+
+<?php
+/* Form validation */
+
+echo "function extendingValidatorMessages() {\n";
+echo "$.extend($.validator.messages, {\n";
+/* Default validation functions */
+PMA_printJsValueForFormValidation('required', __('This field is required'));
+PMA_printJsValueForFormValidation('remote', __('Please fix this field'));
+PMA_printJsValueForFormValidation('email', __('Please enter a valid email address'));
+PMA_printJsValueForFormValidation('url', __('Please enter a valid URL'));
+PMA_printJsValueForFormValidation('date', __('Please enter a valid date'));
+PMA_printJsValueForFormValidation('dateISO', __('Please enter a valid date ( ISO )'));
+PMA_printJsValueForFormValidation('number', __('Please enter a valid number'));
+PMA_printJsValueForFormValidation('creditcard', __('Please enter a valid credit card number'));
+PMA_printJsValueForFormValidation('digits', __('Please enter only digits'));
+PMA_printJsValueForFormValidation('equalTo', __('Please enter the same value again'));
+PMA_printJsValueForFormValidation('maxlength', __('Please enter no more than {0} characters'), true);
+PMA_printJsValueForFormValidation('minlength', __('Please enter at least {0} characters'), true);
+PMA_printJsValueForFormValidation('rangelength', __('Please enter a value between {0} and {1} characters long'), true);
+PMA_printJsValueForFormValidation('range', __('Please enter a value between {0} and {1}'), true);
+PMA_printJsValueForFormValidation('max', __('Please enter a value less than or equal to {0}'), true);
+PMA_printJsValueForFormValidation('min', __('Please enter a value greater than or equal to {0}'), true);
+/* customed functions */
+PMA_printJsValueForFormValidation('validationFunctionForDateTime', __('Please enter a valid date or time'), true);
+PMA_printJsValueForFormValidation('validationFunctionForHex', __('Please enter a valid HEX input'), true);
+PMA_printJsValueForFormValidation('validationFunctionForFuns', __('Error'), true, false);
+echo "\n});";
+echo "\n} /* if ($.validator) */";
+?>
diff --git a/js/microhistory.js b/js/microhistory.js
new file mode 100644
index 0000000000..60bb207147
--- /dev/null
+++ b/js/microhistory.js
@@ -0,0 +1,331 @@
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * An implementation of a client-side page cache.
+ * This object also uses the cache to provide a simple microhistory,
+ * that is the ability to use the back and forward buttons in the browser
+ */
+PMA_MicroHistory = {
+ /**
+ * @var int The maximum number of pages to keep in the cache
+ */
+ MAX: 6,
+ /**
+ * @var object A hash used to prime the cache with data about the initially
+ * loaded page. This is set in the footer, and then loaded
+ * by a double-queued event further down this file.
+ */
+ primer: {},
+ /**
+ * @var array Stores the content of the cached pages
+ */
+ pages: [],
+ /**
+ * @var int The index of the currently loaded page
+ * This is used to know at which point in the history we are
+ */
+ current: 0,
+ /**
+ * Saves a new page in the cache
+ *
+ * @param string hash The hash part of the url that is being loaded
+ * @param array scripts A list of scripts that is required for the page
+ * @param string menu A hash that links to a menu stored
+ * in a dedicated menu cache
+ * @param array params A list of parameters used by PMA_commonParams()
+ * @param string rel A relationship to the current page:
+ * 'samepage': Forces the response to be treated as
+ * the same page as the current one
+ * 'newpage': Forces the response to be treated as
+ * a new page
+ * undefined: Default behaviour, 'samepage' if the
+ * selflinks of the two pages are the same.
+ * 'newpage' otherwise
+ *
+ * @return void
+ */
+ add: function (hash, scripts, menu, params, rel) {
+ if (this.pages.length > PMA_MicroHistory.MAX) {
+ // Trim the cache, to the maximum number of allowed entries
+ // This way we will have a cached menu for every page
+ for (var i = 0; i < this.pages.length - this.MAX; i++) {
+ delete this.pages[i];
+ }
+ }
+ while (this.current < this.pages.length) {
+ // trim the cache if we went back in the history
+ // and are now going forward again
+ this.pages.pop();
+ }
+ if (rel === 'newpage' ||
+ (
+ typeof rel === 'undefined' && (
+ typeof this.pages[this.current - 1] === 'undefined' ||
+ this.pages[this.current - 1].hash !== hash
+ )
+ )
+ ) {
+ this.pages.push({
+ hash: hash,
+ content: $('#page_content').html(),
+ scripts: scripts,
+ selflink: $('#selflink').html(),
+ menu: menu,
+ params: params
+ });
+ PMA_SetUrlHash(this.current, hash);
+ this.current++;
+ }
+ },
+ /**
+ * Restores a page from the cache. This is called when the hash
+ * part of the url changes and it's structure appears to be valid
+ *
+ * @param string index Which page from the history to load
+ *
+ * @return void
+ */
+ navigate: function (index) {
+ if (typeof this.pages[index] === 'undefined' ||
+ typeof this.pages[index].content === 'undefined' ||
+ typeof this.pages[index].menu === 'undefined' ||
+ ! PMA_MicroHistory.menus.get(this.pages[index].menu)
+ ) {
+ PMA_ajaxShowMessage(
+ '<div class="error">' + PMA_messages.strInvalidPage + '</div>',
+ false
+ );
+ } else {
+ AJAX.active = true;
+ var record = this.pages[index];
+ AJAX.scriptHandler.reset(function () {
+ $('#page_content').html(record.content);
+ $('#selflink').html(record.selflink);
+ PMA_MicroHistory.menus.replace(PMA_MicroHistory.menus.get(record.menu));
+ PMA_commonParams.setAll(record.params);
+ AJAX.scriptHandler.load(record.scripts);
+ PMA_MicroHistory.current = ++index;
+ });
+ }
+ },
+ /**
+ * Resaves the content of the current page in the cache.
+ * Necessary in order not to show the user some outdated version of the page
+ *
+ * @return void
+ */
+ update: function () {
+ var page = this.pages[this.current - 1];
+ if (page) {
+ page.content = $('#page_content').html();
+ }
+ },
+ /**
+ * @var object Dedicated menu cache
+ */
+ menus: {
+ /**
+ * Returns the number of items in an associative array
+ *
+ * @return int
+ */
+ size: function (obj) {
+ var size = 0, key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ size++;
+ }
+ }
+ return size;
+ },
+ /**
+ * @var hash Stores the content of the cached menus
+ */
+ data: {},
+ /**
+ * Saves a new menu in the cache
+ *
+ * @param string hash The hash (trimmed md5) of the menu to be saved
+ * @param string content The HTML code of the menu to be saved
+ *
+ * @return void
+ */
+ add: function (hash, content) {
+ if (this.size(this.data) > PMA_MicroHistory.MAX) {
+ // when the cache grows, we remove the oldest entry
+ var oldest, key, init = 0;
+ for (var i in this.data) {
+ if (this.data[i]) {
+ if (! init || this.data[i].timestamp.getTime() < oldest.getTime()) {
+ oldest = this.data[i].timestamp;
+ key = i;
+ init = 1;
+ }
+ }
+ }
+ delete this.data[key];
+ }
+ this.data[hash] = {
+ content: content,
+ timestamp: new Date()
+ };
+ },
+ /**
+ * Retrieves a menu given its hash
+ *
+ * @param string hash The hash of the menu to be retrieved
+ *
+ * @return string
+ */
+ get: function (hash) {
+ if (this.data[hash]) {
+ return this.data[hash].content;
+ } else {
+ // This should never happen as long as the number of stored menus
+ // is larger or equal to the number of pages in the page cache
+ return '';
+ }
+ },
+ /**
+ * Prepares part of the parameter string used during page requests,
+ * this is necessary to tell the server which menus we have in the cache
+ *
+ * @return string
+ */
+ getRequestParam: function () {
+ var param = '';
+ var menuHashes = [];
+ for (var i in this.data) {
+ menuHashes.push(i);
+ }
+ var menuHashesParam = menuHashes.join('-');
+ if (menuHashesParam) {
+ param = '&menuHashes=' + menuHashesParam;
+ }
+ return param;
+ },
+ /**
+ * Replaces the menu with new content
+ *
+ * @return void
+ */
+ replace: function (content) {
+ $('#floating_menubar').html(content)
+ // Remove duplicate wrapper
+ // TODO: don't send it in the response
+ .children().first().remove();
+ $('#topmenu').menuResizer(PMA_mainMenuResizerCallback);
+ }
+ }
+};
+
+/**
+ * URL hash management module.
+ * Allows direct bookmarking and microhistory.
+ */
+PMA_SetUrlHash = (function (jQuery, window) {
+ "use strict";
+ /**
+ * Indictaes whether we have already completed
+ * the initialisation of the hash
+ *
+ * @access private
+ */
+ var ready = false;
+ /**
+ * Stores a hash that needed to be set when we were not ready
+ *
+ * @access private
+ */
+ var savedHash = "";
+ /**
+ * Flag to indicate if the change of hash was triggered
+ * by a user pressing the back/forward button or if
+ * the change was triggered internally
+ *
+ * @access private
+ */
+ var userChange = true;
+
+ // Fix favicon disappearing in Firefox when setting location.hash
+ function resetFavicon() {
+ if (navigator.userAgent.indexOf('Firefox') > -1) {
+ // Move the link tags for the favicon to the bottom
+ // of the head element to force a reload of the favicon
+ $('head > link[href=favicon\\.ico]').appendTo('head');
+ }
+ }
+
+ /**
+ * Sets the hash part of the URL
+ *
+ * @access public
+ */
+ function setUrlHash(index, hash) {
+ /*
+ * Known problem:
+ * Setting hash leads to reload in webkit:
+ * http://www.quirksmode.org/bugreports/archives/2005/05/Safari_13_visual_anomaly_with_windowlocationhref.html
+ *
+ * so we expect that users are not running an ancient Safari version
+ */
+
+ userChange = false;
+ if (ready) {
+ window.location.hash = "PMAURL-" + index + ":" + hash;
+ resetFavicon();
+ } else {
+ savedHash = "PMAURL-" + index + ":" + hash;
+ }
+ }
+ /**
+ * Start initialisation
+ */
+ if (window.location.hash.substring(0, 8) == '#PMAURL-') {
+ // We have a valid hash, let's redirect the user
+ // to the page that it's pointing to
+ var colon_position = window.location.hash.indexOf(':');
+ var questionmark_position = window.location.hash.indexOf('?');
+ if (colon_position != -1 && questionmark_position != -1 && colon_position < questionmark_position) {
+ var hash_url = window.location.hash.substring(colon_position + 1, questionmark_position);
+ if (PMA_gotoWhitelist.indexOf(hash_url) != -1) {
+ window.location = window.location.hash.substring(
+ colon_position + 1
+ );
+ }
+ }
+ } else {
+ // We don't have a valid hash, so we'll set it up
+ // when the page finishes loading
+ jQuery(function () {
+ /* Check if we should set URL */
+ if (savedHash !== "") {
+ window.location.hash = savedHash;
+ savedHash = "";
+ resetFavicon();
+ }
+ // Indicate that we're done initialising
+ ready = true;
+ });
+ }
+ /**
+ * Register an event handler for when the url hash changes
+ */
+ jQuery(function () {
+ jQuery(window).hashchange(function () {
+ if (userChange === false) {
+ // Ignore internally triggered hash changes
+ userChange = true;
+ } else if (/^#PMAURL-\d+:/.test(window.location.hash)) {
+ // Change page if the hash changed was triggered by a user action
+ var index = window.location.hash.substring(
+ 8, window.location.hash.indexOf(':')
+ );
+ PMA_MicroHistory.navigate(index);
+ }
+ });
+ });
+ /**
+ * Publicly exposes a reference to the otherwise private setUrlHash function
+ */
+ return setUrlHash;
+})(jQuery, window); \ No newline at end of file
diff --git a/js/navigation.js b/js/navigation.js
index b123600808..d1b6872ce4 100644
--- a/js/navigation.js
+++ b/js/navigation.js
@@ -68,11 +68,8 @@ function loadChildNodes(isNode, $expandElem, callback) {
})
.slideDown('slow');
}
- if (data._debug){
- $('#session_debug').replaceWith(data._debug);
- }
if (data._errors) {
- $errors = $(data._errors);
+ var $errors = $(data._errors);
if ($errors.children().length > 0) {
$('#pma_errors').replaceWith(data._errors);
}
@@ -86,7 +83,7 @@ function loadChildNodes(isNode, $expandElem, callback) {
} else {
var $throbber = $expandElem.find('img.throbber');
$throbber.hide();
- $icon = $expandElem.find('img.ic_b_plus');
+ var $icon = $expandElem.find('img.ic_b_plus');
$icon.show();
PMA_ajaxShowMessage(data.error, false);
}
@@ -122,7 +119,7 @@ function collapseTreeNode($expandElem) {
*/
function traverseNavigationForPaths() {
var params = {
- pos: $('#pma_navigation_tree div.dbselector select').val()
+ pos: $('#pma_navigation_tree').find('div.dbselector select').val()
};
if ($('#navi_db_select').length) {
return params;
@@ -204,7 +201,7 @@ $(function () {
// reload icon object
var $icon = $(this).find('img');
// source of the hidden throbber icon
- var icon_throbber_src = $('#pma_navigation .throbber').attr('src');
+ var icon_throbber_src = $('#pma_navigation').find('.throbber').attr('src');
// source of the reload icon
var icon_reload_src = $icon.attr('src');
// replace the source of the reload icon with the one for throbber
@@ -217,6 +214,10 @@ $(function () {
});
$(document).on("change", '#navi_db_select', function (event) {
+ if (! $(this).val()) {
+ PMA_commonParams.set('db', '');
+ PMA_reloadNavigation();
+ }
$(this).closest('form').trigger('submit');
});
@@ -226,7 +227,7 @@ $(function () {
*/
$(document).on('click', '#pma_navigation_collapse', function (event) {
event.preventDefault();
- $('#pma_navigation_tree a.expander').each(function() {
+ $('#pma_navigation_tree').find('a.expander').each(function() {
var $icon = $(this).find('img');
if ($icon.is('.ic_b_minus')) {
$(this).click();
@@ -347,13 +348,12 @@ $(function () {
dialog.editorDialog(1, $(this));
});
- /** Execute Routines */
+ /** Edit Routines, Triggers or Events */
$(document).on('click', 'li.procedure > a.ajax, li.function > a.ajax', function (event) {
event.preventDefault();
var dialog = new RTE.object('routine');
- dialog.executeDialog($(this));
+ dialog.editorDialog(0, $(this));
});
- /** Edit Triggers and Events */
$(document).on('click', 'li.trigger > a.ajax', function (event) {
event.preventDefault();
var dialog = new RTE.object('trigger');
@@ -365,15 +365,16 @@ $(function () {
dialog.editorDialog(0, $(this));
});
- /** Edit Routines */
+ /** Execute Routines */
$(document).on('click', 'li.procedure div a.ajax img,' +
' li.function div a.ajax img', function (event) {
event.preventDefault();
var dialog = new RTE.object('routine');
- dialog.editorDialog(0, $(this).parent());
+ dialog.executeDialog($(this).parent());
});
/** Export Triggers and Events */
- $(document).on('click', 'li.trigger div:eq(1) a.ajax img, li.event div:eq(1) a.ajax img', function (event) {
+ $(document).on('click', 'li.trigger div:eq(1) a.ajax img,' +
+ ' li.event div:eq(1) a.ajax img', function (event) {
event.preventDefault();
var dialog = new RTE.object();
dialog.exportDialog($(this).parent());
@@ -487,7 +488,7 @@ $(function () {
cache: false,
type: 'POST',
data: {
- favorite_tables: (isStorageSupported('localStorage'))
+ favorite_tables: (isStorageSupported('localStorage') && typeof window.localStorage.favorite_tables !== 'undefined')
? window.localStorage.favorite_tables
: ''
},
@@ -519,8 +520,8 @@ $(function () {
storage.removeItem('navTreePaths');
});
// Initialize if no previous state is defined
- if ($('#pma_navigation_tree_content').length
- && typeof storage.navTreePaths === 'undefined'
+ if ($('#pma_navigation_tree_content').length &&
+ typeof storage.navTreePaths === 'undefined'
) {
navTreeStateUpdate();
} else if (PMA_commonParams.get('server') === storage.server &&
@@ -578,7 +579,7 @@ function expandTreeNode($expandElem, callback) {
}
$children.promise().done(navTreeStateUpdate);
} else {
- var $throbber = $('#pma_navigation .throbber')
+ var $throbber = $('#pma_navigation').find('.throbber')
.first()
.clone()
.css({visibility: 'visible', display: 'block'})
@@ -648,28 +649,16 @@ function PMA_showCurrentNavigation() {
.removeClass('selected');
if (db) {
var $dbItem = findLoadedItem(
- $('#pma_navigation_tree > div'), db, 'database', !table
+ $('#pma_navigation_tree').find('> div'), db, 'database', !table
);
- if ($dbItem) {
- var $expander = $dbItem.children('div:first').children('a.expander');
- // if not loaded or loaded but collapsed
- if (! $expander.hasClass('loaded') ||
- $expander.find('img').is('.ic_b_plus')
- ) {
- expandTreeNode($expander, function () {
- handleTableOrDb(table, $dbItem);
- });
- } else {
- handleTableOrDb(table, $dbItem);
- }
- } else if ($('#navi_db_select').length
- && $('option:selected', $('#navi_db_select')).length
+ if ($('#navi_db_select').length &&
+ $('option:selected', $('#navi_db_select')).length
) {
if (! PMA_selectCurrentDb()) {
return;
}
// If loaded database in navigation is not same as current one
- if ( $('#pma_navigation_tree_content span.loaded_db:first').text()
+ if ($('#pma_navigation_tree_content').find('span.loaded_db:first').text()
!== $('#navi_db_select').val()
) {
loadChildNodes(false, $('option:selected', $('#navi_db_select')), function (data) {
@@ -680,7 +669,21 @@ function PMA_showCurrentNavigation() {
} else {
handleTableOrDb(table, $('#pma_navigation_tree_content'));
}
+ } else if ($dbItem) {
+ var $expander = $dbItem.children('div:first').children('a.expander');
+ // if not loaded or loaded but collapsed
+ if (! $expander.hasClass('loaded') ||
+ $expander.find('img').is('.ic_b_plus')
+ ) {
+ expandTreeNode($expander, function () {
+ handleTableOrDb(table, $dbItem);
+ });
+ } else {
+ handleTableOrDb(table, $dbItem);
+ }
}
+ } else if ($('#navi_db_select').length && $('#navi_db_select').val()) {
+ $('#navi_db_select').val('').hide().trigger('change');
}
PMA_showFullName($('#pma_navigation_tree'));
@@ -725,7 +728,7 @@ function PMA_showCurrentNavigation() {
}
// taverse up and expand and parent navigation groups
$li.parents('.navGroup').each(function () {
- $cont = $(this).children('div.list_container');
+ var $cont = $(this).children('div.list_container');
if (! $cont.is(':visible')) {
$(this)
.children('div:first')
@@ -769,7 +772,7 @@ function PMA_showCurrentNavigation() {
.children('div:first')
.children('a.expander');
if (! $expander.hasClass('loaded')) {
- loadAndShowTableOrView($expander, $containers[index], itemName);
+ loadAndShowTableOrView($expander, $containers[index], itemName);
}
});
// else if no subContainers
@@ -778,7 +781,7 @@ function PMA_showCurrentNavigation() {
.children('div:first')
.children('a.expander');
if (! $expander.hasClass('loaded')) {
- loadAndShowTableOrView($expander, $dbItem, itemName);
+ loadAndShowTableOrView($expander, $dbItem, itemName);
}
}
}
@@ -820,6 +823,46 @@ function PMA_showCurrentNavigation() {
}
/**
+ * Disable navigation panel settings
+ *
+ * @return void
+ */
+function PMA_disableNaviSettings() {
+ $('#pma_navigation_settings_icon').addClass('hide');
+ $('#pma_navigation_settings').remove();
+}
+
+/**
+ * Ensure that navigation panel settings is properly setup.
+ * If not, set it up
+ *
+ * @return void
+ */
+function PMA_ensureNaviSettings(selflink) {
+ $('#pma_navigation_settings_icon').removeClass('hide');
+
+ if (!$('#pma_navigation_settings').length) {
+ var params = {
+ getNaviSettings: true
+ };
+ var url = $('#pma_navigation').find('a.navigation_url').attr('href');
+ $.post(url, params, function (data) {
+ if (typeof data !== 'undefined' && data.success) {
+ $('#pma_navi_settings_container').html(data.message);
+ setupRestoreField();
+ setupValidation();
+ setupConfigTabs();
+ $('#pma_navigation_settings').find('form').attr('action', selflink);
+ } else {
+ PMA_ajaxShowMessage(data.error);
+ }
+ });
+ } else {
+ $('#pma_navigation_settings').find('form').attr('action', selflink);
+ }
+}
+
+/**
* Reloads the whole navigation tree while preserving its state
*
* @param function the callback function
@@ -829,7 +872,8 @@ function PMA_showCurrentNavigation() {
*/
function PMA_reloadNavigation(callback, paths) {
var params = {
- reload: true
+ reload: true,
+ no_debug: true
};
paths = paths || traverseNavigationForPaths();
$.extend(params, paths);
@@ -862,13 +906,19 @@ function PMA_reloadNavigation(callback, paths) {
}
function PMA_selectCurrentDb() {
- if ($('#navi_db_select').length) {
- $('#navi_db_select').val(PMA_commonParams.get('db'));
- if ($('#navi_db_select').val() !== PMA_commonParams.get('db')) {
- return false;
- }
- return true;
+ var $naviDbSelect = $('#navi_db_select');
+
+ if (!$naviDbSelect.length) {
+ return false;
}
+
+ if (PMA_commonParams.get('db')) { // db selected
+ $naviDbSelect.show();
+ }
+
+ $naviDbSelect.val(PMA_commonParams.get('db'));
+ return $naviDbSelect.val() === PMA_commonParams.get('db');
+
}
/**
diff --git a/js/normalization.js b/js/normalization.js
index d23adf6ea9..5ac085f8ba 100644
--- a/js/normalization.js
+++ b/js/normalization.js
@@ -13,6 +13,7 @@
var normalizeto = '1nf';
var primary_key;
+var data_parsed = null;
function appendHtmlColumnsList()
{
$.get(
@@ -45,21 +46,21 @@ function goTo3NFStep1(newTables)
"tables": newTables,
"step": '3.1'
}, function(data) {
- $("#page_content h3").html(PMA_messages.str3NFNormalization);
- $("#mainContent legend").html(data.legendText);
- $("#mainContent h4").html(data.headText);
- $("#mainContent p").html(data.subText);
- $("#mainContent #extra").html(data.extra);
- $("#extra form").each(function() {
- form_id = $(this).attr('id');
- colname = $(this).data('colname');
- $("#"+form_id+" input[value='"+colname+"']").next().remove();
- $("#"+form_id+" input[value='"+colname+"']").remove();
+ $("#page_content").find("h3").html(PMA_messages.str3NFNormalization);
+ $("#mainContent").find("legend").html(data.legendText);
+ $("#mainContent").find("h4").html(data.headText);
+ $("#mainContent").find("p").html(data.subText);
+ $("#mainContent").find("#extra").html(data.extra);
+ $("#extra").find("form").each(function() {
+ var form_id = $(this).attr('id');
+ var colname = $(this).data('colname');
+ $("#" + form_id + " input[value='" + colname + "']").next().remove();
+ $("#" + form_id + " input[value='" + colname + "']").remove();
});
- $("#mainContent #newCols").html('');
+ $("#mainContent").find("#newCols").html('');
$('.tblFooters').html('');
if (data.subText !== "") {
- $('.tblFooters').html('<input type="button" onClick="processDependencies(\'\', true);" value="'+PMA_messages.strDone+'"/>');
+ $('.tblFooters').html('<input type="button" onClick="processDependencies(\'\', true);" value="' + PMA_messages.strDone + '"/>');
}
}
);
@@ -81,7 +82,7 @@ function goTo2NFStep1() {
$("#mainContent #extra").html(data.extra);
$("#mainContent #newCols").html('');
if (data.subText !== '') {
- $('.tblFooters').html('<input type="submit" value="'+PMA_messages.strDone+'" onclick="processDependencies(\''+data.primary_key+'\');">');
+ $('.tblFooters').html('<input type="submit" value="' + PMA_messages.strDone + '" onclick="processDependencies(\'' + data.primary_key + '\');">');
} else {
if (normalizeto === '3nf') {
$("#mainContent #newCols").html(PMA_messages.strToNextStep);
@@ -127,7 +128,7 @@ function goToStep4()
$("#mainContent #newCols").html('');
$('.tblFooters').html('');
for(var pk in primary_key) {
- $("#extra input[value='"+primary_key[pk]+"']").attr("disabled","disabled");
+ $("#extra input[value='" + primary_key[pk] + "']").attr("disabled","disabled");
}
}
);
@@ -152,7 +153,7 @@ function goToStep3()
$('.tblFooters').html('');
primary_key = $.parseJSON(data.primary_key);
for(var pk in primary_key) {
- $("#extra input[value='"+primary_key[pk]+"']").attr("disabled","disabled");
+ $("#extra input[value='" + primary_key[pk] + "']").attr("disabled","disabled");
}
}
);
@@ -198,7 +199,7 @@ function goTo2NFFinish(pd)
{
var tables = {};
for (var dependson in pd) {
- tables[dependson] = $('#extra input[name="'+dependson+'"]').val();
+ tables[dependson] = $('#extra input[name="' + dependson + '"]').val();
}
datastring = {"token": PMA_commonParams.get('token'),
"ajax_request": true,
@@ -240,7 +241,7 @@ function goTo3NFFinish(newTables)
{
for (var table in newTables) {
for (var newtbl in newTables[table]) {
- updatedname = $('#extra input[name="'+newtbl+'"]').val();
+ var updatedname = $('#extra input[name="' + newtbl + '"]').val();
newTables[table][updatedname] = newTables[table][newtbl];
if (updatedname !== newtbl) {
delete newTables[table][newtbl];
@@ -279,7 +280,7 @@ var backup = '';
function goTo2NFStep2(pd, primary_key)
{
$("#newCols").html('');
- $("#mainContent legend").html(PMA_messages.strStep+' 2.2 '+PMA_messages.strConfirmPd);
+ $("#mainContent legend").html(PMA_messages.strStep + ' 2.2 ' + PMA_messages.strConfirmPd);
$("#mainContent h4").html(PMA_messages.strSelectedPd);
$("#mainContent p").html(PMA_messages.strPdHintNote);
var extra = '<div class="dependencies_box">';
@@ -287,11 +288,11 @@ function goTo2NFStep2(pd, primary_key)
for (var dependson in pd) {
if (dependson !== primary_key) {
pdFound = true;
- extra += '<p class="displayblock desc">'+escapeHtml(dependson) +" -> "+escapeHtml(pd[dependson].toString())+'</p>';
+ extra += '<p class="displayblock desc">' + escapeHtml(dependson) + " -> " + escapeHtml(pd[dependson].toString()) + '</p>';
}
}
if(!pdFound) {
- extra += '<p class="displayblock desc">'+PMA_messages.strNoPdSelected+'</p>';
+ extra += '<p class="displayblock desc">' + PMA_messages.strNoPdSelected + '</p>';
extra += '</div>';
} else {
extra += '</div>';
@@ -316,7 +317,7 @@ function goTo2NFStep2(pd, primary_key)
});
}
$("#mainContent #extra").html(extra);
- $('.tblFooters').html('<input type="button" value="'+PMA_messages.strBack+'" id="backEditPd"/><input type="button" id="goTo2NFFinish" value="'+PMA_messages.strGo+'"/>');
+ $('.tblFooters').html('<input type="button" value="' + PMA_messages.strBack + '" id="backEditPd"/><input type="button" id="goTo2NFFinish" value="' + PMA_messages.strGo + '"/>');
$("#goTo2NFFinish").click(function(){
goTo2NFFinish(pd);
});
@@ -325,7 +326,7 @@ function goTo2NFStep2(pd, primary_key)
function goTo3NFStep2(pd, tablesTds)
{
$("#newCols").html('');
- $("#mainContent legend").html(PMA_messages.strStep+' 3.2 '+PMA_messages.strConfirmTd);
+ $("#mainContent legend").html(PMA_messages.strStep + ' 3.2 ' + PMA_messages.strConfirmTd);
$("#mainContent h4").html(PMA_messages.strSelectedTd);
$("#mainContent p").html(PMA_messages.strPdHintNote);
var extra = '<div class="dependencies_box">';
@@ -335,12 +336,12 @@ function goTo3NFStep2(pd, tablesTds)
dependson = tablesTds[table][i];
if (dependson !== '' && dependson !== table) {
pdFound = true;
- extra += '<p class="displayblock desc">'+escapeHtml(dependson) +" -> "+escapeHtml(pd[dependson].toString())+'</p>';
+ extra += '<p class="displayblock desc">' + escapeHtml(dependson) + " -> " + escapeHtml(pd[dependson].toString()) + '</p>';
}
}
}
if(!pdFound) {
- extra += '<p class="displayblock desc">'+PMA_messages.strNoTdSelected+'</p>';
+ extra += '<p class="displayblock desc">' + PMA_messages.strNoTdSelected + '</p>';
extra += '</div>';
} else {
extra += '</div>';
@@ -366,7 +367,7 @@ function goTo3NFStep2(pd, tablesTds)
});
}
$("#mainContent #extra").html(extra);
- $('.tblFooters').html('<input type="button" value="'+PMA_messages.strBack+'" id="backEditPd"/><input type="button" id="goTo3NFFinish" value="'+PMA_messages.strGo+'"/>');
+ $('.tblFooters').html('<input type="button" value="' + PMA_messages.strBack + '" id="backEditPd"/><input type="button" id="goTo3NFFinish" value="' + PMA_messages.strGo + '"/>');
$("#goTo3NFFinish").click(function(){
if (!pdFound) {
goTo3NFFinish([]);
@@ -382,6 +383,7 @@ function processDependencies(primary_key, isTransitive)
var dependsOn;
pd[primary_key] = [];
$("#extra form").each(function() {
+ var tblname;
if (isTransitive === true) {
tblname = $(this).data('tablename');
primary_key = tblname;
@@ -390,11 +392,11 @@ function processDependencies(primary_key, isTransitive)
}
tablesTds[tblname].push(primary_key);
}
- form_id = $(this).attr('id');
- $('#'+form_id+' input[type=checkbox]:not(:checked)').removeAttr('checked');
+ var form_id = $(this).attr('id');
+ $('#' + form_id + ' input[type=checkbox]:not(:checked)').removeAttr('checked');
dependsOn = '';
- $('#'+form_id+' input[type=checkbox]:checked').each(function(){
- dependsOn += $(this).val()+', ';
+ $('#' + form_id + ' input[type=checkbox]:checked').each(function(){
+ dependsOn += $(this).val() + ', ';
$(this).attr("checked","checked");
});
if (dependsOn === '') {
@@ -425,8 +427,8 @@ function processDependencies(primary_key, isTransitive)
}
function moveRepeatingGroup(repeatingCols) {
- newTable = $("input[name=repeatGroupTable]").val();
- newColumn = $("input[name=repeatGroupColumn]").val();
+ var newTable = $("input[name=repeatGroupTable]").val();
+ var newColumn = $("input[name=repeatGroupColumn]").val();
if (!newTable) {
$("input[name=repeatGroupTable]").focus();
return false;
@@ -506,8 +508,8 @@ AJAX.registerOnload('normalization.js', function() {
$('#newCols').html(data.message);
$('.default_value').hide();
$('.enum_notice').hide();
- $('.tblFooters').html("<input type='submit' id='saveSplit' value='"+PMA_messages.strSave+"'/>" +
- "<input type='submit' id='cancelSplit' value='"+PMA_messages.strCancel+"' "+
+ $('.tblFooters').html("<input type='submit' id='saveSplit' value='" + PMA_messages.strSave + "'/>" +
+ "<input type='submit' id='cancelSplit' value='" + PMA_messages.strCancel + "' " +
"onclick=\"$('#newCols').html('');$(this).parent().html('')\"/>");
}
}
@@ -532,6 +534,7 @@ AJAX.registerOnload('normalization.js', function() {
"db": PMA_commonParams.get('db'),
"table": PMA_commonParams.get('table'),
"dropped_column": selectedCol,
+ "purge" : 1,
"sql_query": 'ALTER TABLE `' + PMA_commonParams.get('table') + '` DROP `' + selectedCol + '`;',
"is_js_confirmed": 1
},
@@ -567,8 +570,8 @@ AJAX.registerOnload('normalization.js', function() {
$('#newCols').html(data.message);
$('.default_value').hide();
$('.enum_notice').hide();
- $('.tblFooters').html("<input type='submit' id='saveNewPrimary' value='"+PMA_messages.strSave+"'/>" +
- "<input type='submit' id='cancelSplit' value='"+PMA_messages.strCancel+"' "+
+ $('.tblFooters').html("<input type='submit' id='saveNewPrimary' value='" + PMA_messages.strSave + "'/>" +
+ "<input type='submit' id='cancelSplit' value='" + PMA_messages.strCancel + "' " +
"onclick=\"$('#newCols').html('');$(this).parent().html('')\"/>");
} else {
PMA_ajaxShowMessage(data.error, false);
@@ -578,7 +581,7 @@ AJAX.registerOnload('normalization.js', function() {
return false;
});
$(".tblFooters").on("click", "#saveNewPrimary", function() {
- datastring = $('#newCols :input').serialize();
+ var datastring = $('#newCols :input').serialize();
datastring += "&field_key[0]=primary_0&ajax_request=1&do_save_data=1&field_where=last";
$.post("tbl_addfield.php", datastring, function(data) {
if (data.success === true) {
@@ -627,15 +630,15 @@ AJAX.registerOnload('normalization.js', function() {
});
if (repeatingCols !== '') {
- newColName = $("#extra input[type=checkbox]:checked:first").val();
+ var newColName = $("#extra input[type=checkbox]:checked:first").val();
repeatingCols = repeatingCols.slice(0, -2);
- confirmStr = PMA_sprintf(PMA_messages.strMoveRepeatingGroup, escapeHtml(repeatingCols), escapeHtml(PMA_commonParams.get('table')));
- confirmStr += '<input type="text" name="repeatGroupTable" placeholder="'+PMA_messages.strNewTablePlaceholder+'"/>'+
- '( '+escapeHtml(primary_key.toString())+', <input type="text" name="repeatGroupColumn" placeholder="'+PMA_messages.strNewColumnPlaceholder+'" value="'+escapeHtml(newColName)+'">)'+
+ var confirmStr = PMA_sprintf(PMA_messages.strMoveRepeatingGroup, escapeHtml(repeatingCols), escapeHtml(PMA_commonParams.get('table')));
+ confirmStr += '<input type="text" name="repeatGroupTable" placeholder="' + PMA_messages.strNewTablePlaceholder + '"/>' +
+ '( ' + escapeHtml(primary_key.toString()) + ', <input type="text" name="repeatGroupColumn" placeholder="' + PMA_messages.strNewColumnPlaceholder + '" value="' + escapeHtml(newColName) + '">)' +
'</ol>';
$("#newCols").html(confirmStr);
- $('.tblFooters').html('<input type="submit" value="'+PMA_messages.strCancel+'" onclick="$(\'#newCols\').html(\'\');$(\'#extra input[type=checkbox]\').removeAttr(\'checked\')"/>'+
- '<input type="submit" value="'+PMA_messages.strGo+'" onclick="moveRepeatingGroup(\''+repeatingCols+'\')"/>');
+ $('.tblFooters').html('<input type="submit" value="' + PMA_messages.strCancel + '" onclick="$(\'#newCols\').html(\'\');$(\'#extra input[type=checkbox]\').removeAttr(\'checked\')"/>' +
+ '<input type="submit" value="' + PMA_messages.strGo + '" onclick="moveRepeatingGroup(\'' + repeatingCols + '\')"/>');
}
});
$("#mainContent p").on("click", "#createPrimaryKey", function(event) {
@@ -665,19 +668,19 @@ AJAX.registerOnload('normalization.js', function() {
});
$("#mainContent").on("click", "#showPossiblePd", function(){
if($(this).hasClass('hideList')) {
- $(this).html('+ '+PMA_messages.strShowPossiblePd);
+ $(this).html('+ ' + PMA_messages.strShowPossiblePd);
$(this).removeClass('hideList');
$("#newCols").slideToggle("slow");
return false;
}
if($("#newCols").html() !== '') {
- $("#showPossiblePd").html('- '+PMA_messages.strHidePd);
+ $("#showPossiblePd").html('- ' + PMA_messages.strHidePd);
$("#showPossiblePd").addClass('hideList');
$("#newCols").slideToggle("slow");
return false;
}
$("#newCols").insertAfter("#mainContent h4");
- $("#newCols").html('<div class="center">'+PMA_messages.strLoading+'<br/>'+PMA_messages.strWaitForPd+'</div>');
+ $("#newCols").html('<div class="center">' + PMA_messages.strLoading + '<br/>' + PMA_messages.strWaitForPd + '</div>');
$.post(
"normalization.php",
{
@@ -687,7 +690,7 @@ AJAX.registerOnload('normalization.js', function() {
"table": PMA_commonParams.get('table'),
"findPdl": true
}, function(data) {
- $("#showPossiblePd").html('- '+PMA_messages.strHidePd);
+ $("#showPossiblePd").html('- ' + PMA_messages.strHidePd);
$("#showPossiblePd").addClass('hideList');
$("#newCols").html(data.message);
});
@@ -698,9 +701,9 @@ AJAX.registerOnload('normalization.js', function() {
var strColsRight = $(this).next().next().html();
var colsRight = strColsRight.split(',');
for (var i in colsRight) {
- $('form[data-colname="'+colsRight[i].trim()+'"] input[type="checkbox"]').prop('checked', false);
+ $('form[data-colname="' + colsRight[i].trim() + '"] input[type="checkbox"]').prop('checked', false);
for (var j in colsLeft) {
- $('form[data-colname="'+colsRight[i].trim()+'"] input[value="'+colsLeft[j].trim()+'"]').prop('checked', true);
+ $('form[data-colname="' + colsRight[i].trim() + '"] input[value="' + colsLeft[j].trim() + '"]').prop('checked', true);
}
}
});
diff --git a/js/page_settings.js b/js/page_settings.js
new file mode 100644
index 0000000000..c0055bed8c
--- /dev/null
+++ b/js/page_settings.js
@@ -0,0 +1,59 @@
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * @fileoverview function used for page-related settings
+ * @name Page-related settings
+ *
+ * @requires jQuery
+ * @requires jQueryUI
+ * @required js/functions.js
+ */
+
+function showSettings(selector) {
+ var buttons = {};
+ buttons[PMA_messages.strApply] = function() {
+ $('.config-form').submit();
+ };
+
+ buttons[PMA_messages.strCancel] = function () {
+ $(this).dialog('close');
+ };
+
+ // Keeping a clone to restore in case the user cancels the operation
+ var $clone = $(selector + ' .page_settings').clone(true);
+ $(selector)
+ .dialog({
+ title: PMA_messages.strPageSettings,
+ width: 700,
+ minHeight: 250,
+ modal: true,
+ open: function() {
+ $(this).dialog('option', 'maxHeight', $(window).height() - $(this).offset().top);
+ },
+ close: function() {
+ $(selector + ' .page_settings').replaceWith($clone);
+ },
+ buttons: buttons
+ });
+}
+
+function showPageSettings() {
+ showSettings('#page_settings_modal');
+}
+
+function showNaviSettings() {
+ showSettings('#pma_navigation_settings');
+}
+
+AJAX.registerTeardown('page_settings.js', function () {
+ $('#page_settings_icon').css('display', 'none');
+ $('#page_settings_icon').unbind('click');
+ $('#pma_navigation_settings_icon').unbind('click');
+});
+
+AJAX.registerOnload('page_settings.js', function () {
+ if ($('#page_settings_modal').length) {
+ $('#page_settings_icon').css('display', 'inline');
+ $('#page_settings_icon').bind('click', showPageSettings);
+ }
+ $('#pma_navigation_settings_icon').bind('click', showNaviSettings);
+});
diff --git a/js/pmd/designer_page.js b/js/pmd/designer_page.js
index 9c292e79da..7730fbdff6 100644
--- a/js/pmd/designer_page.js
+++ b/js/pmd/designer_page.js
@@ -91,19 +91,27 @@ function Delete_page(page_id, callback)
function Load_first_page(db, callback)
{
DesignerOfflineDB.loadAllObjects('pdf_pages', function (pages) {
+ var firstPage = null;
for (var i = 0; i < pages.length; i++) {
var page = pages[i];
if (page.db_name == db) {
- callback(page);
- return;
+ // give preference to a page having same name as the db
+ if (page.page_descr == db) {
+ callback(page);
+ return;
+ }
+ if (firstPage == null) {
+ firstPage = page;
+ }
}
}
+ callback(firstPage);
});
}
function Show_new_page_tables(check)
{
- var all_tables = $("#id_scroll_tab td input:checkbox");
+ var all_tables = $("#id_scroll_tab").find("td input:checkbox");
all_tables.prop('checked', check);
for (var tab = 0; tab < all_tables.length; tab++) {
var input = all_tables[tab];
@@ -115,7 +123,7 @@ function Show_new_page_tables(check)
}
}
selected_page = -1;
- $("#name-panel #page_name").text(PMA_messages.strUntitled);
+ $("#page_name").text(PMA_messages.strUntitled);
MarkUnsaved();
}
@@ -123,7 +131,7 @@ function Load_HTML_for_page(page_id)
{
Show_new_page_tables(false);
Load_page_objects(page_id, function (page, tbl_cords) {
- $("#name-panel #page_name").text(page.page_descr);
+ $("#name-panel").find("#page_name").text(page.page_descr);
MarkSaved();
for (var t = 0; t < tbl_cords.length; t++) {
var tb_id = db + '.' + tbl_cords[t].table_name;
diff --git a/js/pmd/history.js b/js/pmd/history.js
index 3fdfcfd793..9f70c03d46 100644
--- a/js/pmd/history.js
+++ b/js/pmd/history.js
@@ -10,22 +10,7 @@
var history_array = []; // Global array to store history objects
var select_field = []; // Global array to store informaation for columns which are used in select clause
var g_index;
-
-/**
- * function for panel, hides and shows toggle_container <div>,which is for history elements uses {@link JQuery}.
- *
- * @param index has value 1 or 0,decides wheter to hide toggle_container on load.
-**/
-
-function panel(index)
-{
- if (!index) {
- $(".toggle_container").hide();
- }
- $("h2.tiger").click(function () {
- $(this).toggleClass("active").next().slideToggle("slow");
- });
-}
+var vqb_editor = null;
/**
* To display details of objects(where,rename,Having,aggregate,groupby,orderby,having)
@@ -51,7 +36,7 @@ function detail(index)
str = 'GroupBy ' + history_array[index].get_column_name();
}
if (type == "OrderBy") {
- str = 'OrderBy ' + history_array[index].get_column_name();
+ str = 'OrderBy ' + history_array[index].get_column_name() + ' ' + history_array[index].get_obj().get_order();
}
if (type == "Having") {
str = 'Having ';
@@ -97,7 +82,7 @@ function display(init, finit)
str = ''; // string to store Html code for history tab
for (i = 0; i < history_array.length; i++) {
temp = history_array[i].get_tab(); //+ '.' + history_array[i].get_obj_no(); for Self JOIN
- str += '<h2 class="tiger"><a href="#">' + temp + '</a></h2>';
+ str += '<h3 class="tiger"><a href="#">' + temp + '</a></h3>';
str += '<div class="toggle_container">\n';
while ((history_array[i].get_tab()) == temp) { //+ '.' + history_array[i].get_obj_no()) == temp) {
str += '<div class="block"> <table width ="250">';
@@ -107,20 +92,27 @@ function display(init, finit)
} else {
str += '<img src="' + pmaThemeImage + 'pmd/and_icon.png" onclick="and_or(' + i + ')" title="AND"/></td>';
}
- str += '<td style="padding-left: 5px;" class="right">' + PMA_getImage('b_sbrowse.png', 'column name') + '</td><td width="175" style="padding-left: 5px">' + history_array[i].get_column_name();
+ str += '<td style="padding-left: 5px;" class="right">' + PMA_getImage('b_sbrowse.png', 'column name') + '</td>' +
+ '<td width="175" style="padding-left: 5px">' + history_array[i].get_column_name() + '<td>';
if (history_array[i].get_type() == "GroupBy" || history_array[i].get_type() == "OrderBy") {
- str += '</td><td class="center">' + PMA_getImage('s_info.png', detail(i)) + '<td title="' + detail(i) + '">' + history_array[i].get_type() + '</td></td><td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_delete(' + i + ')>' + PMA_getImage('b_drop.png', 'Delete') + '</td></tr></thead>';
+ str += '<td class="center">' + PMA_getImage('s_info.png', detail(i)) + '</td>' +
+ '<td title="' + detail(i) + '">' + history_array[i].get_type() + '</td>' +
+ '<td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_delete(' + i + ')>' + PMA_getImage('b_drop.png', PMA_messages.strDelete) + '</td>';
} else {
- str += '</td><td class="center">' + PMA_getImage('s_info.png', detail(i)) + '</td><td title="' + detail(i) + '">' + history_array[i].get_type() + '</td><td <td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_edit(' + i + ')>' + PMA_getImage('b_edit.png', PMA_messages.strEdit) + '</td><td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_delete(' + i + ')><img src="themes/original/img/b_drop.png" title="Delete"></td></tr></thead>';
+ str += '<td class="center">' + PMA_getImage('s_info.png', detail(i)) + '</td>' +
+ '<td title="' + detail(i) + '">' + history_array[i].get_type() + '</td>' +
+ '<td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_edit(' + i + ')>' + PMA_getImage('b_edit.png', PMA_messages.strEdit) + '</td>' +
+ '<td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_delete(' + i + ')>' + PMA_getImage('b_drop.png', PMA_messages.strDelete) + '</td>';
}
+ str += '</tr></thead>';
i++;
if (i >= history_array.length) {
break;
}
- str += '</table></div><br/>';
+ str += '</table></div>';
}
i--;
- str += '</div><br/>';
+ str += '</div>';
}
return str;
}
@@ -142,7 +134,7 @@ function and_or(index)
}
var existingDiv = document.getElementById('ab');
existingDiv.innerHTML = display(0, 0);
- panel(1);
+ $('#ab').accordion("refresh");
}
/**
@@ -163,7 +155,7 @@ function history_delete(index)
history_array.splice(index, 1);
var existingDiv = document.getElementById('ab');
existingDiv.innerHTML = display(0, 0);
- panel(1);
+ $('#ab').accordion("refresh");
}
/**
@@ -258,7 +250,7 @@ function edit(type)
}
var existingDiv = document.getElementById('ab');
existingDiv.innerHTML = display(0, 0);
- panel(1);
+ $('#ab').accordion("refresh");
}
/**
@@ -272,7 +264,7 @@ function edit(type)
*
**/
-function history(ncolumn_name, nobj, ntab, nobj_no, ntype)
+function history_obj(ncolumn_name, nobj, ntab, nobj_no, ntype)
{
var and_or;
var obj;
@@ -355,6 +347,21 @@ var where = function (nrelation_operator, nquery) {
this.setrelation_operator(nrelation_operator);
};
+/**
+ * Orderby object closure
+ *
+ * @param norder order, ASC or DESC
+ */
+var orderby = function(norder) {
+ var order;
+ this.set_order = function(norder) {
+ order = norder;
+ };
+ this.get_order = function() {
+ return order;
+ };
+ this.set_order(norder);
+};
/**
* Having object closure, makes an object with all information of where
@@ -510,10 +517,10 @@ function query_groupby()
var str = "";
for (i = 0; i < history_array.length;i++) {
if (history_array[i].get_type() == "GroupBy") {
- str += history_array[i].get_column_name() + ", ";
+ str += '`' + history_array[i].get_column_name() + "`, ";
}
}
- str = str.substr(0, str.length - 1);
+ str = str.substr(0, str.length - 2);
return str;
}
@@ -529,10 +536,10 @@ function query_having()
for (i = 0; i < history_array.length;i++) {
if (history_array[i].get_type() == "Having") {
if (history_array[i].get_obj().get_operator() != 'None') {
- and += history_array[i].get_obj().get_operator() + "(" + history_array[i].get_column_name() + " ) " + history_array[i].get_obj().getrelation_operator();
+ and += history_array[i].get_obj().get_operator() + "(`" + history_array[i].get_column_name() + "`) " + history_array[i].get_obj().getrelation_operator();
and += " " + history_array[i].get_obj().getquery() + ", ";
} else {
- and += history_array[i].get_column_name() + " " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ", ";
+ and += "`" + history_array[i].get_column_name() + "` " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ", ";
}
}
}
@@ -555,9 +562,12 @@ function query_orderby()
var i;
var str = "";
for (i = 0; i < history_array.length;i++) {
- if (history_array[i].get_type() == "OrderBy") { str += history_array[i].get_column_name() + " , "; }
+ if (history_array[i].get_type() == "OrderBy") {
+ str += "`" + history_array[i].get_column_name() + "` " +
+ history_array[i].get_obj().get_order() + ", ";
+ }
}
- str = str.substr(0, str.length - 1);
+ str = str.substr(0, str.length - 2);
return str;
}
@@ -575,10 +585,10 @@ function query_where()
for (i = 0; i < history_array.length;i++) {
if (history_array[i].get_type() == "Where") {
if (history_array[i].get_and_or() === 0) {
- and += "( " + history_array[i].get_column_name() + " " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ")";
+ and += "( `" + history_array[i].get_column_name() + "` " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ")";
and += " AND ";
} else {
- or += "( " + history_array[i].get_column_name() + " " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ")";
+ or += "( `" + history_array[i].get_column_name() + "` " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ")";
or += " OR ";
}
}
@@ -623,26 +633,6 @@ function check_rename(id_this)
return "";
}
-function gradient(id, level)
-{
- var box = document.getElementById(id);
- box.style.opacity = level;
- box.style.MozOpacity = level;
- box.style.KhtmlOpacity = level;
- box.style.filter = "alpha(opacity=" + level * 100 + ")";
- box.style.display = "block";
-}
-
-
-function fadein(id)
-{
- var level = 0;
- while (level <= 1) {
- setTimeout("gradient('" + id + "'," + level + ")", (level * 1000) + 10);
- level += 0.01;
- }
-}
-
/**
* This function builds from clause of query
* makes automatic joins.
@@ -674,7 +664,7 @@ function query_from()
from_array = unique(from_array);
tab_left = from_array;
temp = tab_left.shift();
- quer = temp;
+ quer = '`' + temp + '`';
tab_used.push(temp);
// if master table (key2) matches with tab used get all keys and check if tab_left matches
// after this check if master table (key2) matches with tab left then check if any foreign matches with master .
@@ -688,7 +678,7 @@ function query_from()
parts1 = contr[K][key][key2][key3][0].split(".");
if (found(tab_left, parts1[1]) > 0) {
query += "\n" + 'LEFT JOIN ';
- query += '`' + parts1[0] + '`.`' + parts1[1] + '` ON ';
+ query += '`' + parts1[1] + '` ON ';
query += '`' + parts[1] + '`.`' + key3 + '` = ';
query += '`' + parts1[1] + '`.`' + contr[K][key][key2][key3][1] + '` ';
t_tab_left.push(parts1[1]);
@@ -712,7 +702,7 @@ function query_from()
parts1 = contr[K][key][key2][key3][0].split(".");
if (found(tab_used, parts1[1]) > 0) {
query += "\n" + 'LEFT JOIN ';
- query += '`' + parts[0] + '`.`' + parts[1] + '` ON ';
+ query += '`' + parts[1] + '` ON ';
query += '`' + parts1[1] + '`.`' + contr[K][key][key2][key3][1] + '` = ';
query += '`' + parts[1] + '`.`' + key3 + '` ';
t_tab_left.push(parts[1]);
@@ -752,46 +742,91 @@ function build_query(formtitle, fadin)
{
var q_select = "SELECT ";
var temp;
- for (var i = 0;i < select_field.length; i++) {
- temp = check_aggregate(select_field[i]);
- if (temp !== "") {
- q_select += temp;
- temp = check_rename(select_field[i]);
- q_select += temp + ",";
- } else {
- temp = check_rename(select_field[i]);
- q_select += select_field[i] + temp + ",";
+ if (select_field.length > 0) {
+ for (var i = 0; i < select_field.length; i++) {
+ temp = check_aggregate(select_field[i]);
+ if (temp !== "") {
+ q_select += temp;
+ temp = check_rename(select_field[i]);
+ q_select += temp + ", ";
+ } else {
+ temp = check_rename(select_field[i]);
+ q_select += select_field[i] + temp + ", ";
+ }
}
- }
- q_select = q_select.substring(0, q_select.length - 1);
- q_select += " FROM " + query_from();
- if (query_where() !== "") {
- q_select += "\n WHERE";
- q_select += query_where();
- }
- if (query_groupby() !== "") { q_select += "\nGROUP BY " + query_groupby(); }
- if (query_having() !== "") { q_select += "\nHAVING " + query_having(); }
- if (query_orderby() !== "") { q_select += "\nORDER BY " + query_orderby(); }
- var box = document.getElementById('box');
- document.getElementById('filter').style.display = 'block';
- var btitle = document.getElementById('boxtitle');
- btitle.innerHTML = 'SELECT';//formtitle;
- if (fadin) {
- gradient("box", 0);
- fadein("box");
+ q_select = q_select.substring(0, q_select.length - 2);
} else {
- box.style.display = 'block';
+ q_select += "* ";
}
- document.getElementById('textSqlquery').innerHTML = q_select;
-}
-function closebox()
-{
- document.getElementById('box').style.display = 'none';
- document.getElementById('filter').style.display = 'none';
+ q_select += "\nFROM " + query_from();
+
+ var q_where = query_where();
+ if (q_where !== "") {
+ q_select += "\nWHERE " + q_where;
+ }
+
+ var q_groupby = query_groupby();
+ if (q_groupby !== "") {
+ q_select += "\nGROUP BY " + q_groupby;
+ }
+
+ var q_having = query_having();
+ if (q_having !== "") {
+ q_select += "\nHAVING " + q_having;
+ }
+
+ var q_orderby = query_orderby();
+ if (q_orderby !== "") {
+ q_select += "\nORDER BY " + q_orderby;
+ }
+
+ /**
+ * @var button_options Object containing options
+ * for jQueryUI dialog buttons
+ */
+ var button_options = {};
+ button_options[PMA_messages.strClose] = function () {
+ $(this).dialog("close");
+ };
+ button_options[PMA_messages.strSubmit] = function () {
+ if (vqb_editor) {
+ var $elm = $ajaxDialog.find('textarea');
+ vqb_editor.save();
+ $elm.val(vqb_editor.getValue());
+ }
+ $('#vqb_form').submit();
+ };
+
+ var $ajaxDialog = $('#box').dialog({
+ appendTo: '#page_content',
+ width: 500,
+ buttons: button_options,
+ modal: true,
+ title: 'SELECT'
+ });
+ // Attach syntax highlighted editor to query dialog
+ /**
+ * @var $elm jQuery object containing the reference
+ * to the query textarea.
+ */
+ var $elm = $ajaxDialog.find('textarea');
+ if (! vqb_editor) {
+ vqb_editor = PMA_getSQLEditor($elm);
+ }
+ if (vqb_editor) {
+ vqb_editor.setValue(q_select);
+ vqb_editor.focus();
+ } else {
+ $elm.val(q_select);
+ $elm.focus();
+ }
}
AJAX.registerTeardown('pmd/history.js', function () {
+ vqb_editor = null;
+ history_array = [];
+ select_field = [];
$("#ok_edit_rename").unbind('click');
$("#ok_edit_having").unbind('click');
$("#ok_edit_Aggr").unbind('click');
@@ -811,4 +846,5 @@ AJAX.registerOnload('pmd/history.js', function () {
$("#ok_edit_where").click(function() {
edit('Where');
});
-}); \ No newline at end of file
+ $('#ab').accordion({collapsible : true, active : 'none'});
+});
diff --git a/js/pmd/iecanvas.js b/js/pmd/iecanvas.js
index d478f15bf3..e2a6b52c1a 100644
--- a/js/pmd/iecanvas.js
+++ b/js/pmd/iecanvas.js
@@ -16,10 +16,10 @@ if (! isCanvasSupported()) {
el.parentNode.replaceChild(newEl, el);
el = newEl;
el.getContext = function () {
- if (this.cont) {
- return this.cont;
+ if (! this.cont) {
+ this.cont = new PMD_2D(this);
}
- return this.cont = new PMD_2D(this);
+ return this.cont;
};
el.style.width = el.attributes.width.nodeValue + "px";
diff --git a/js/pmd/init.js b/js/pmd/init.js
index 2719353716..ec779ea883 100644
--- a/js/pmd/init.js
+++ b/js/pmd/init.js
@@ -3,7 +3,7 @@
* Initialises the data required to run PMD, then fires it up.
*/
-var j_tabs, h_tabs, contr, server, db, token, selected_page, pmd_tables_enabled;
+var j_tabs, h_tabs, contr, display_field, server, db, token, selected_page, pmd_tables_enabled;
AJAX.registerTeardown('pmd/init.js', function () {
$(".trigger").unbind('click');
@@ -13,6 +13,7 @@ AJAX.registerOnload('pmd/init.js', function () {
$(".trigger").click(function () {
$(".panel").toggle("fast");
$(this).toggleClass("active");
+ $('#ab').accordion("refresh");
return false;
});
var tables_data = $.parseJSON($("#script_tables").html());
diff --git a/js/pmd/move.js b/js/pmd/move.js
index d58b0c1f83..ba4bbbbfca 100644
--- a/js/pmd/move.js
+++ b/js/pmd/move.js
@@ -17,6 +17,8 @@ AJAX.registerTeardown('pmd/move.js', function () {
if ($.FullScreen.supported) {
$(document).unbind($.FullScreen.prefix + 'fullscreenchange');
}
+
+ $('#selflink').show();
});
AJAX.registerOnload('pmd/move.js', function () {
@@ -26,15 +28,18 @@ AJAX.registerOnload('pmd/move.js', function () {
if (! $.FullScreen.isFullScreen()) {
$('#page_content').removeClass('content_fullscreen')
.css({'width': 'auto', 'height': 'auto'});
- var $img = $('#toggleFullscreen img');
- $img.attr('src', $img.data('enter'));
+ var $img = $('#toggleFullscreen').find('img');
var $span = $img.siblings('span');
$span.text($span.data('enter'));
+ $img.attr('src', $img.data('enter'))
+ .attr('title', $span.data('enter'));
}
});
} else {
$('#toggleFullscreen').hide();
}
+
+ $('#selflink').hide();
});
// Below is the function to bind onbeforeunload events with the content_frame as well as the top window.
@@ -177,7 +182,7 @@ function MouseMove(e)
if (ON_grid) {
new_x = parseInt(new_x / grid_size) * grid_size;
new_y = parseInt(new_y / grid_size) * grid_size;
- };
+ }
$cur_click.css('left', new_x + 'px');
$cur_click.css('top', new_y + 'px');
@@ -190,14 +195,15 @@ function MouseMove(e)
if (menu_moved) {
delta_x = -delta_x;
}
- var new_width = $('#layer_menu').width() + delta_x;
+ var $layer_menu = $('#layer_menu');
+ var new_width = $layer_menu.width() + delta_x;
if (new_width < 150) {
new_width = 150;
}
else {
dx = e.pageX;
}
- $('#layer_menu').width(new_width);
+ $layer_menu.width(new_width);
}
if (ON_relation || ON_display_field) {
@@ -244,6 +250,52 @@ function Osn_tab_pos()
osn_tab_height = parseInt(document.getElementById('osn_tab').style.height, 10);
}
+function setDefaultValuesFromSavedState()
+{
+ if ($('#angular_direct_button').attr('class') === 'M_butt') {
+ ON_angular_direct = 0;
+ } else {
+ ON_angular_direct = 1;
+ }
+ Angular_direct();
+
+ if ($('#grid_button').attr('class') === 'M_butt') {
+ ON_grid = 1;
+ } else {
+ ON_grid = 0;
+ }
+ Grid();
+
+ var $relLineInvert = $('#relLineInvert');
+ if ($relLineInvert.attr('class') === 'M_butt') {
+ show_relation_lines = false;
+ $relLineInvert.attr('class', 'M_butt');
+ } else {
+ show_relation_lines = true;
+ $relLineInvert.attr('class', 'M_butt_Selected_down');
+ }
+ Relation_lines_invert();
+
+ if ($('#pin_Text').attr('class') === 'M_butt_Selected_down') {
+ always_show_text = true;
+ Show_text();
+ } else {
+ always_show_text = false;
+ }
+
+ var $key_SB_all = $('#key_SB_all');
+ if ($key_SB_all.attr('class') === 'M_butt_Selected_down') {
+ $key_SB_all.click();
+ $key_SB_all.toggleClass('M_butt_Selected_down');
+ $key_SB_all.toggleClass('M_butt');
+ }
+
+ var $key_Left_Right = $('#key_Left_Right');
+ if ($key_Left_Right.attr('class') === 'M_butt_Selected_down') {
+ $key_Left_Right.click();
+ }
+
+}
function Main()
{
@@ -257,6 +309,7 @@ function Main()
Canvas_pos();
Small_tab_refresh();
Re_load();
+ setDefaultValuesFromSavedState();
id_hint = document.getElementById('pmd_hint');
if (isIE) {
General_scroll();
@@ -374,8 +427,8 @@ function Re_load()
row_offset_top = 0;
tab_hide_button = document.getElementById('id_hide_tbody_' + contr[K][key][key2][key3][0]);
if (tab_hide_button.innerHTML == 'v') {
- var toColumn = document.getElementById(contr[K][key][key2][key3][0]
- + '.' + contr[K][key][key2][key3][1]);
+ var toColumn = document.getElementById(contr[K][key][key2][key3][0] +
+ '.' + contr[K][key][key2][key3][1]);
if (toColumn) {
row_offset_top = toColumn.offsetTop;
} else {
@@ -533,19 +586,24 @@ function Rect(x1, y1, w, h, color)
//--------------------------- FULLSCREEN -------------------------------------
function Toggle_fullscreen()
{
- var $img = $('#toggleFullscreen img');
+ var value_sent = '';
+ var $img = $('#toggleFullscreen').find('img');
var $span = $img.siblings('span');
if (! $.FullScreen.isFullScreen()) {
$img.attr('src', $img.data('exit'))
+ .attr('title', $span.data('exit'));
$span.text($span.data('exit'));
$('#page_content')
.addClass('content_fullscreen')
.css({'width': screen.width - 5, 'height': screen.height - 5})
.requestFullScreen();
+ value_sent = 'on';
}
if ($.FullScreen.isFullScreen()) {
$.FullScreen.cancelFullScreen();
+ value_sent = 'off';
}
+ saveValueInConfig('full_screen', value_sent);
}
// ------------------------------ NEW ------------------------------------------
@@ -728,7 +786,7 @@ function Edit_pages()
if (! pmd_tables_enabled) {
Create_page_list(db, function (options) {
- $("#page_edit_dialog #selected_page").append(options);
+ $("#selected_page").append(options);
});
}
$('<div id="page_edit_dialog"></div>')
@@ -808,7 +866,7 @@ function Delete_pages()
if (! pmd_tables_enabled) {
Create_page_list(db, function (options) {
- $("#page_delete_dialog #selected_page").append(options);
+ $("#selected_page").append(options);
});
}
@@ -907,7 +965,7 @@ function Save_as()
if (! pmd_tables_enabled) {
Create_page_list(db, function (options) {
- $("#page_save_as_dialog #selected_page").append(options);
+ $("#selected_page").append(options);
});
}
@@ -915,7 +973,7 @@ function Save_as()
.append(data.message)
.dialog({
appendTo: '#page_content',
- title: "Save table coordinates",
+ title: PMA_messages.strSavePageAs,
width: 450,
modal: true,
buttons: button_options,
@@ -1033,26 +1091,45 @@ function Load_page(page) {
function Grid()
{
+ var value_sent = '';
if (!ON_grid) {
ON_grid = 1;
+ value_sent = 'on';
document.getElementById('grid_button').className = 'M_butt_Selected_down';
} else {
document.getElementById('grid_button').className = 'M_butt';
ON_grid = 0;
+ value_sent = 'off';
}
+ saveValueInConfig('snap_to_grid', value_sent);
}
function Angular_direct()
{
+ var value_sent = '';
if (ON_angular_direct) {
ON_angular_direct = 0;
+ value_sent = 'angular';
document.getElementById('angular_direct_button').className = 'M_butt_Selected_down';
} else {
ON_angular_direct = 1;
+ value_sent = 'direct';
document.getElementById('angular_direct_button').className = 'M_butt';
}
+ saveValueInConfig('angular_direct', value_sent);
Re_load();
}
+
+function saveValueInConfig(index_sent, value_sent) {
+ $.post('db_designer.php',
+ {operation: 'save_setting_value', index: index_sent, ajax_request: true, server: server, token: token, value: value_sent},
+ function (data) {
+ if (data.success === false) {
+ PMA_ajaxShowMessage(data.error, false);
+ }
+ });
+}
+
//++++++++++++++++++++++++++++++ RELATION ++++++++++++++++++++++++++++++++++++++
function Start_relation()
{
@@ -1181,6 +1258,7 @@ function Small_tab_all(id_this) // max/min all tables
{
var icon = id_this.childNodes[0];
var key;
+ var value_sent = '';
if (icon.alt == "v") {
for (key in j_tabs) {
if (document.getElementById('id_hide_tbody_' + key).innerHTML == "v") {
@@ -1189,6 +1267,7 @@ function Small_tab_all(id_this) // max/min all tables
}
icon.alt = ">";
icon.src = icon.dataset.right;
+ value_sent = 'v';
} else {
for (key in j_tabs) {
if (document.getElementById('id_hide_tbody_' + key).innerHTML != "v") {
@@ -1197,7 +1276,11 @@ function Small_tab_all(id_this) // max/min all tables
}
icon.alt = "v";
icon.src = icon.dataset.down;
+ value_sent = '>';
}
+ saveValueInConfig('small_big_all', value_sent);
+ $('#key_SB_all').toggleClass('M_butt_Selected_down');
+ $('#key_SB_all').toggleClass('M_butt');
Re_load();
}
@@ -1212,6 +1295,9 @@ function Small_tab_invert() // invert max/min all tables
function Relation_lines_invert()
{
show_relation_lines = ! show_relation_lines;
+ saveValueInConfig('relation_lines', show_relation_lines);
+ $('#relLineInvert').toggleClass('M_butt_Selected_down');
+ $('#relLineInvert').toggleClass('M_butt');
Re_load();
}
@@ -1450,7 +1536,7 @@ function No_have_constr(id_this)
if (id_this.alt == 'v') {
id_this.alt = '>';
- id_this.src = id_this.dataset.right;;
+ id_this.src = id_this.dataset.right;
} else {
id_this.alt = 'v';
id_this.src = id_this.dataset.down;
@@ -1540,19 +1626,24 @@ function Side_menu_right(id_this)
icon.attr('src', icon.attr('data-right'));
icon.attr('data-right', current);
menu_moved = !menu_moved;
+ saveValueInConfig('side_menu', $('#side_menu').hasClass('right'));
+ $('#key_Left_Right').toggleClass('M_butt_Selected_down');
+ $('#key_Left_Right').toggleClass('M_butt');
}
//------------------------------------------------------------------------------
function Show_text () {
- $('#side_menu .hidable').show();
+ $('#side_menu').find('.hidable').show();
}
function Hide_text () {
if (!always_show_text) {
- $('#side_menu .hidable').hide();
+ $('#side_menu').find('.hidable').hide();
}
}
function Pin_text () {
always_show_text = !always_show_text;
$('#pin_Text').toggleClass('M_butt_Selected_down');
+ $('#pin_Text').toggleClass('M_butt');
+ saveValueInConfig('pin_text', always_show_text);
}
//------------------------------------------------------------------------------
function Start_display_field()
@@ -1739,26 +1830,26 @@ function add_object()
}
p = document.getElementById('Query');
where_obj = new where(rel.value, p.value);//make where object
- history_array.push(new history(col_name, where_obj, tab_name, h_tabs[downer + '.' + tab_name], "Where"));
+ history_array.push(new history_obj(col_name, where_obj, tab_name, h_tabs[downer + '.' + tab_name], "Where"));
sum = sum + 1;
rel.value = '--';
p.value = "";
}
if (document.getElementById('new_name').value !== "") {
var rename_obj = new rename(document.getElementById('new_name').value);//make Rename object
- history_array.push(new history(col_name, rename_obj, tab_name, h_tabs[downer + '.' + tab_name], "Rename"));
+ history_array.push(new history_obj(col_name, rename_obj, tab_name, h_tabs[downer + '.' + tab_name], "Rename"));
sum = sum + 1;
document.getElementById('new_name').value = "";
}
if (document.getElementById('operator').value != '---') {
var aggregate_obj = new aggregate(document.getElementById('operator').value);
- history_array.push(new history(col_name, aggregate_obj, tab_name, h_tabs[downer + '.' + tab_name], "Aggregate"));
+ history_array.push(new history_obj(col_name, aggregate_obj, tab_name, h_tabs[downer + '.' + tab_name], "Aggregate"));
sum = sum + 1;
document.getElementById('operator').value = '---';
//make aggregate operator
}
if (document.getElementById('groupby').checked === true) {
- history_array.push(new history(col_name, 'GroupBy', tab_name, h_tabs[downer + '.' + tab_name], "GroupBy"));
+ history_array.push(new history_obj(col_name, 'GroupBy', tab_name, h_tabs[downer + '.' + tab_name], "GroupBy"));
sum = sum + 1;
document.getElementById('groupby').checked = false;
//make groupby
@@ -1775,16 +1866,17 @@ function add_object()
p.value,
document.getElementById('h_operator').value
);//make where object
- history_array.push(new history(col_name, where_obj, tab_name, h_tabs[downer + '.' + tab_name], "Having"));
+ history_array.push(new history_obj(col_name, where_obj, tab_name, h_tabs[downer + '.' + tab_name], "Having"));
sum = sum + 1;
document.getElementById('h_rel_opt').value = '--';
document.getElementById('h_operator').value = '---';
p.value = ""; //make having
}
- if (document.getElementById('orderby').checked === true) {
- history_array.push(new history(col_name, 'OrderBy', tab_name, h_tabs[downer + '.' + tab_name], "OrderBy"));
+ if (document.getElementById('orderby').value != '---') {
+ var oderby_obj = new orderby(document.getElementById('orderby').value);
+ history_array.push(new history_obj(col_name, oderby_obj, tab_name, h_tabs[downer + '.' + tab_name], "OrderBy"));
sum = sum + 1;
- document.getElementById('orderby').checked = false;
+ document.getElementById('orderby').value = '---';
//make orderby
}
PMA_ajaxShowMessage(PMA_sprintf(PMA_messages.strObjectsCreated, sum));
@@ -1792,7 +1884,7 @@ function add_object()
var existingDiv = document.getElementById('ab');
existingDiv.innerHTML = display(init, history_array.length);
Close_option();
- panel(0);
+ $('#ab').accordion("refresh");
}
AJAX.registerTeardown('pmd/move.js', function () {
@@ -1823,7 +1915,7 @@ AJAX.registerTeardown('pmd/move.js', function () {
$("#key_HS").unbind('click');
$('.scroll_tab_struct').unbind('click');
$('.scroll_tab_checkbox').unbind('click');
- $('#id_scroll_tab tr').off('click', '.pmd_Tabs2,.pmd_Tabs');
+ $('#id_scroll_tab').find('tr').off('click', '.pmd_Tabs2,.pmd_Tabs');
$('.pmd_tab').off('click', '.select_all_1');
$('.pmd_tab').off('click', '.small_tab,.small_tab2');
$('.pmd_tab').off('click', '.small_tab_pref_1');
@@ -1945,7 +2037,7 @@ AJAX.registerOnload('pmd/move.js', function () {
$('.scroll_tab_checkbox').click(function() {
VisibleTab(this,$(this).val());
});
- $('#id_scroll_tab tr').on('click', '.pmd_Tabs2,.pmd_Tabs', function() {
+ $('#id_scroll_tab').find('tr').on('click', '.pmd_Tabs2,.pmd_Tabs', function() {
Select_tab($(this).attr('pmd_url_table_name'));
});
$('.pmd_tab').on('click', '.select_all_1', function() {
diff --git a/js/replication.js b/js/replication.js
index d9dbf15dcf..42b93b77d7 100644
--- a/js/replication.js
+++ b/js/replication.js
@@ -41,6 +41,7 @@ AJAX.registerTeardown('replication.js', function () {
$('#slave_errormanagement_href').unbind('click');
$('#slave_synchronization_href').unbind('click');
$('#db_reset_href').unbind('click');
+ $('#db_select_href').unbind('click');
});
AJAX.registerOnload('replication.js', function () {
@@ -70,4 +71,8 @@ AJAX.registerOnload('replication.js', function () {
$('#db_select option:selected').prop('selected', false);
$('#db_select').trigger('change');
});
+ $('#db_select_href').click(function () {
+ $('#db_select option').prop('selected', true);
+ $('#db_select').trigger('change');
+ });
});
diff --git a/js/rte.js b/js/rte.js
index 77658b579f..fcc85d7b3f 100644
--- a/js/rte.js
+++ b/js/rte.js
@@ -110,8 +110,41 @@ RTE.COMMON = {
exportDialog: function ($this) {
var $msg = PMA_ajaxShowMessage();
- // Fire the ajax request straight away
- $.get($this.attr('href'), {'ajax_request': true}, function (data) {
+ if ($this.hasClass('mult_submit')) {
+ var combined = {
+ success: true,
+ title: PMA_messages.strExport,
+ message: '',
+ error: ''
+ };
+ // export anchors of all selected rows
+ var export_anchors = $('input.checkall:checked').parents('tr').find('.export_anchor');
+ var count = export_anchors.length;
+ var returnCount = 0;
+
+ export_anchors.each(function () {
+ $.get($(this).attr('href'), {'ajax_request': true}, function (data) {
+ returnCount++;
+ if (data.success === true) {
+ combined.message += "\n" + data.message + "\n";
+ if (returnCount == count) {
+ showExport(combined);
+ }
+ } else {
+ // complain even if one export is failing
+ combined.success = false;
+ combined.error += "\n" + data.error + "\n";
+ if (returnCount == count) {
+ showExport(combined);
+ }
+ }
+ });
+ });
+ } else {
+ $.get($this.attr('href'), {'ajax_request': true}, showExport);
+ }
+
+ function showExport(data) {
if (data.success === true) {
PMA_ajaxRemoveMessage($msg);
/**
@@ -125,6 +158,7 @@ RTE.COMMON = {
/**
* Display the dialog to the user
*/
+ data.message = '<textarea cols="40" rows="15" style="width: 100%;">' + data.message + '</textarea>';
var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
width: 500,
buttons: button_options,
@@ -136,24 +170,11 @@ RTE.COMMON = {
* to the Export textarea.
*/
var $elm = $ajaxDialog.find('textarea');
- /**
- * @var opts Options to pass to the codemirror editor
- */
- var opts = {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- };
- CodeMirror.fromTextArea($elm[0], opts)
- .on("inputRead", codemirrorAutocompleteOnInputRead);
+ PMA_getSQLEditor($elm);
} else {
PMA_ajaxShowMessage(data.error, false);
}
- }); // end $.get()
+ } // end showExport()
}, // end exportDialog()
editorDialog: function (is_new, $this) {
var that = this;
@@ -339,22 +360,8 @@ RTE.COMMON = {
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
- /**
- * @var opts Options to pass to the codemirror editor
- */
- var opts = {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- };
- if (typeof CodeMirror != 'undefined') {
- that.syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts);
- that.syntaxHiglighter.on("inputRead", codemirrorAutocompleteOnInputRead);
- }
+ that.syntaxHiglighter = PMA_getSQLEditor($elm);
+
// Execute item-specific code
that.postDialogShow(data);
} else {
@@ -364,7 +371,7 @@ RTE.COMMON = {
},
dropDialog: function ($this) {
- /**
+ /**
* @var $curr_row Object containing reference to the current row
*/
var $curr_row = $this.parents('tr');
@@ -397,6 +404,7 @@ RTE.COMMON = {
// nothing to show in the table, so we hide it.
$table.hide("slow", function () {
$(this).find('tr.even, tr.odd').remove();
+ $('.withSelected').remove();
$('#nothing2display').show("slow");
});
} else {
@@ -415,7 +423,7 @@ RTE.COMMON = {
*/
var rowclass = '';
$table.find('tr').has('td').each(function () {
- rowclass = (ct % 2 === 0) ? 'odd' : 'even';
+ rowclass = (ct % 2 === 1) ? 'odd' : 'even';
$(this).removeClass().addClass(rowclass);
ct++;
});
@@ -431,6 +439,89 @@ RTE.COMMON = {
}
}); // end $.get()
}); // end $.PMA_confirm()
+ },
+
+ dropMultipleDialog: function ($this) {
+ // We ask for confirmation here
+ $this.PMA_confirm(PMA_messages.strDropRTEitems, '', function (url) {
+ /**
+ * @var msg jQuery object containing the reference to
+ * the AJAX message shown to the user
+ */
+ var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
+
+ // drop anchors of all selected rows
+ var drop_anchors = $('input.checkall:checked').parents('tr').find('.drop_anchor');
+ var success = true;
+ var count = drop_anchors.length;
+ var returnCount = 0;
+
+ drop_anchors.each(function () {
+ var $anchor = $(this);
+ /**
+ * @var $curr_row Object containing reference to the current row
+ */
+ var $curr_row = $anchor.parents('tr');
+ $.get($anchor.attr('href'), {'is_js_confirmed': 1, 'ajax_request': true}, function (data) {
+ returnCount++;
+ if (data.success === true) {
+ /**
+ * @var $table Object containing reference
+ * to the main list of elements
+ */
+ var $table = $curr_row.parent();
+ // Check how many rows will be left after we remove
+ // the one that the user has requested us to remove
+ if ($table.find('tr').length === 3) {
+ // If there are two rows left, it means that they are
+ // the header of the table and the rows that we are
+ // about to remove, so after the removal there will be
+ // nothing to show in the table, so we hide it.
+ $table.hide("slow", function () {
+ $(this).find('tr.even, tr.odd').remove();
+ $('.withSelected').remove();
+ $('#nothing2display').show("slow");
+ });
+ } else {
+ $curr_row.hide("fast", function () {
+ $(this).remove();
+ // Now we have removed the row from the list, but maybe
+ // some row classes are wrong now. So we will itirate
+ // throught all rows and assign correct classes to them.
+ /**
+ * @var ct Count of processed rows
+ */
+ var ct = 0;
+ /**
+ * @var rowclass Class to be attached to the row
+ * that is being processed
+ */
+ var rowclass = '';
+ $table.find('tr').has('td').each(function () {
+ rowclass = (ct % 2 === 1) ? 'odd' : 'even';
+ $(this).removeClass().addClass(rowclass);
+ ct++;
+ });
+ });
+ }
+ if (returnCount == count) {
+ if (success) {
+ // Get rid of the "Loading" message
+ PMA_ajaxRemoveMessage($msg);
+ $('#rteListForm_checkall').prop({checked: false, indeterminate: false});
+ }
+ PMA_reloadNavigation();
+ }
+ } else {
+ PMA_ajaxShowMessage(data.error, false);
+ success = false;
+ if (returnCount == count) {
+ PMA_reloadNavigation();
+ }
+ }
+ }); // end $.get()
+ }); // end drop_anchors.each()
+ }); // end $.PMA_confirm()
}
}; // end RTE namespace
@@ -711,7 +802,7 @@ RTE.ROUTINE = {
/**
* Display the dialog to the user
*/
- $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
+ var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
width: 650,
buttons: that.buttonOptions,
title: data.title,
@@ -806,6 +897,12 @@ $(function () {
dialog.exportDialog($(this));
}); // end $(document).on()
+ $(document).on('click', '#rteListForm.ajax .mult_submit[value="export"]', function (event) {
+ event.preventDefault();
+ var dialog = new RTE.object();
+ dialog.exportDialog($(this));
+ }); // end $(document).on()
+
/**
* Attach Ajax event handlers for Drop functionality
* of Routines, Triggers and Events.
@@ -816,6 +913,12 @@ $(function () {
dialog.dropDialog($(this));
}); // end $(document).on()
+ $(document).on('click', '#rteListForm.ajax .mult_submit[value="drop"]', function (event) {
+ event.preventDefault();
+ var dialog = new RTE.object();
+ dialog.dropMultipleDialog($(this));
+ }); // end $(document).on()
+
/**
* Attach Ajax event handlers for the "Change event/routine type"
* functionality in the events editor, so that the correct
diff --git a/js/server_databases.js b/js/server_databases.js
index b2d00bdddb..42cb7868b6 100644
--- a/js/server_databases.js
+++ b/js/server_databases.js
@@ -127,7 +127,9 @@ AJAX.registerOnload('server_databases.js', function () {
var dbStruct_url = data.url_query;
dbStruct_url = dbStruct_url.replace(/amp;/ig, '');
var params = 'ajax_request=true&ajax_page_request=true';
- params += AJAX.cache.menus.getRequestParam();
+ if (! (history && history.pushState)) {
+ params += PMA_Microhistory.menus.getRequestParam();
+ }
$.get(dbStruct_url, params, AJAX.responseHandler);
} else {
PMA_ajaxShowMessage(data.error, false);
diff --git a/js/server_plugins.js b/js/server_plugins.js
index 4867bda938..dc63827fec 100644
--- a/js/server_plugins.js
+++ b/js/server_plugins.js
@@ -2,24 +2,8 @@
/**
* Functions used in server plugins pages
*/
-var pma_theme_image; // filled in server_plugins.php
-
AJAX.registerOnload('server_plugins.js', function () {
- // Add tabs
- $('#pluginsTabs').tabs({
- // Tab persistence
- cookie: { name: 'pma_serverStatusTabs', expires: 1 },
- show: function (event, ui) {
- // Fixes line break in the menu bar when the page overflows and scrollbar appears
- $('#topmenu').menuResizer('resize');
- // 'Plugins' tab is too high due to hiding of 'Modules' by negative left position,
- // hide tabs by changing display to fix it
- $(ui.panel).closest('.ui-tabs').find('> div').not(ui.panel).css('display', 'none');
- $(ui.panel).css('display', 'block');
- }
- });
-
- // Make columns sortable, but only for tables with more than 1 data row
+ // Make columns sortable, but only for tables with more than 1 data row
var $tables = $('#plugins_plugins table:has(tbody tr + tr)');
$tables.tablesorter({
sortList: [[0, 0]],
diff --git a/js/server_privileges.js b/js/server_privileges.js
index 1310b01a84..6228dfce9d 100644
--- a/js/server_privileges.js
+++ b/js/server_privileges.js
@@ -61,6 +61,7 @@ AJAX.registerTeardown('server_privileges.js', function () {
$(document).off("click", ".checkall_box");
$(document).off('change', '#checkbox_SSL_priv');
$(document).off('change', 'input[name="ssl_type"]');
+ $(document).off('change', '#select_authentication_plugin');
});
AJAX.registerOnload('server_privileges.js', function () {
@@ -92,6 +93,18 @@ AJAX.registerOnload('server_privileges.js', function () {
});
/**
+ * Display a notice if sha256_password is selected
+ */
+ $(document).on("change", "#select_authentication_plugin", function () {
+ var selected_plugin = $(this).val();
+ if (selected_plugin === 'sha256_password') {
+ $('#ssl_reqd_warning').show();
+ } else {
+ $('#ssl_reqd_warning').hide();
+ }
+ });
+
+ /**
* AJAX handler for 'Revoke User'
*
* @see PMA_ajaxShowMessage()
@@ -106,7 +119,7 @@ AJAX.registerOnload('server_privileges.js', function () {
$thisButton.PMA_confirm(PMA_messages.strDropUserWarning, $form.attr('action'), function (url) {
- $drop_users_db_checkbox = $("#checkbox_drop_users_db");
+ var $drop_users_db_checkbox = $("#checkbox_drop_users_db");
if ($drop_users_db_checkbox.is(':checked')) {
var is_confirmed = confirm(PMA_messages.strDropDatabaseStrongWarning + '\n' + PMA_sprintf(PMA_messages.strDoYouReally, 'DROP DATABASE'));
if (! is_confirmed) {
@@ -259,18 +272,7 @@ AJAX.registerOnload('server_privileges.js', function () {
});
PMA_ajaxRemoveMessage($msgbox);
// Attach syntax highlighted editor to export dialog
- if (typeof CodeMirror != 'undefined') {
- CodeMirror.fromTextArea(
- $ajaxDialog.find('textarea')[0],
- {
- lineNumbers: true,
- matchBrackets: true,
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- }
- );
- }
+ PMA_getSQLEditor($ajaxDialog.find('textarea'));
} else {
PMA_ajaxShowMessage(data.error, false);
}
@@ -278,18 +280,7 @@ AJAX.registerOnload('server_privileges.js', function () {
); //end $.post
});
// if exporting non-ajax, highlight anyways
- if ($("textarea.export").length > 0 && typeof CodeMirror != 'undefined') {
- CodeMirror.fromTextArea(
- $('textarea.export')[0],
- {
- lineNumbers: true,
- matchBrackets: true,
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- }
- );
- }
+ PMA_getSQLEditor($('textarea.export'));
$(document).on('click', "a.export_user_anchor.ajax", function (event) {
event.preventDefault();
@@ -315,18 +306,7 @@ AJAX.registerOnload('server_privileges.js', function () {
});
PMA_ajaxRemoveMessage($msgbox);
// Attach syntax highlighted editor to export dialog
- if (typeof CodeMirror != 'undefined') {
- CodeMirror.fromTextArea(
- $ajaxDialog.find('textarea')[0],
- {
- lineNumbers: true,
- matchBrackets: true,
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- }
- );
- }
+ PMA_getSQLEditor($ajaxDialog.find('textarea'));
} else {
PMA_ajaxShowMessage(data.error, false);
}
diff --git a/js/server_status_advisor.js b/js/server_status_advisor.js
index eb1a5f89fb..c2e3b6bac8 100644
--- a/js/server_status_advisor.js
+++ b/js/server_status_advisor.js
@@ -16,6 +16,12 @@ AJAX.registerTeardown('server_status_advisor.js', function () {
});
AJAX.registerOnload('server_status_advisor.js', function () {
+
+ // if no advisor is loaded
+ if ($('#advisorData').length == 0) {
+ return;
+ }
+
/**** Server config advisor ****/
var $dialog = $('<div />').attr('id', 'advisorDialog');
var $instructionsDialog = $('<div />')
diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js
index e1bcad371e..84b8a31477 100644
--- a/js/server_status_monitor.js
+++ b/js/server_status_monitor.js
@@ -103,7 +103,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
}
// Timepicker is loaded on demand so we need to initialize
// datetime fields from the 'load log' dialog
- $('#logAnalyseDialog .datetimefield').each(function () {
+ $('#logAnalyseDialog').find('.datetimefield').each(function () {
PMA_addDatepicker($(this));
});
@@ -403,15 +403,15 @@ AJAX.registerOnload('server_status_monitor.js', function () {
calculateChartSize();
// Empty cells should keep their size so you can drop onto them
- $('#chartGrid tr td').css('width', chartSize.width + 'px');
- $('#chartGrid .monitorChart').css({
+ $('#chartGrid').find('tr td').css('width', chartSize.width + 'px');
+ $('#chartGrid').find('.monitorChart').css({
width: chartSize.width + 'px',
height: chartSize.height + 'px'
});
/* Reorder all charts that it fills all column cells */
var numColumns;
- var $tr = $('#chartGrid tr:first');
+ var $tr = $('#chartGrid').find('tr:first');
var row = 0;
var tempManageCols = function () {
@@ -488,7 +488,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
var type = $('input[name="chartType"]:checked').val();
if (type == 'preset') {
- newChart = presetCharts[$('#addChartDialog select[name="presetCharts"]').prop('value')];
+ newChart = presetCharts[$('#addChartDialog').find('select[name="presetCharts"]').prop('value')];
} else {
// If user builds his own chart, it's being set/updated
// each time he adds a series
@@ -517,7 +517,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
$(this).dialog("close");
};
- var $presetList = $('#addChartDialog select[name="presetCharts"]');
+ var $presetList = $('#addChartDialog').find('select[name="presetCharts"]');
if ($presetList.html().length === 0) {
$.each(presetCharts, function (key, value) {
$presetList.append('<option value="' + key + '">' + value.title + '</option>');
@@ -551,7 +551,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
buttons: dlgButtons
});
- $('#addChartDialog #seriesPreview').html('<i>' + PMA_messages.strNone + '</i>');
+ $('#seriesPreview').html('<i>' + PMA_messages.strNone + '</i>');
return false;
});
@@ -984,10 +984,10 @@ AJAX.registerOnload('server_status_monitor.js', function () {
/* Calculate how much spacing there is between each chart */
$('#chartGrid').html('<tr><td></td><td></td></tr><tr><td></td><td></td></tr>');
chartSpacing = {
- width: $('#chartGrid td:nth-child(2)').offset().left -
- $('#chartGrid td:nth-child(1)').offset().left,
- height: $('#chartGrid tr:nth-child(2) td:nth-child(2)').offset().top -
- $('#chartGrid tr:nth-child(1) td:nth-child(1)').offset().top
+ width: $('#chartGrid').find('td:nth-child(2)').offset().left -
+ $('#chartGrid').find('td:nth-child(1)').offset().left,
+ height: $('#chartGrid').find('tr:nth-child(2) td:nth-child(2)').offset().top -
+ $('#chartGrid').find('tr:nth-child(1) td:nth-child(1)').offset().top
};
$('#chartGrid').html('');
@@ -1002,15 +1002,15 @@ AJAX.registerOnload('server_status_monitor.js', function () {
}
/* Fill in missing cells */
- var numCharts = $('#chartGrid .monitorChart').length;
+ var numCharts = $('#chartGrid').find('.monitorChart').length;
var numMissingCells = (monitorSettings.columns - numCharts % monitorSettings.columns) % monitorSettings.columns;
for (i = 0; i < numMissingCells; i++) {
- $('#chartGrid tr:last').append('<td></td>');
+ $('#chartGrid').find('tr:last').append('<td></td>');
}
// Empty cells should keep their size so you can drop onto them
calculateChartSize();
- $('#chartGrid tr td').css('width', chartSize.width + 'px');
+ $('#chartGrid').find('tr td').css('width', chartSize.width + 'px');
buildRequiredDataList();
refreshChartGrid();
@@ -1130,7 +1130,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
settings.series = chartObj.series;
if ($('#' + 'gridchart' + runtime.chartAI).length === 0) {
- var numCharts = $('#chartGrid .monitorChart').length;
+ var numCharts = $('#chartGrid').find('.monitorChart').length;
if (numCharts === 0 || (numCharts % monitorSettings.columns === 0)) {
$('#chartGrid').append('<tr></tr>');
@@ -1139,7 +1139,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
if (!chartSize) {
calculateChartSize();
}
- $('#chartGrid tr:last').append(
+ $('#chartGrid').find('tr:last').append(
'<td><div id="gridChartContainer' + runtime.chartAI + '" class="">' +
'<div class="ui-state-default monitorChart"' +
' id="gridchart' + runtime.chartAI + '"' +
@@ -1238,7 +1238,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
if ($('#selection_box').length) {
$('#selection_box').remove();
}
- selectionBox = $('<div id="selection_box" style="z-index:1000;height:250px;position:absolute;background-color:#87CEEB;opacity:0.4;filter:alpha(opacity=40);pointer-events:none;">');
+ var selectionBox = $('<div id="selection_box" style="z-index:1000;height:205px;position:absolute;background-color:#87CEEB;opacity:0.4;filter:alpha(opacity=40);pointer-events:none;">');
$(document.body).append(selectionBox);
selectionStartX = ev.pageX;
selectionStartY = ev.pageY;
@@ -1289,19 +1289,20 @@ AJAX.registerOnload('server_status_monitor.js', function () {
$(document.body).mouseup(function () {
if ($('#selection_box').length) {
- selectionBox.remove();
+ $('#selection_box').remove();
}
});
// Edit, Print icon only in edit mode
- $('#chartGrid div svg').find('*[zIndex=20], *[zIndex=21], *[zIndex=19]').toggle(editMode);
+ $('#chartGrid').find('div svg').find('*[zIndex=20], *[zIndex=21], *[zIndex=19]').toggle(editMode);
runtime.chartAI++;
}
function PMA_getLogAnalyseDialog(min, max) {
- var $dateStart = $('#logAnalyseDialog input[name="dateStart"]');
- var $dateEnd = $('#logAnalyseDialog input[name="dateEnd"]');
+ var $logAnalyseDialog = $('#logAnalyseDialog');
+ var $dateStart = $logAnalyseDialog.find('input[name="dateStart"]');
+ var $dateEnd = $logAnalyseDialog.find('input[name="dateEnd"]');
$dateStart.prop("readonly", true);
$dateEnd.prop("readonly", true);
@@ -1317,7 +1318,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
$(this).dialog("close");
};
- $('#logAnalyseDialog').dialog({
+ $logAnalyseDialog.dialog({
width: 'auto',
height: 'auto',
buttons: dlgBtns
@@ -1333,13 +1334,13 @@ AJAX.registerOnload('server_status_monitor.js', function () {
showMicrosec: false,
timeFormat: 'HH:mm:ss'
});
- $('#logAnalyseDialog input[name="dateStart"]').datepicker('setDate', min);
- $('#logAnalyseDialog input[name="dateEnd"]').datepicker('setDate', max);
+ $dateStart.datepicker('setDate', min);
+ $dateEnd.datepicker('setDate', max);
}
function loadLog(type, min, max) {
- var dateStart = Date.parse($('#logAnalyseDialog input[name="dateStart"]').datepicker('getDate')) || min;
- var dateEnd = Date.parse($('#logAnalyseDialog input[name="dateEnd"]').datepicker('getDate')) || max;
+ var dateStart = Date.parse($('#logAnalyseDialog').find('input[name="dateStart"]').datepicker('getDate')) || min;
+ var dateEnd = Date.parse($('#logAnalyseDialog').find('input[name="dateEnd"]').datepicker('getDate')) || max;
loadLogStatistics({
src: type,
@@ -1350,7 +1351,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
});
}
- /* Called in regular intervalls, this function updates the values of each chart in the grid */
+ /* Called in regular intervals, this function updates the values of each chart in the grid */
function refreshChartGrid() {
/* Send to server */
runtime.refreshRequest = $.post('server_status_monitor.php' + PMA_commonParams.get('common_query'), {
@@ -1610,66 +1611,66 @@ AJAX.registerOnload('server_status_monitor.js', function () {
return serverResponseError();
}
- if (logData.rows.length !== 0) {
- runtime.logDataCols = buildLogTable(logData, opts.removeVariables);
-
- /* Show some stats in the dialog */
- $('#emptyDialog').dialog({title: PMA_messages.strLoadingLogs});
- $('#emptyDialog').html('<p>' + PMA_messages.strLogDataLoaded + '</p>');
- $.each(logData.sum, function (key, value) {
- key = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
- if (key == 'Total') {
- key = '<b>' + key + '</b>';
- }
- $('#emptyDialog').append(key + ': ' + value + '<br/>');
- });
+ if (logData.rows.length === 0) {
+ $('#emptyDialog').dialog({title: PMA_messages.strNoDataFoundTitle});
+ $('#emptyDialog').html('<p>' + PMA_messages.strNoDataFound + '</p>');
- /* Add filter options if more than a bunch of rows there to filter */
- if (logData.numRows > 12) {
- $('#logTable').prepend(
- '<fieldset id="logDataFilter">' +
- ' <legend>' + PMA_messages.strFiltersForLogTable + '</legend>' +
- ' <div class="formelement">' +
- ' <label for="filterQueryText">' + PMA_messages.strFilterByWordRegexp + '</label>' +
- ' <input name="filterQueryText" type="text" id="filterQueryText" style="vertical-align: baseline;" />' +
- ' </div>' +
- ((logData.numRows > 250) ? ' <div class="formelement"><button name="startFilterQueryText" id="startFilterQueryText">' + PMA_messages.strFilter + '</button></div>' : '') +
- ' <div class="formelement">' +
- ' <input type="checkbox" id="noWHEREData" name="noWHEREData" value="1" /> ' +
- ' <label for="noWHEREData"> ' + PMA_messages.strIgnoreWhereAndGroup + '</label>' +
- ' </div' +
- '</fieldset>'
- );
+ dlgBtns[PMA_messages.strClose] = function () {
+ $(this).dialog("close");
+ };
- $('#logTable #noWHEREData').change(function () {
- filterQueries(true);
- });
+ $('#emptyDialog').dialog("option", "buttons", dlgBtns);
+ return;
+ }
- if (logData.numRows > 250) {
- $('#logTable #startFilterQueryText').click(filterQueries);
- } else {
- $('#logTable #filterQueryText').keyup(filterQueries);
- }
+ runtime.logDataCols = buildLogTable(logData, opts.removeVariables);
+ /* Show some stats in the dialog */
+ $('#emptyDialog').dialog({title: PMA_messages.strLoadingLogs});
+ $('#emptyDialog').html('<p>' + PMA_messages.strLogDataLoaded + '</p>');
+ $.each(logData.sum, function (key, value) {
+ key = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
+ if (key == 'Total') {
+ key = '<b>' + key + '</b>';
}
+ $('#emptyDialog').append(key + ': ' + value + '<br/>');
+ });
- dlgBtns[PMA_messages.strJumpToTable] = function () {
- $(this).dialog("close");
- $(document).scrollTop($('#logTable').offset().top);
- };
-
- $('#emptyDialog').dialog("option", "buttons", dlgBtns);
+ /* Add filter options if more than a bunch of rows there to filter */
+ if (logData.numRows > 12) {
+ $('#logTable').prepend(
+ '<fieldset id="logDataFilter">' +
+ ' <legend>' + PMA_messages.strFiltersForLogTable + '</legend>' +
+ ' <div class="formelement">' +
+ ' <label for="filterQueryText">' + PMA_messages.strFilterByWordRegexp + '</label>' +
+ ' <input name="filterQueryText" type="text" id="filterQueryText" style="vertical-align: baseline;" />' +
+ ' </div>' +
+ ((logData.numRows > 250) ? ' <div class="formelement"><button name="startFilterQueryText" id="startFilterQueryText">' + PMA_messages.strFilter + '</button></div>' : '') +
+ ' <div class="formelement">' +
+ ' <input type="checkbox" id="noWHEREData" name="noWHEREData" value="1" /> ' +
+ ' <label for="noWHEREData"> ' + PMA_messages.strIgnoreWhereAndGroup + '</label>' +
+ ' </div' +
+ '</fieldset>'
+ );
- } else {
- $('#emptyDialog').dialog({title: PMA_messages.strNoDataFoundTitle});
- $('#emptyDialog').html('<p>' + PMA_messages.strNoDataFound + '</p>');
+ $('#noWHEREData').change(function () {
+ filterQueries(true);
+ });
- dlgBtns[PMA_messages.strClose] = function () {
- $(this).dialog("close");
- };
+ if (logData.numRows > 250) {
+ $('#startFilterQueryText').click(filterQueries);
+ } else {
+ $('#filterQueryText').keyup(filterQueries);
+ }
- $('#emptyDialog').dialog("option", "buttons", dlgBtns);
}
+
+ dlgBtns[PMA_messages.strJumpToTable] = function () {
+ $(this).dialog("close");
+ $(document).scrollTop($('#logTable').offset().top);
+ };
+
+ $('#emptyDialog').dialog("option", "buttons", dlgBtns);
}
);
@@ -1682,7 +1683,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
*/
function filterQueries(varFilterChange) {
var odd_row = false, cell, textFilter;
- var val = $('#logTable #filterQueryText').val();
+ var val = $('#filterQueryText').val();
if (val.length === 0) {
textFilter = null;
@@ -1691,7 +1692,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
}
var rowSum = 0, totalSum = 0, i = 0, q;
- var noVars = $('#logTable #noWHEREData').prop('checked');
+ var noVars = $('#noWHEREData').prop('checked');
var equalsFilter = /([^=]+)=(\d+|((\'|"|).*?[^\\])\4((\s+)|$))/gi;
var functionFilter = /([a-z0-9_]+)\(.+?\)/gi;
var filteredQueries = {}, filteredQueriesLines = {};
@@ -1717,7 +1718,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
};
// We just assume the sql text is always in the second last column, and that the total count is right of it
- $('#logTable table tbody tr td:nth-child(' + (runtime.logDataCols.length - 1) + ')').each(function () {
+ $('#logTable').find('table tbody tr td:nth-child(' + (runtime.logDataCols.length - 1) + ')').each(function () {
var $t = $(this);
// If query is a SELECT and user enabled or disabled to group
// queries ignoring data in where statements, we
@@ -1793,7 +1794,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
// We finished summarizing counts => Update count values of all grouped entries
if (varFilterChange) {
if (noVars) {
- var numCol, row, $table = $('#logTable table tbody');
+ var numCol, row, $table = $('#logTable').find('table tbody');
$.each(filteredQueriesLines, function (key, value) {
if (filteredQueries[key] <= 1) {
return;
@@ -1812,16 +1813,16 @@ AJAX.registerOnload('server_status_monitor.js', function () {
});
}
- $('#logTable table').trigger("update");
+ $('#logTable').find('table').trigger("update");
setTimeout(function () {
- $('#logTable table').trigger('sorton', [[[runtime.logDataCols.length - 1, 1]]]);
+ $('#logTable').find('table').trigger('sorton', [[[runtime.logDataCols.length - 1, 1]]]);
}, 0);
}
// Display some stats at the bottom of the table
- $('#logTable table tfoot tr')
+ $('#logTable').find('table tfoot tr')
.html('<th colspan="' + (runtime.logDataCols.length - 1) + '">' +
- PMA_messages.strSumRows + ' ' + rowSum + '<span style="float:right">' +
+ PMA_messages.strSumRows + ' ' + rowSum + '<span class="floatright">' +
PMA_messages.strTotal + '</span></th><th class="right">' + totalSum + '</th>');
}
}
@@ -1900,12 +1901,12 @@ AJAX.registerOnload('server_status_monitor.js', function () {
$table.append('<tfoot>' +
'<tr><th colspan="' + (cols.length - 1) + '">' + PMA_messages.strSumRows +
- ' ' + data.numRows + '<span style="float:right">' + PMA_messages.strTotal +
+ ' ' + data.numRows + '<span class="floatright">' + PMA_messages.strTotal +
'</span></th><th class="right">' + data.sum.TOTAL + '</th></tr></tfoot>');
// Append a tooltip to the count column, if there exist one
- if ($('#logTable tr:first th:last').text().indexOf("#") > -1) {
- $('#logTable tr:first th:last').append('&nbsp;' + PMA_getImage('b_help.png', '', {'class': 'qroupedQueryInfoIcon'}));
+ if ($('#logTable').find('tr:first th:last').text().indexOf("#") > -1) {
+ $('#logTable').find('tr:first th:last').append('&nbsp;' + PMA_getImage('b_help.png', '', {'class': 'qroupedQueryInfoIcon'}));
var tooltipContent = PMA_messages.strCountColumnExplanation;
if (groupInserts) {
@@ -1919,12 +1920,12 @@ AJAX.registerOnload('server_status_monitor.js', function () {
);
}
- $('#logTable table').tablesorter({
+ $('#logTable').find('table').tablesorter({
sortList: [[cols.length - 1, 1]],
widgets: ['fast-zebra']
});
- $('#logTable table thead th')
+ $('#logTable').find('table thead th')
.append('<div class="sorticon"></div>');
return cols;
@@ -1968,7 +1969,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
if (profilingChart !== null) {
profilingChart.destroy();
}
- $('#queryAnalyzerDialog div.placeHolder').html('');
+ $('#queryAnalyzerDialog').find('div.placeHolder').html('');
if (codemirror_editor) {
codemirror_editor.setValue('');
} else {
@@ -1982,7 +1983,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
function loadQueryAnalysis(rowData) {
var db = rowData.db || '';
- $('#queryAnalyzerDialog div.placeHolder').html(
+ $('#queryAnalyzerDialog').find('div.placeHolder').html(
PMA_messages.strAnalyzing + ' <img class="ajaxIcon" src="' +
pmaThemeImage + 'ajax_clock_small.gif" alt="">');
@@ -1992,7 +1993,7 @@ AJAX.registerOnload('server_status_monitor.js', function () {
query: codemirror_editor ? codemirror_editor.getValue() : $('#sqlquery').val(),
database: db
}, function (data) {
- var i;
+ var i, l;
if (typeof data !== 'undefined' && data.success === true) {
data = data.message;
}
@@ -2000,12 +2001,12 @@ AJAX.registerOnload('server_status_monitor.js', function () {
if (data.error.indexOf('1146') != -1 || data.error.indexOf('1046') != -1) {
data.error = PMA_messages.strServerLogError;
}
- $('#queryAnalyzerDialog div.placeHolder').html('<div class="error">' + data.error + '</div>');
+ $('#queryAnalyzerDialog').find('div.placeHolder').html('<div class="error">' + data.error + '</div>');
return;
}
var totalTime = 0;
// Float sux, I'll use table :(
- $('#queryAnalyzerDialog div.placeHolder')
+ $('#queryAnalyzerDialog').find('div.placeHolder')
.html('<table width="100%" border="0"><tr><td class="explain"></td><td class="chart"></td></tr></table>');
var explain = '<b>' + PMA_messages.strExplainOutput + '</b> ' + $('#explain_docu').html();
@@ -2041,9 +2042,9 @@ AJAX.registerOnload('server_status_monitor.js', function () {
explain += '<p><b>' + PMA_messages.strAffectedRows + '</b> ' + data.affectedRows;
- $('#queryAnalyzerDialog div.placeHolder td.explain').append(explain);
+ $('#queryAnalyzerDialog').find('div.placeHolder td.explain').append(explain);
- $('#queryAnalyzerDialog div.placeHolder a[href*="#showExplain"]').click(function () {
+ $('#queryAnalyzerDialog').find('div.placeHolder a[href*="#showExplain"]').click(function () {
var id = $(this).attr('href').split('-')[1];
$(this).parent().find('div[class*="explain"]').hide();
$(this).parent().find('div[class*="explain-' + id + '"]').show();
@@ -2081,26 +2082,26 @@ AJAX.registerOnload('server_status_monitor.js', function () {
numberTable += '<tr><td><b>' + PMA_messages.strTotalTime + '</b></td><td>' + PMA_prettyProfilingNum(totalTime, 2) + '</td></tr>';
numberTable += '</tbody></table>';
- $('#queryAnalyzerDialog div.placeHolder td.chart').append(
+ $('#queryAnalyzerDialog').find('div.placeHolder td.chart').append(
'<b>' + PMA_messages.strProfilingResults + ' ' + $('#profiling_docu').html() + '</b> ' +
'(<a href="#showNums">' + PMA_messages.strTable + '</a>, <a href="#showChart">' + PMA_messages.strChart + '</a>)<br/>' +
numberTable + ' <div id="queryProfiling"></div>');
- $('#queryAnalyzerDialog div.placeHolder a[href="#showNums"]').click(function () {
- $('#queryAnalyzerDialog #queryProfiling').hide();
- $('#queryAnalyzerDialog table.queryNums').show();
+ $('#queryAnalyzerDialog').find('div.placeHolder a[href="#showNums"]').click(function () {
+ $('#queryAnalyzerDialog').find('#queryProfiling').hide();
+ $('#queryAnalyzerDialog').find('table.queryNums').show();
return false;
});
- $('#queryAnalyzerDialog div.placeHolder a[href="#showChart"]').click(function () {
- $('#queryAnalyzerDialog #queryProfiling').show();
- $('#queryAnalyzerDialog table.queryNums').hide();
+ $('#queryAnalyzerDialog').find('div.placeHolder a[href="#showChart"]').click(function () {
+ $('#queryAnalyzerDialog').find('#queryProfiling').show();
+ $('#queryAnalyzerDialog').find('table.queryNums').hide();
return false;
});
profilingChart = PMA_createProfilingChartJqplot(
- 'queryProfiling',
- chartData
+ 'queryProfiling',
+ chartData
);
//$('#queryProfiling').resizable();
diff --git a/js/server_status_processes.js b/js/server_status_processes.js
index 017735fcfb..a8b47662f7 100644
--- a/js/server_status_processes.js
+++ b/js/server_status_processes.js
@@ -57,10 +57,9 @@ var processList = {
$tr.remove();
// As we just removed a row, reapply odd-even classes
// to keep table stripes consistent
- $('#tableprocesslist > tbody > tr').filter(':even')
- .removeClass('odd').addClass('even');
- $('#tableprocesslist > tbody > tr').filter(':odd')
- .removeClass('even').addClass('odd');
+ var $tableProcessListTr = $('#tableprocesslist').find('> tbody > tr');
+ $tableProcessListTr.filter(':even').removeClass('odd').addClass('even');
+ $tableProcessListTr.filter(':odd').removeClass('even').addClass('odd');
// Show process killed message
PMA_ajaxShowMessage(data.message, false);
} else {
diff --git a/js/server_status_sorter.js b/js/server_status_sorter.js
index 424389e7d9..b0891c1688 100644
--- a/js/server_status_sorter.js
+++ b/js/server_status_sorter.js
@@ -72,18 +72,12 @@ $(function () {
$.tablesorter.addWidget({
id: "fast-zebra",
format: function (table) {
- if (table.config.debug) {
- var time = new Date();
- }
$("tr:even", table.tBodies[0])
.removeClass(table.config.widgetZebra.css[0])
.addClass(table.config.widgetZebra.css[1]);
$("tr:odd", table.tBodies[0])
.removeClass(table.config.widgetZebra.css[1])
.addClass(table.config.widgetZebra.css[0]);
- if (table.config.debug) {
- $.tablesorter.benchmark("Applying Fast-Zebra widget", time);
- }
}
});
});
diff --git a/js/server_status_variables.js b/js/server_status_variables.js
index 7410c9e5bf..fa46f1fda9 100644
--- a/js/server_status_variables.js
+++ b/js/server_status_variables.js
@@ -38,8 +38,8 @@ AJAX.registerOnload('server_status_variables.js', function () {
$('#dontFormat').change(function () {
// Hiding the table while changing values speeds up the process a lot
$('#serverstatusvariables').hide();
- $('#serverstatusvariables td.value span.original').toggle(this.checked);
- $('#serverstatusvariables td.value span.formatted').toggle(! this.checked);
+ $('#serverstatusvariables').find('td.value span.original').toggle(this.checked);
+ $('#serverstatusvariables').find('td.value span.formatted').toggle(! this.checked);
$('#serverstatusvariables').show();
}).trigger('change');
@@ -64,7 +64,7 @@ AJAX.registerOnload('server_status_variables.js', function () {
}
if (section.length > 1) {
- $('#linkSuggestions span').each(function () {
+ $('#linkSuggestions').find('span').each(function () {
if ($(this).attr('class').indexOf('status_' + section) != -1) {
useful_links++;
$(this).css('display', '');
@@ -81,7 +81,7 @@ AJAX.registerOnload('server_status_variables.js', function () {
}
odd_row = false;
- $('#serverstatusvariables th.name').each(function () {
+ $('#serverstatusvariables').find('th.name').each(function () {
if ((textFilter === null || textFilter.exec($(this).text())) &&
(! alertFilter || $(this).next().find('span.attention').length > 0) &&
(categoryFilter.length === 0 || $(this).parent().hasClass('s_' + categoryFilter))
diff --git a/js/server_variables.js b/js/server_variables.js
index 22f759f6f8..3b4dc11244 100644
--- a/js/server_variables.js
+++ b/js/server_variables.js
@@ -43,7 +43,7 @@ AJAX.registerOnload('server_variables.js', function () {
/* Filters the rows by the user given regexp */
function filterVariables(textFilter) {
var mark_next = false, $row, odd_row = false;
- $('#serverVariables .var-row').not('.var-header').each(function () {
+ $('#serverVariables').find('.var-row').not('.var-header').each(function () {
$row = $(this);
if (mark_next || textFilter === null ||
textFilter.exec($row.find('.var-name').text())
diff --git a/js/sql.js b/js/sql.js
index ecc3f3d2d1..6815f7ed69 100644
--- a/js/sql.js
+++ b/js/sql.js
@@ -91,6 +91,7 @@ AJAX.registerTeardown('sql.js', function () {
$(document).off('stickycolumns', ".sqlqueryresults");
$("#togglequerybox").unbind('click');
$(document).off('click', "#button_submit_query");
+ $(document).off('change', '#id_bookmark');
$("input[name=bookmark_variable]").unbind("keypress");
$(document).off('submit', "#sqlqueryform.ajax");
$(document).off('click', "input[name=navig].ajax");
@@ -100,6 +101,7 @@ AJAX.registerTeardown('sql.js', function () {
$(document).off('click', 'th.column_heading.marker');
$(window).unbind('scroll');
$(document).off("keyup", ".filter_rows");
+ $(document).off('click', "#printView");
if (codemirror_editor) {
codemirror_editor.off('change');
} else {
@@ -191,6 +193,16 @@ AJAX.registerOnload('sql.js', function () {
}).trigger('keyup');
/**
+ * Attach Event Handler for 'Print View'
+ */
+ $(document).on('click', "#printView", function (event) {
+ event.preventDefault();
+
+ // Print the page
+ printPage();
+ }); //end of Print View action
+
+ /**
* Attach the {@link makegrid} function to a custom event, which will be
* triggered manually everytime the table of results is reloaded
* @memberOf jQuery
@@ -272,6 +284,31 @@ AJAX.registerOnload('sql.js', function () {
});
/**
+ * Event handler to show appropiate number of variable boxes
+ * based on the bookmarked query
+ */
+ $(document).on('change', '#id_bookmark', function (event) {
+
+ var varCount = $(this).find('option:selected').data('varcount');
+ if (typeof varCount == 'undefined') {
+ varCount = 0;
+ }
+
+ var $varDiv = $('#bookmark_variables');
+ $varDiv.empty();
+ for (var i = 1; i <= varCount; i++) {
+ $varDiv.append($('<label for="bookmark_variable_' + i + '">' + PMA_sprintf(PMA_messages.strBookmarkVariable, i) + '</label>'));
+ $varDiv.append($('<input type="text" size="10" name="bookmark_variable[' + i + ']" id="bookmark_variable_' + i + '"></input>'));
+ }
+
+ if (varCount == 0) {
+ $varDiv.parent('.formelement').hide();
+ } else {
+ $varDiv.parent('.formelement').show();
+ }
+ });
+
+ /**
* Event handler for hitting enter on sqlqueryform bookmark_variable
* (the Variable textfield in Bookmarked SQL query section)
*
@@ -351,10 +388,21 @@ AJAX.registerOnload('sql.js', function () {
PMA_highlightSQL($sqlqueryresultsouter);
if (data._menu) {
- AJAX.cache.menus.replace(data._menu);
- AJAX.cache.menus.add(data._menuHash, data._menu);
+ if (history && history.pushState) {
+ history.replaceState({
+ menu : data._menu
+ },
+ null
+ );
+ AJAX.handleMenu.replace(data._menu);
+ } else {
+ PMA_Microhistory.menus.replace(data._menu);
+ PMA_Microhistory.menus.add(data._menuHash, data._menu);
+ }
} else if (data._menuHash) {
- AJAX.cache.menus.replace(AJAX.cache.menus.get(data._menuHash));
+ if (! (history && history.pushState)) {
+ PMA_Microhistory.menus.replace(PMA_Microhistory.menus.get(data._menuHash));
+ }
}
if (data._params) {
@@ -463,7 +511,7 @@ AJAX.registerOnload('sql.js', function () {
// Prompt to confirm on Show All
$('body').on('click', '.navigation .showAllRows', function (e) {
e.preventDefault();
- $form = $(this).parents('form');
+ var $form = $(this).parents('form');
if (! $(this).is(':checked')) { // already showing all rows
submitShowAllForm();
@@ -538,7 +586,7 @@ AJAX.registerOnload('sql.js', function () {
dialog_content += response.message;
}
dialog_content += '</div>';
- $dialog_content = $(dialog_content);
+ var $dialog_content = $(dialog_content);
var button_options = {};
button_options[PMA_messages.strClose] = function () {
$(this).dialog('close');
@@ -572,9 +620,10 @@ AJAX.registerOnload('sql.js', function () {
$('body').on('click', 'form[name="resultsForm"].ajax button[name="submit_mult"], form[name="resultsForm"].ajax input[name="submit_mult"]', function (e) {
e.preventDefault();
var $button = $(this);
- var $form = $button.parent('form');
+ var $form = $button.closest('form');
var submitData = $form.serialize() + '&ajax_request=true&ajax_page_request=true&submit_mult=' + $button.val();
PMA_ajaxShowMessage();
+ AJAX.source = $form;
$.post($form.attr('action'), submitData, AJAX.responseHandler);
});
}); // end $()
diff --git a/js/tbl_change.js b/js/tbl_change.js
index fb16701900..29a186b3da 100644
--- a/js/tbl_change.js
+++ b/js/tbl_change.js
@@ -100,7 +100,7 @@ function isDate(val, tmstmp)
}
val = arrayVal.join("-");
var pos = 2;
- var dtexp = new RegExp(/^([0-9]{4})-(((01|03|05|07|08|10|12)-((0[0-9])|([1-2][0-9])|(3[0-1])))|((02|04|06|09|11)-((0[0-9])|([1-2][0-9])|30)))$/);
+ var dtexp = new RegExp(/^([0-9]{4})-(((01|03|05|07|08|10|12)-((0[1-9])|([1-2][0-9])|(3[0-1])))|((02|04|06|09|11)-((0[1-9])|([1-2][0-9])|30)))$/);
if (val.length == 8) {
pos = 0;
}
@@ -147,16 +147,29 @@ function isTime(val)
return tmexp.test(val);
}
+/**
+ * To check whether insert section is ignored or not
+ */
+function checkForCheckbox(multi_edit)
+{
+ if($("#insert_ignore_"+multi_edit).length) {
+ return $("#insert_ignore_"+multi_edit).is(":unchecked");
+ }
+ return true;
+}
+
function verificationsAfterFieldChange(urlField, multi_edit, theType)
{
var evt = window.event || arguments.callee.caller.arguments[0];
var target = evt.target || evt.srcElement;
- var $this_input = $("input[name='fields[multi_edit][" + multi_edit + "][" +
+ var $this_input = $(":input[name^='fields[multi_edit][" + multi_edit + "][" +
+ urlField + "]']");
+ // the function drop-down that corresponds to this input field
+ var $this_function = $("select[name='funcs[multi_edit][" + multi_edit + "][" +
urlField + "]']");
- // check if it is textarea rather than input
- if ($this_input.length === 0) {
- $this_input = $("textarea[name='fields[multi_edit][" + multi_edit + "][" +
- urlField + "]']");
+ var function_selected = false;
+ if (typeof $this_function.val() !== 'undefined' && $this_function.val().length > 0) {
+ function_selected = true;
}
//To generate the textbox that can take the salt
@@ -178,19 +191,17 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType)
$("#salt_" + target.id).remove();
}
- if (target.value === 'AES_DECRYPT' || target.value === 'AES_ENCRYPT') {
- if ($this_input.data('type') !== 'HEX') {
- $('#' + target.id).addClass('invalid_value');
- return false;
- }
- } else if(target.value === 'MD5' &&
- typeof $this_input.data('maxlength') !== 'undefined' &&
- $this_input.data('maxlength') < 32
- ) {
- $('#' + target.id).addClass('invalid_value');
- return false;
- } else {
- $('#' + target.id).removeClass('invalid_value');
+ if (target.value === 'AES_DECRYPT'
+ || target.value === 'AES_ENCRYPT'
+ || target.value === 'MD5') {
+ $('#' + target.id).rules("add", {
+ validationFunctionForFuns: {
+ param: $this_input,
+ depends: function() {
+ return checkForCheckbox(multi_edit);
+ }
+ }
+ });
}
// Unchecks the corresponding "NULL" control
@@ -199,149 +210,118 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType)
// Unchecks the Ignore checkbox for the current row
$("input[name='insert_ignore_" + multi_edit + "']").prop('checked', false);
- // Does this field come from datepicker?
- if ($this_input.data('comes_from') == 'datepicker') {
- // Yes, so do not validate because the final value is not yet in
- // the field and hopefully the datepicker returns a valid date+time
- $this_input.removeClass("invalid_value");
- return true;
+ var charExceptionHandling;
+ if (theType.substring(0,4) === "char") {
+ charExceptionHandling = theType.substring(5,6);
+ }
+ else if (theType.substring(0,7) === "varchar") {
+ charExceptionHandling = theType.substring(8,9);
+ }
+ if (function_selected) {
+ $this_input.removeAttr('min');
+ $this_input.removeAttr('max');
+ // @todo: put back attributes if corresponding function is deselected
}
- if (target.name.substring(0, 6) == "fields") {
+ if ($this_input.data('rulesadded') == null && ! function_selected) {
+
+ //call validate before adding rules
+ $($this_input[0].form).validate();
// validate for date time
if (theType == "datetime" || theType == "time" || theType == "date" || theType == "timestamp") {
- $this_input.removeClass("invalid_value");
- var dt_value = $this_input.val();
- if (theType == "date") {
- if (! isDate(dt_value)) {
- $this_input.addClass("invalid_value");
- return false;
- }
- } else if (theType == "time") {
- if (! isTime(dt_value)) {
- $this_input.addClass("invalid_value");
- return false;
- }
- } else if (theType == "datetime" || theType == "timestamp") {
- var tmstmp = false;
- if (dt_value == "CURRENT_TIMESTAMP") {
- return true;
- }
- if (theType == "timestamp") {
- tmstmp = true;
- }
- if (dt_value == "0000-00-00 00:00:00") {
- return true;
- }
- var dv = dt_value.indexOf(" ");
- if (dv == -1) {
- $this_input.addClass("invalid_value");
- return false;
- } else {
- if (! (isDate(dt_value.substring(0, dv), tmstmp) && isTime(dt_value.substring(dv + 1)))) {
- $this_input.addClass("invalid_value");
- return false;
+ $this_input.rules("add", {
+ validationFunctionForDateTime: {
+ param: theType,
+ depends: function() {
+ return checkForCheckbox(multi_edit);
}
}
- }
+ });
}
//validation for integer type
if ($this_input.data('type') === 'INT') {
- var min = $this_input.attr('min');
- var max = $this_input.attr('max');
- var value = $this_input.val();
- $this_input.removeClass("invalid_value");
- if (isNaN(value) || BigInts.compare(value, min) < 0 ||
- BigInts.compare(value, max) > 0
- ) {
- $this_input.addClass("invalid_value");
- return false;
- }
+ var mini = parseInt($this_input.attr('min'));
+ var maxi = parseInt($this_input.attr('max'));
+ $this_input.rules("add", {
+ number: {
+ param : true,
+ depends: function() {
+ return checkForCheckbox(multi_edit);
+ }
+ },
+ min: {
+ param: mini,
+ depends: function() {
+ if (isNaN($this_input.val())) {
+ return false;
+ } else {
+ return checkForCheckbox(multi_edit);
+ }
+ }
+ },
+ max: {
+ param: maxi,
+ depends: function() {
+ if (isNaN($this_input.val())) {
+ return false;
+ } else {
+ return checkForCheckbox(multi_edit);
+ }
+ }
+ }
+ });
//validation for CHAR types
} else if ($this_input.data('type') === 'CHAR') {
- var len = $this_input.val().length;
var maxlen = $this_input.data('maxlength');
- $this_input.removeClass("invalid_value");
- if (typeof maxlen !== 'undefined' && len > maxlen) {
- $this_input.addClass("invalid_value");
- return false;
+ if (typeof maxlen !== 'undefined') {
+ if (maxlen <=4) {
+ maxlen=charExceptionHandling;
+ }
+ $this_input.rules("add", {
+ maxlength: {
+ param: maxlen,
+ depends: function() {
+ return checkForCheckbox(multi_edit);
+ }
+ }
+ });
}
// validate binary & blob types
} else if ($this_input.data('type') === 'HEX') {
- $this_input.removeClass("invalid_value");
- if ($this_input.val().match(/^[a-f0-9]*$/i) === null) {
- $this_input.addClass("invalid_value");
- return false;
- }
+ $this_input.rules("add", {
+ validationFunctionForHex: {
+ param: true,
+ depends: function() {
+ return checkForCheckbox(multi_edit);
+ }
+ }
+ });
}
+ $this_input.data('rulesadded', true);
+ } else if ($this_input.data('rulesadded') == true && function_selected) {
+ // remove any rules added
+ $this_input.rules("remove");
+ // remove any error messages
+ $this_input
+ .removeClass('error')
+ .removeAttr('aria-invalid')
+ .siblings('.error')
+ .remove();
+ $this_input.data('rulesadded', null);
}
}
- /* End of fields validation*/
-
-/**
- * Applies the selected function to all rows to be inserted.
- *
- * @param string currId Current ID of the row
- * @param string functionName Name of the function
- * @param bool copySalt Whether to copy salt or not
- * @param string salt Salt value
- * @param object targetRows Target rows
- *
- * @return void
- */
-function applyFunctionToAllRows(currId, functionName, copySalt, salt, targetRows)
-{
- targetRows.each(function () {
- var currentRowNum = /\d/.exec($(this).find("input[name*='fields_name']").attr("name"));
-
- // Append the function select list.
- var targetSelectList = $(this).find("select[name*='funcs[multi_edit]']");
-
- if (targetSelectList.attr("id") === currId) {
- return;
- }
- targetSelectList.find("option").filter(function () {
- return $(this).text() === functionName;
- }).attr("selected","selected");
-
- // Handle salt field.
- if (functionName === 'AES_ENCRYPT' ||
- functionName === 'AES_DECRYPT' ||
- functionName === 'DES_ENCRYPT' ||
- functionName === 'DES_DECRYPT' ||
- functionName === 'ENCRYPT') {
- if ($("#salt_" + targetSelectList.attr("id")).length === 0) {
- // Get hash value.
- var hashed_value = targetSelectList.attr("name").match(/\[multi\_edit\]\[\d\]\[(.*)\]/);
- //To generate the textbox that can take the salt
- var new_salt_box = "<br><input type=text name=salt[multi_edit][" + currentRowNum + "][" + hashed_value[1] + "]" +
- " id=salt_" + targetSelectList.attr("id") + " placeholder='" + PMA_messages.strEncryptionKey + "'>";
- targetSelectList.parent().next("td").next("td").find("input[name*='fields']").after(new_salt_box);
- }
-
- if (copySalt) {
- $("#salt_" + targetSelectList.attr("id")).val(salt);
- }
- } else {
- var id = targetSelectList.attr("id");
- if ($("#salt_" + id).length) {
- $("#salt_" + id).remove();
- }
- }
- });
-}
-
+/* End of fields validation*/
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('tbl_change.js', function () {
$(document).off('click', 'span.open_gis_editor');
+ $(document).off('click', "input[name^='insert_ignore_']");
$(document).off('click', "input[name='gis_data[save]']");
$(document).off('click', 'input.checkbox_null');
$('select[name="submit_type"]').unbind('change');
$(document).off('change', "#insert_rows");
- $(document).off('click', "select[name*='funcs']");
});
/**
@@ -352,6 +332,61 @@ AJAX.registerTeardown('tbl_change.js', function () {
* Restart insertion with 'N' rows.
*/
AJAX.registerOnload('tbl_change.js', function () {
+
+ if($("#insertForm").length) {
+ // validate the comment form when it is submitted
+ $("#insertForm").validate();
+ jQuery.validator.addMethod("validationFunctionForHex", function(value, element) {
+ return value.match(/^[a-f0-9]*$/i) !== null;
+ });
+
+ jQuery.validator.addMethod("validationFunctionForFuns", function(value, element, options) {
+ if (value.substring(0, 3) === "AES" && options.data('type') !== 'HEX') {
+ return false;
+ }
+
+ return !(value.substring(0, 3) === "MD5"
+ && typeof options.data('maxlength') !== 'undefined'
+ && options.data('maxlength') < 32);
+ });
+
+ jQuery.validator.addMethod("validationFunctionForDateTime", function(value, element, options) {
+ var dt_value = value;
+ var theType = options;
+ if (theType == "date") {
+ return isDate(dt_value);
+
+ } else if (theType == "time") {
+ return isTime(dt_value);
+
+ } else if (theType == "datetime" || theType == "timestamp") {
+ var tmstmp = false;
+ dt_value = dt_value.trim();
+ if (dt_value == "CURRENT_TIMESTAMP") {
+ return true;
+ }
+ if (theType == "timestamp") {
+ tmstmp = true;
+ }
+ if (dt_value == "0000-00-00 00:00:00") {
+ return true;
+ }
+ var dv = dt_value.indexOf(" ");
+ if (dv == -1) { // Only the date component, which is valid
+ return isDate(dt_value, tmstmp);
+ }
+
+ return isDate(dt_value.substring(0, dv), tmstmp)
+ && isTime(dt_value.substring(dv + 1));
+ }
+ });
+ /*
+ * message extending script must be run
+ * after initiation of functions
+ */
+ extendingValidatorMessages();
+ }
+
$.datepicker.initialized = false;
$(document).on('click', 'span.open_gis_editor', function (event) {
@@ -378,6 +413,13 @@ AJAX.registerOnload('tbl_change.js', function () {
});
/**
+ * Forced validation check of fields
+ */
+ $(document).on('click',"input[name^='insert_ignore_']", function (event) {
+ $("#insertForm").valid();
+ });
+
+ /**
* Uncheck the null checkbox as geometry data is placed on the input field
*/
$(document).on('click', "input[name='gis_data[save]']", function (event) {
@@ -648,90 +690,6 @@ AJAX.registerOnload('tbl_change.js', function () {
// Add all the required datepickers back
addDateTimePicker();
});
-
- /**
- * @var $function_option_dialog object holds dialog for selected function options.
- */
- var $function_option_dialog = null;
-
- PMA_tooltip(
- $("select[name*='funcs']"),
- 'select',
- PMA_messages.strFunctionHint
- );
-
- $(document).on('click', "select[name*='funcs']", function (event) {
- if (! event.shiftKey) {
- return false;
- }
-
- // Name of selected function.
- var functionName = $(this).find("option:selected").html();
- var currId = $(this).attr("id");
- // Name of column.
- var columnName = $(this).closest("tr").find("input[name*='fields_name']").val();
- var targetRows = $("tr").has("input[value='" + columnName + "']");
- var salt;
- var copySalt = false;
-
- if (functionName === 'AES_ENCRYPT' ||
- functionName === 'AES_DECRYPT' ||
- functionName === 'DES_ENCRYPT' ||
- functionName === 'DES_DECRYPT' ||
- functionName === 'ENCRYPT') {
- // Dialog title.
- var title = functionName;
- // Dialog buttons functions.
- var buttonOptions = {};
- buttonOptions[PMA_messages.strYes] = function () {
- // Go function.
- copySalt = true;
- salt = $("#salt_" + currId).val();
- applyFunctionToAllRows(currId, functionName, copySalt, salt, targetRows);
- $(this).dialog("close");
- };
- buttonOptions[PMA_messages.strNo] = function () {
- copySalt = false;
- salt = "";
- applyFunctionToAllRows(currId, functionName, copySalt, salt, targetRows);
- $(this).dialog("close");
- };
-
- // Contents of dialog.
- var dialog = "<div>" +
- "<fieldset>" +
- "<span style='font-weight: bold;'>" +
- PMA_messages.strCopyEncryptionKey +
- "</fieldset>" +
- "</div>";
-
- // Show the dialog
- var width = parseInt(
- (parseInt($('html').css('font-size'), 10) / 13) * 340,
- 10
- );
- if (! width) {
- width = 340;
- }
-
- $function_option_dialog = $(dialog).dialog({
- minWidth: width,
- modal: true,
- title: title,
- buttons: buttonOptions,
- resizable: false,
- open: function () {
- // Focus the "Go" button after opening the dialog
- $(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button:first').focus();
- },
- close: function () {
- $(this).remove();
- }
- });
- }
-
- applyFunctionToAllRows(currId, functionName, copySalt, "", targetRows);
- });
});
function changeValueFieldType(elem, searchIndex)
diff --git a/js/tbl_chart.js b/js/tbl_chart.js
index 4e7100cd56..33cdab78dd 100644
--- a/js/tbl_chart.js
+++ b/js/tbl_chart.js
@@ -33,7 +33,7 @@ function PMA_queryChart(data, columnNames, settings) {
return;
}
- var jqPlotSettings = {
+ var plotSettings = {
title : {
text : settings.title,
escapeHtml: true
@@ -73,6 +73,7 @@ function PMA_queryChart(data, columnNames, settings) {
dataTable.addColumn(ColumnType.STRING, columnNames[settings.mainAxis]);
}
+ var i;
if (settings.seriesColumn === null) {
$.each(settings.selectedSeries, function (index, element) {
dataTable.addColumn(ColumnType.NUMBER, columnNames[element]);
@@ -84,7 +85,7 @@ function PMA_queryChart(data, columnNames, settings) {
columnsToExtract.push(element);
});
var values = [], newRow, row, col;
- for (var i = 0; i < data.length; i++) {
+ for (i = 0; i < data.length; i++) {
row = data[i];
newRow = [];
for (var j = 0; j < columnsToExtract.length; j++) {
@@ -107,7 +108,7 @@ function PMA_queryChart(data, columnNames, settings) {
} else {
var seriesNames = {}, seriesNumber = 1;
var seriesColumnName = columnNames[settings.seriesColumn];
- for (var i = 0; i < data.length; i++) {
+ for (i = 0; i < data.length; i++) {
if (! seriesNames[data[i][seriesColumnName]]) {
seriesNames[data[i][seriesColumnName]] = seriesNumber;
seriesNumber++;
@@ -121,7 +122,7 @@ function PMA_queryChart(data, columnNames, settings) {
var valueMap = {}, xValue, value;
var mainAxisName = columnNames[settings.mainAxis];
var valueColumnName = columnNames[settings.valueColumn];
- for (var i = 0; i < data.length; i++) {
+ for (i = 0; i < data.length; i++) {
xValue = data[i][mainAxisName];
value = valueMap[xValue];
if (! value) {
@@ -140,7 +141,7 @@ function PMA_queryChart(data, columnNames, settings) {
}
// draw the chart and return the chart object
- chart.draw(dataTable, jqPlotSettings);
+ chart.draw(dataTable, plotSettings);
return chart;
}
@@ -236,39 +237,23 @@ AJAX.registerTeardown('tbl_chart.js', function () {
$('input[name="xaxis_label"]').unbind('keyup');
$('input[name="yaxis_label"]').unbind('keyup');
$('#resizer').unbind('resizestop');
+ $('#tblchartform').unbind('submit');
});
AJAX.registerOnload('tbl_chart.js', function () {
- // from jQuery UI
- $('#resizer').resizable({
- minHeight: 240,
- minWidth: 300
- })
- .width($('#div_view_options').width() - 50);
-
+ // handle manual resize
$('#resizer').bind('resizestop', function (event, ui) {
// make room so that the handle will still appear
$('#querychart').height($('#resizer').height() * 0.96);
$('#querychart').width($('#resizer').width() * 0.96);
- currentChart.redraw({
- resetAxes : true
- });
+ if (currentChart !== null) {
+ currentChart.redraw({
+ resetAxes : true
+ });
+ }
});
- currentSettings = {
- type : 'line',
- width : $('#resizer').width() - 20,
- height : $('#resizer').height() - 20,
- xaxisLabel : $('input[name="xaxis_label"]').val(),
- yaxisLabel : $('input[name="yaxis_label"]').val(),
- title : $('input[name="chartTitle"]').val(),
- stackSeries : false,
- mainAxis : parseInt($('select[name="chartXAxis"]').val(), 10),
- selectedSeries : getSelectedSeries(),
- seriesColumn : null
- };
-
// handle chart type changes
$('input[name="chartType"]').click(function () {
var type = currentSettings.type = $(this).val();
@@ -332,16 +317,6 @@ AJAX.registerOnload('tbl_chart.js', function () {
}
});
- var vals = $('input[name="dateTimeCols"]').val().split(' ');
- $.each(vals, function (i, v) {
- dateTimeCols.push(parseInt(v, 10));
- });
-
- vals = $('input[name="numericCols"]').val().split(' ');
- $.each(vals, function (i, v) {
- numericCols.push(parseInt(v, 10));
- });
-
// handle changing the x-axis
$('select[name="chartXAxis"]').change(function () {
onXAxisChange();
@@ -366,64 +341,79 @@ AJAX.registerOnload('tbl_chart.js', function () {
drawChart();
});
- // handle manual changes to the chart axis labels
+ // handle manual changes to the chart x-axis labels
$('input[name="xaxis_label"]').keyup(function () {
currentSettings.xaxisLabel = $(this).val();
drawChart();
});
+
+ // handle manual changes to the chart y-axis labels
$('input[name="yaxis_label"]').keyup(function () {
currentSettings.yaxisLabel = $(this).val();
drawChart();
});
- onXAxisChange();
- onDataSeriesChange();
+ // handler for ajax form submission
+ $('#tblchartform').submit(function (event) {
- $("#tblchartform").submit();
-});
-
-/**
- * Ajax Event handler for 'Go' button click
- *
- */
-$(document).on('submit', "#tblchartform", function (event) {
- if (!checkFormElementInRange(this, 'session_max_rows', PMA_messages.strNotValidRowNumber, 1) ||
- !checkFormElementInRange(this, 'pos', PMA_messages.strNotValidRowNumber, 0 - 1)
- ) {
- return false;
- }
+ var $form = $(this);
+ if (codemirror_editor) {
+ $form[0].elements.sql_query.value = codemirror_editor.getValue();
+ }
+ if (!checkSqlQuery($form[0])) {
+ return false;
+ }
- var $form = $(this);
- if (codemirror_editor) {
- $form[0].elements.sql_query.value = codemirror_editor.getValue();
- }
- if (!checkSqlQuery($form[0])) {
- return false;
- }
- // remove any div containing a previous error message
- $('.error').remove();
- var $msgbox = PMA_ajaxShowMessage();
- PMA_prepareForAjaxRequest($form);
-
- $.post($form.attr('action'), $form.serialize(), function (data) {
- if (typeof data !== 'undefined' && data.success === true) {
- $('.success').fadeOut();
- if (typeof data.chartData != 'undefined') {
+ var $msgbox = PMA_ajaxShowMessage();
+ PMA_prepareForAjaxRequest($form);
+ $.post($form.attr('action'), $form.serialize(), function (data) {
+ if (typeof data !== 'undefined' &&
+ data.success === true &&
+ typeof data.chartData !== 'undefined') {
chart_data = jQuery.parseJSON(data.chartData);
drawChart();
- $('div#querychart').height($('div#resizer').height() * 0.96);
- $('div#querychart').width($('div#resizer').width() * 0.96);
- currentChart.redraw({
- resetAxes : true
- });
- $('#querychart').show();
+ PMA_ajaxRemoveMessage($msgbox);
+ } else {
+ PMA_ajaxShowMessage(data.error, false);
}
- } else {
- PMA_ajaxRemoveMessage($msgbox);
- PMA_ajaxShowMessage(data.error, false);
- }
- PMA_ajaxRemoveMessage($msgbox);
- }, "json"); // end $.post()
+ }, "json"); // end $.post()
+
+ return false;
+ });
+
+ // from jQuery UI
+ $('#resizer').resizable({
+ minHeight: 240,
+ minWidth: 300
+ })
+ .width($('#div_view_options').width() - 50)
+ .trigger('resizestop');
+
+ currentSettings = {
+ type : 'line',
+ width : $('#resizer').width() - 20,
+ height : $('#resizer').height() - 20,
+ xaxisLabel : $('input[name="xaxis_label"]').val(),
+ yaxisLabel : $('input[name="yaxis_label"]').val(),
+ title : $('input[name="chartTitle"]').val(),
+ stackSeries : false,
+ mainAxis : parseInt($('select[name="chartXAxis"]').val(), 10),
+ selectedSeries : getSelectedSeries(),
+ seriesColumn : null
+ };
+
+ var vals = $('input[name="dateTimeCols"]').val().split(' ');
+ $.each(vals, function (i, v) {
+ dateTimeCols.push(parseInt(v, 10));
+ });
- return false;
-}); // end
+ vals = $('input[name="numericCols"]').val().split(' ');
+ $.each(vals, function (i, v) {
+ numericCols.push(parseInt(v, 10));
+ });
+
+ onXAxisChange();
+ onDataSeriesChange();
+
+ $("#tblchartform").submit();
+});
diff --git a/js/tbl_gis_visualization.js b/js/tbl_gis_visualization.js
index 71787428fd..6a71a946b2 100644
--- a/js/tbl_gis_visualization.js
+++ b/js/tbl_gis_visualization.js
@@ -14,8 +14,8 @@ var defaultX = 0;
var defaultY = 0;
// Variables
-var x;
-var y;
+var x = 0;
+var y = 0;
var scale = 1;
var svg;
@@ -26,6 +26,9 @@ var svg;
function zoomAndPan()
{
var g = svg.getElementById('groupPanel');
+ if (!g) {
+ return;
+ }
g.setAttribute('transform', 'translate(' + x + ', ' + y + ') scale(' + scale + ')');
var id;
@@ -104,7 +107,7 @@ function loadSVG() {
*/
function addZoomPanControllers() {
var $placeholder = $('#placeholder');
- if ($("#placeholder svg").length > 0) {
+ if ($("#placeholder").find("svg").length > 0) {
var pmaThemeImage = $('#pmaThemeImage').val();
// add panning arrows
$('<img class="button" id="left_arrow" src="' + pmaThemeImage + 'west-mini.png">').appendTo($placeholder);
@@ -249,10 +252,10 @@ AJAX.registerOnload('tbl_gis_visualization.js', function () {
});
$(document).on('drag', 'svg', function (event, dd) {
- newX = Math.round(dd.offsetX);
+ var newX = Math.round(dd.offsetX);
x += newX - dragX;
dragX = newX;
- newY = Math.round(dd.offsetY);
+ var newY = Math.round(dd.offsetY);
y += newY - dragY;
dragY = newY;
zoomAndPan();
@@ -272,8 +275,9 @@ AJAX.registerOnload('tbl_gis_visualization.js', function () {
//zoom in
scale *= zoomFactor;
- width = $('#placeholder svg').attr('width');
- height = $('#placeholder svg').attr('height');
+ var $placeholder = $('#placeholder').find('svg');
+ width = $placeholder.attr('width');
+ height = $placeholder.attr('height');
// zooming in keeping the center unmoved.
x = width / 2 - (width / 2 - x) * zoomFactor;
y = height / 2 - (height / 2 - y) * zoomFactor;
@@ -293,8 +297,9 @@ AJAX.registerOnload('tbl_gis_visualization.js', function () {
//zoom out
scale /= zoomFactor;
- width = $('#placeholder svg').attr('width');
- height = $('#placeholder svg').attr('height');
+ var $placeholder = $('#placeholder').find('svg');
+ width = $placeholder.attr('width');
+ height = $placeholder.attr('height');
// zooming out keeping the center unmoved.
x = width / 2 - (width / 2 - x) / zoomFactor;
y = height / 2 - (height / 2 - y) / zoomFactor;
diff --git a/js/tbl_operations.js b/js/tbl_operations.js
index b851cecb43..8ce2d6fe1f 100644
--- a/js/tbl_operations.js
+++ b/js/tbl_operations.js
@@ -5,6 +5,7 @@ AJAX.registerTeardown('tbl_operations.js', function () {
$(document).off('submit', "#copyTable.ajax");
$(document).off('submit', "#moveTableForm");
$(document).off('submit', "#tableOptionsForm");
+ $(document).off('submit', "#partitionsForm");
$(document).off('click', "#tbl_maintenance li a.maintain_action.ajax");
$(document).off('click', "#drop_tbl_anchor.ajax");
$(document).off('click', "#drop_view_anchor.ajax");
@@ -80,10 +81,35 @@ AJAX.registerOnload('tbl_operations.js', function () {
event.stopPropagation();
var $form = $(this);
var $tblNameField = $form.find('input[name=new_name]');
+ var $tblCollationField = $form.find('select[name=tbl_collation]');
+ var collationOrigValue = $('select[name="tbl_collation"] option[selected]').val();
+ var $changeAllColumnCollationsCheckBox = $('#checkbox_change_all_collations');
+ var question = PMA_messages.strChangeAllColumnCollationsWarning;
+
if ($tblNameField.val() !== $tblNameField[0].defaultValue) {
// reload page and navigation if the table has been renamed
PMA_prepareForAjaxRequest($form);
var tbl = $tblNameField.val();
+
+ if ($tblCollationField.val() !== collationOrigValue && $changeAllColumnCollationsCheckBox.is(':checked')) {
+ $form.PMA_confirm(question, $form.attr('action'), function (url) {
+ submitOptionsForm();
+ });
+ } else {
+ submitOptionsForm();
+ }
+ } else {
+
+ if ($tblCollationField.val() !== collationOrigValue && $changeAllColumnCollationsCheckBox.is(':checked')) {
+ $form.PMA_confirm(question, $form.attr('action'), function (url) {
+ $form.removeClass('ajax').submit().addClass('ajax');
+ });
+ } else {
+ $form.removeClass('ajax').submit().addClass('ajax');
+ }
+ }
+
+ function submitOptionsForm() {
$.post($form.attr('action'), $form.serialize(), function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_commonParams.set('table', tbl);
@@ -95,8 +121,6 @@ AJAX.registerOnload('tbl_operations.js', function () {
PMA_ajaxShowMessage(data.error, false);
}
}); // end $.post()
- } else {
- $form.removeClass('ajax').submit().addClass('ajax');
}
});
@@ -143,6 +167,36 @@ AJAX.registerOnload('tbl_operations.js', function () {
}); // end $.post()
});//end of table maintenance ajax click
+ /**
+ * Ajax action for submitting the "Partition Maintenance"
+ * Also, asks for confirmation when DROP partition is submitted
+ */
+ $(document).on('submit', "#partitionsForm", function (event) {
+ event.preventDefault();
+ var $form = $(this);
+
+ function submitPartitionMaintenance() {
+ var submitData = $form.serialize() + '&ajax_request=true&ajax_page_request=true';
+ PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
+ AJAX.source = $form;
+ $.post($form.attr('action'), submitData, AJAX.responseHandler);
+ }
+
+ if ($('#partition_operation_DROP').is(':checked')) {
+ var question = PMA_messages.strDropPartitionWarning;
+ $form.PMA_confirm(question, $form.attr('action'), function (url) {
+ submitPartitionMaintenance();
+ });
+ } else if ($('#partition_operation_TRUNCATE').is(':checked')) {
+ var question = PMA_messages.strTruncatePartitionWarning;
+ $form.PMA_confirm(question, $form.attr('action'), function (url) {
+ submitPartitionMaintenance();
+ });
+ } else {
+ submitPartitionMaintenance();
+ }
+ });
+
$(document).on('click', "#drop_tbl_anchor.ajax", function (event) {
event.preventDefault();
/**
@@ -152,12 +206,15 @@ AJAX.registerOnload('tbl_operations.js', function () {
question += PMA_sprintf(
PMA_messages.strDoYouReally,
'DROP TABLE ' + escapeHtml(PMA_commonParams.get('table'))
- );
+ ) + getForeignKeyCheckboxLoader();
$(this).PMA_confirm(question, $(this).attr('href'), function (url) {
var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
- $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function (data) {
+
+ var params = getJSConfirmCommonParam(this);
+
+ $.get(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxRemoveMessage($msgbox);
// Table deleted successfully, refresh both the frames
@@ -173,7 +230,7 @@ AJAX.registerOnload('tbl_operations.js', function () {
PMA_ajaxShowMessage(data.error, false);
}
}); // end $.get()
- }); // end $.PMA_confirm()
+ }, loadForeignKeyCheckbox); // end $.PMA_confirm()
}); //end of Drop Table Ajax action
$(document).on('click', "#drop_view_anchor.ajax", function (event) {
@@ -218,10 +275,13 @@ AJAX.registerOnload('tbl_operations.js', function () {
question += PMA_sprintf(
PMA_messages.strDoYouReally,
'TRUNCATE ' + escapeHtml(PMA_commonParams.get('table'))
- );
+ ) + getForeignKeyCheckboxLoader();
$(this).PMA_confirm(question, $(this).attr('href'), function (url) {
PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
- $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function (data) {
+
+ var params = getJSConfirmCommonParam(this);
+
+ $.get(url, params, function (data) {
if ($(".sqlqueryresults").length !== 0) {
$(".sqlqueryresults").remove();
}
@@ -237,7 +297,7 @@ AJAX.registerOnload('tbl_operations.js', function () {
PMA_ajaxShowMessage(data.error, false);
}
}); // end $.get()
- }); // end $.PMA_confirm()
+ }, loadForeignKeyCheckbox); // end $.PMA_confirm()
}); //end of Truncate Table Ajax action
}); //end $(document).ready for 'Table operations'
diff --git a/js/tbl_relation.js b/js/tbl_relation.js
index f3de08295c..9a4ae5903d 100644
--- a/js/tbl_relation.js
+++ b/js/tbl_relation.js
@@ -35,18 +35,18 @@ function setDropdownValues($dropdown, values, selectedValue) {
*/
function getDropdownValues($dropdown) {
var foreignDb = null, foreignTable = null;
- var $tableDd, $columnDd;
+ var $databaseDd, $tableDd, $columnDd;
var foreign = '';
// if the changed dropdown is for foreign key constraints
if ($dropdown.is('select[name^="destination_foreign"]')) {
$databaseDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_db"]');
- $tableDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_table"]');
- $columnDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_column"]');
+ $tableDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_table"]');
+ $columnDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_column"]');
foreign = '_foreign';
} else { // internal relations
$databaseDd = $dropdown.parent().find('select[name^="destination_db"]');
- $tableDd = $dropdown.parent().find('select[name^="destination_table"]');
- $columnDd = $dropdown.parent().find('select[name^="destination_column"]');
+ $tableDd = $dropdown.parent().find('select[name^="destination_table"]');
+ $columnDd = $dropdown.parent().find('select[name^="destination_column"]');
}
// if the changed dropdown is a database selector
diff --git a/js/tbl_select.js b/js/tbl_select.js
index 05511fd65f..8167b4458b 100644
--- a/js/tbl_select.js
+++ b/js/tbl_select.js
@@ -92,8 +92,15 @@ AJAX.registerOnload('tbl_select.js', function () {
"!= ''"
];
+ var geomUnaryFunctions = [
+ 'IsEmpty',
+ 'IsSimple',
+ 'IsRing',
+ 'IsClosed',
+ ];
+
// jQuery object to reuse
- $search_form = $(this);
+ var $search_form = $(this);
event.preventDefault();
// empty previous search results while we are waiting for new results
@@ -120,6 +127,11 @@ AJAX.registerOnload('tbl_select.js', function () {
continue;
}
+ if (values['geom_func[' + a + ']'] &&
+ $.isArray(values['geom_func[' + a + ']'], geomUnaryFunctions) >= 0) {
+ continue;
+ }
+
if (values['criteriaValues[' + a + ']'] === '' || values['criteriaValues[' + a + ']'] === null) {
delete values['criteriaValues[' + a + ']'];
delete values['criteriaColumnOperators[' + a + ']'];
diff --git a/js/tbl_structure.js b/js/tbl_structure.js
index d734b55104..0937923090 100644
--- a/js/tbl_structure.js
+++ b/js/tbl_structure.js
@@ -58,10 +58,12 @@ function reloadFieldForm() {
var $temp_div = $("<div id='temp_div'><div>").append(form_data.message);
$("#fieldsForm").replaceWith($temp_div.find("#fieldsForm"));
$("#addColumns").replaceWith($temp_div.find("#addColumns"));
- $('#move_columns_dialog ul').replaceWith($temp_div.find("#move_columns_dialog ul"));
+ $('#move_columns_dialog').find('ul').replaceWith($temp_div.find("#move_columns_dialog ul"));
$("#moveColumns").removeClass("move-active");
/* reinitialise the more options in table */
- $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ if ($('#fieldsForm').hasClass('HideStructureActions')) {
+ $('#fieldsForm').find('ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ }
});
$('#page_content').show();
}
@@ -80,8 +82,10 @@ AJAX.registerTeardown('tbl_structure.js', function () {
$(document).off('click', "a.drop_column_anchor.ajax");
$(document).off('click', "a.add_key.ajax");
$(document).off('click', "#move_columns_anchor");
+ $(document).off('click', "#printView");
$(document).off('submit', ".append_fields_form.ajax");
$('body').off('click', '#fieldsForm.ajax button[name="submit_mult"], #fieldsForm.ajax input[name="submit_mult"]');
+ $(document).off('click', 'a[name^=partition_action].ajax');
});
AJAX.registerOnload('tbl_structure.js', function () {
@@ -91,6 +95,7 @@ AJAX.registerOnload('tbl_structure.js', function () {
unique_indexes = [];
indexes = [];
fulltext_indexes = [];
+ spatial_indexes = [];
/**
*Ajax action for submitting the "Column Change" and "Add Column" form
@@ -102,6 +107,54 @@ AJAX.registerOnload('tbl_structure.js', function () {
* @var the_form object referring to the export form
*/
var $form = $(this);
+ var field_cnt = $form.find('input[name=orig_num_fields]').val();
+
+
+ function submitForm(){
+ $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
+ $.post($form.attr('action'), $form.serialize() + '&do_save_data=1', function (data) {
+ if ($(".sqlqueryresults").length !== 0) {
+ $(".sqlqueryresults").remove();
+ } else if ($(".error:not(.tab)").length !== 0) {
+ $(".error:not(.tab)").remove();
+ }
+ if (typeof data.success != 'undefined' && data.success === true) {
+ $("#page_content")
+ .empty()
+ .append(data.message)
+ .show();
+ PMA_highlightSQL($('#page_content'));
+ $(".result_query .notice").remove();
+ reloadFieldForm();
+ $form.remove();
+ PMA_ajaxRemoveMessage($msg);
+ PMA_init_slider();
+ PMA_reloadNavigation();
+ } else {
+ PMA_ajaxShowMessage(data.error, false);
+ }
+ }); // end $.post()
+ }
+
+ function checkIfConfirmRequired($form, $field_cnt) {
+ var i = 0, id, elm, val, name_orig, elm_orig, val_orig;
+ var checkRequired = false;
+ for (i = 0; i < field_cnt; i++) {
+ id = "#field_" + i + "_5";
+ elm = $(id);
+ val = elm.val();
+
+ name_orig = "input[name=field_collation_orig\\[" + i + "\\]]";
+ elm_orig = $form.find(name_orig);
+ val_orig = elm_orig.val();
+
+ if (val && val_orig && val !== val_orig){
+ checkRequired = true;
+ break;
+ }
+ }
+ return checkRequired;
+ }
/*
* First validate the form; if there is a problem, avoid submitting it
@@ -110,34 +163,24 @@ AJAX.registerOnload('tbl_structure.js', function () {
* this is why we pass $form[0] as a parameter (the jQuery object
* is actually an array of DOM elements)
*/
- if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) {
+ if (checkTableEditForm($form[0], field_cnt)) {
// OK, form passed validation step
+
PMA_prepareForAjaxRequest($form);
if (PMA_checkReservedWordColumns($form)) {
//User wants to submit the form
- $msg = PMA_ajaxShowMessage();
- $.post($form.attr('action'), $form.serialize() + '&do_save_data=1', function (data) {
- if ($(".sqlqueryresults").length !== 0) {
- $(".sqlqueryresults").remove();
- } else if ($(".error:not(.tab)").length !== 0) {
- $(".error:not(.tab)").remove();
- }
- if (typeof data.success != 'undefined' && data.success === true) {
- $("#page_content")
- .empty()
- .append(data.message)
- .show();
- PMA_highlightSQL($('#page_content'));
- $(".result_query .notice").remove();
- reloadFieldForm();
- $form.remove();
- PMA_ajaxRemoveMessage($msg);
- PMA_init_slider();
- PMA_reloadNavigation();
- } else {
- PMA_ajaxShowMessage(data.error, false);
- }
- }); // end $.post()
+
+ // If Collation is changed, Warn and Confirm
+ if (checkIfConfirmRequired($form, field_cnt)){
+ var question = sprintf(
+ PMA_messages.strChangeColumnCollation, 'http://wiki.phpmyadmin.net/pma/Garbled_data'
+ );
+ $form.PMA_confirm(question, $form.attr('action'), function (url) {
+ submitForm();
+ });
+ } else {
+ submitForm();
+ }
}
}
}); // end change table button "do_save_data"
@@ -207,12 +250,22 @@ AJAX.registerOnload('tbl_structure.js', function () {
}); //end of Drop Column Anchor action
/**
+ * Attach Event Handler for 'Print View'
+ */
+ $(document).on('click', "#printView", function (event) {
+ event.preventDefault();
+
+ // Print the page
+ printPage();
+ }); //end of Print View action
+
+ /**
* Ajax Event handler for adding keys
*/
$(document).on('click', "a.add_key.ajax", function (event) {
event.preventDefault();
- $this = $(this);
+ var $this = $(this);
var curr_table_name = $this.closest('form').find('input[name=table]').val();
var curr_column_name = $this.parents('tr').children('th').children('label').text();
@@ -282,7 +335,9 @@ AJAX.registerOnload('tbl_structure.js', function () {
buttons: button_options_error
}); // end dialog options
} else {
- $('#fieldsForm ul.table-structure-actions').menuResizer('destroy');
+ if ($('#fieldsForm').hasClass('HideStructureActions')) {
+ $('#fieldsForm').find('ul.table-structure-actions').menuResizer('destroy');
+ }
// sort the fields table
var $fields_table = $("table#tablestructure tbody");
// remove all existing rows and remember them
@@ -308,7 +363,9 @@ AJAX.registerOnload('tbl_structure.js', function () {
}
PMA_ajaxShowMessage(data.message);
$this.dialog('close');
- $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ if ($('#fieldsForm').hasClass('HideStructureActions')) {
+ $('#fieldsForm').find('ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ }
}
});
};
@@ -323,7 +380,7 @@ AJAX.registerOnload('tbl_structure.js', function () {
var columns = [];
- $("#tablestructure tbody tr").each(function () {
+ $("#tablestructure").find("tbody tr").each(function () {
var col_name = $(this).find("input:checkbox").eq(0).val();
var hidden_input = $("<input/>")
.prop({
@@ -337,17 +394,17 @@ AJAX.registerOnload('tbl_structure.js', function () {
.append(hidden_input);
});
- var col_list = $("#move_columns_dialog ul")
+ var col_list = $("#move_columns_dialog").find("ul")
.find("li").remove().end();
for (var i in columns) {
col_list.append(columns[i]);
}
col_list.sortable({
axis: 'y',
- containment: $("#move_columns_dialog div"),
+ containment: $("#move_columns_dialog").find("div"),
tolerance: 'pointer'
}).disableSelection();
- var $form = $("#move_columns_dialog form");
+ var $form = $("#move_columns_dialog").find("form");
$form.data("serialized-unmoved", $form.serialize());
$("#move_columns_dialog").dialog({
@@ -370,28 +427,66 @@ AJAX.registerOnload('tbl_structure.js', function () {
$('body').on('click', '#fieldsForm.ajax button[name="submit_mult"], #fieldsForm.ajax input[name="submit_mult"]', function (e) {
e.preventDefault();
var $button = $(this);
- var $form = $button.parent('form');
+ var $form = $button.parents('form');
var submitData = $form.serialize() + '&ajax_request=true&ajax_page_request=true&submit_mult=' + $button.val();
PMA_ajaxShowMessage();
AJAX.source = $form;
$.post($form.attr('action'), submitData, AJAX.responseHandler);
});
+
+ /**
+ * Handles clicks on Action links in partition table
+ */
+ $(document).on('click', 'a[name^=partition_action].ajax', function (e) {
+ e.preventDefault();
+ var $link = $(this);
+
+ function submitPartitionAction(url) {
+ var submitData = '&ajax_request=true&ajax_page_request=true';
+ PMA_ajaxShowMessage();
+ AJAX.source = $link;
+ $.post(url, submitData, AJAX.responseHandler);
+ }
+
+ if ($link.is('#partition_action_DROP')) {
+ var question = PMA_messages.strDropPartitionWarning;
+ $link.PMA_confirm(question, $link.attr('href'), function (url) {
+ submitPartitionAction(url);
+ });
+ } else if ($link.is('#partition_action_TRUNCATE')) {
+ var question = PMA_messages.strTruncatePartitionWarning;
+ $link.PMA_confirm(question, $link.attr('href'), function (url) {
+ submitPartitionAction(url);
+ });
+ } else {
+ submitPartitionAction($link.attr('href'));
+ }
+ });
});
/** Handler for "More" dropdown in structure table rows */
AJAX.registerOnload('tbl_structure.js', function () {
if ($('#fieldsForm').hasClass('HideStructureActions')) {
- $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ $('#fieldsForm').find('ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ } else {
+ $('.table-structure-actions').width(function () {
+ var width = 5;
+ $(this).find('li').each(function () {
+ width += $(this).outerWidth(true);
+ });
+ return width;
+ });
}
});
AJAX.registerTeardown('tbl_structure.js', function () {
- $('#fieldsForm ul.table-structure-actions').menuResizer('destroy');
+ if ($('#fieldsForm').hasClass('HideStructureActions')) {
+ $('#fieldsForm').find('ul.table-structure-actions').menuResizer('destroy');
+ }
});
$(function () {
$(window).resize($.throttle(function () {
- var $list = $('#fieldsForm ul.table-structure-actions');
- if ($list.length) {
- $list.menuResizer('resize');
+ if ($('#fieldsForm').length && $('#fieldsForm').hasClass('HideStructureActions')) {
+ $('#fieldsForm').find('ul.table-structure-actions').menuResizer('resize');
}
}));
});
diff --git a/js/tbl_tracking.js b/js/tbl_tracking.js
index 48473e4be6..37e67220fa 100644
--- a/js/tbl_tracking.js
+++ b/js/tbl_tracking.js
@@ -60,10 +60,12 @@ AJAX.registerOnload('tbl_tracking.js', function () {
var question = PMA_messages.strDeleteTrackingVersionMultiple;
$button.PMA_confirm(question, $form.attr('action'), function (url) {
PMA_ajaxShowMessage();
+ AJAX.source = $form;
$.post(url, submitData, AJAX.responseHandler);
});
} else {
PMA_ajaxShowMessage();
+ AJAX.source = $form;
$.post($form.attr('action'), submitData, AJAX.responseHandler);
}
});
@@ -77,6 +79,7 @@ AJAX.registerOnload('tbl_tracking.js', function () {
var question = PMA_messages.strDeleteTrackingVersion;
$anchor.PMA_confirm(question, $anchor.attr('href'), function (url) {
PMA_ajaxShowMessage();
+ AJAX.source = $anchor;
$.get(url, {'ajax_page_request': true, 'ajax_request': true}, AJAX.responseHandler);
});
});
@@ -90,6 +93,7 @@ AJAX.registerOnload('tbl_tracking.js', function () {
var question = PMA_messages.strDeletingTrackingEntry;
$anchor.PMA_confirm(question, $anchor.attr('href'), function (url) {
PMA_ajaxShowMessage();
+ AJAX.source = $anchor;
$.get(url, {'ajax_page_request': true, 'ajax_request': true}, AJAX.responseHandler);
});
});
diff --git a/js/tbl_zoom_plot_jqplot.js b/js/tbl_zoom_plot_jqplot.js
index 235b067512..757275955f 100644
--- a/js/tbl_zoom_plot_jqplot.js
+++ b/js/tbl_zoom_plot_jqplot.js
@@ -12,7 +12,15 @@
** Display Help/Info
**/
function displayHelp() {
- PMA_ajaxShowMessage(PMA_messages.strDisplayHelp, 10000);
+ $('<div />')
+ .append(PMA_messages.strDisplayHelp)
+ .appendTo('#page_content')
+ .dialog({
+ width: 450,
+ height: 'auto',
+ title: PMA_messages.strHelpTitle
+ });
+ return false;
}
/**
@@ -166,10 +174,10 @@ AJAX.registerOnload('tbl_zoom_plot_jqplot.js', function () {
'it' : 0,
'token' : PMA_commonParams.get('token')
}, function (data) {
- $('#tableFieldsId tr:eq(1) td:eq(0)').html(data.field_type);
- $('#tableFieldsId tr:eq(1) td:eq(1)').html(data.field_collation);
- $('#tableFieldsId tr:eq(1) td:eq(2)').html(data.field_operators);
- $('#tableFieldsId tr:eq(1) td:eq(3)').html(data.field_value);
+ $('#tableFieldsId').find('tr:eq(1) td:eq(0)').html(data.field_type);
+ $('#tableFieldsId').find('tr:eq(1) td:eq(1)').html(data.field_collation);
+ $('#tableFieldsId').find('tr:eq(1) td:eq(2)').html(data.field_operators);
+ $('#tableFieldsId').find('tr:eq(1) td:eq(3)').html(data.field_value);
xLabel = $('#tableid_0').val();
$('#types_0').val(data.field_type);
xType = data.field_type;
@@ -191,10 +199,10 @@ AJAX.registerOnload('tbl_zoom_plot_jqplot.js', function () {
'it' : 1,
'token' : PMA_commonParams.get('token')
}, function (data) {
- $('#tableFieldsId tr:eq(3) td:eq(0)').html(data.field_type);
- $('#tableFieldsId tr:eq(3) td:eq(1)').html(data.field_collation);
- $('#tableFieldsId tr:eq(3) td:eq(2)').html(data.field_operators);
- $('#tableFieldsId tr:eq(3) td:eq(3)').html(data.field_value);
+ $('#tableFieldsId').find('tr:eq(3) td:eq(0)').html(data.field_type);
+ $('#tableFieldsId').find('tr:eq(3) td:eq(1)').html(data.field_collation);
+ $('#tableFieldsId').find('tr:eq(3) td:eq(2)').html(data.field_operators);
+ $('#tableFieldsId').find('tr:eq(3) td:eq(3)').html(data.field_value);
yLabel = $('#tableid_1').val();
$('#types_1').val(data.field_type);
yType = data.field_type;
@@ -215,10 +223,10 @@ AJAX.registerOnload('tbl_zoom_plot_jqplot.js', function () {
'it' : 2,
'token' : PMA_commonParams.get('token')
}, function (data) {
- $('#tableFieldsId tr:eq(6) td:eq(0)').html(data.field_type);
- $('#tableFieldsId tr:eq(6) td:eq(1)').html(data.field_collation);
- $('#tableFieldsId tr:eq(6) td:eq(2)').html(data.field_operators);
- $('#tableFieldsId tr:eq(6) td:eq(3)').html(data.field_value);
+ $('#tableFieldsId').find('tr:eq(6) td:eq(0)').html(data.field_type);
+ $('#tableFieldsId').find('tr:eq(6) td:eq(1)').html(data.field_collation);
+ $('#tableFieldsId').find('tr:eq(6) td:eq(2)').html(data.field_operators);
+ $('#tableFieldsId').find('tr:eq(6) td:eq(3)').html(data.field_value);
$('#types_2').val(data.field_type);
$('#collations_2').val(data.field_collations);
addDateTimePicker();
@@ -237,10 +245,10 @@ AJAX.registerOnload('tbl_zoom_plot_jqplot.js', function () {
'it' : 3,
'token' : PMA_commonParams.get('token')
}, function (data) {
- $('#tableFieldsId tr:eq(8) td:eq(0)').html(data.field_type);
- $('#tableFieldsId tr:eq(8) td:eq(1)').html(data.field_collation);
- $('#tableFieldsId tr:eq(8) td:eq(2)').html(data.field_operators);
- $('#tableFieldsId tr:eq(8) td:eq(3)').html(data.field_value);
+ $('#tableFieldsId').find('tr:eq(8) td:eq(0)').html(data.field_type);
+ $('#tableFieldsId').find('tr:eq(8) td:eq(1)').html(data.field_collation);
+ $('#tableFieldsId').find('tr:eq(8) td:eq(2)').html(data.field_operators);
+ $('#tableFieldsId').find('tr:eq(8) td:eq(3)').html(data.field_value);
$('#types_3').val(data.field_type);
$('#collations_3').val(data.field_collations);
addDateTimePicker();
@@ -612,8 +620,8 @@ AJAX.registerOnload('tbl_zoom_plot_jqplot.js', function () {
// now fill the displayResultForm with row values
var key;
for (key in data.row_info) {
- $field = $('#edit_fieldID_' + field_id);
- $field_null = $('#edit_fields_null_id_' + field_id);
+ var $field = $('#edit_fieldID_' + field_id);
+ var $field_null = $('#edit_fields_null_id_' + field_id);
if (data.row_info[key] === null) {
$field_null.prop('checked', true);
$field.val('');
diff --git a/js/transformations/json_editor.js b/js/transformations/json_editor.js
index 8912e647b5..040d5f325f 100644
--- a/js/transformations/json_editor.js
+++ b/js/transformations/json_editor.js
@@ -5,8 +5,8 @@
* @package PhpMyAdmin
*/
AJAX.registerOnload('transformations/json_editor.js', function() {
- $.each($('textarea.transform_json_editor'), function (i, e) {
- CodeMirror.fromTextArea(e, {
+ $('textarea.transform_json_editor').each(function () {
+ CodeMirror.fromTextArea(this, {
lineNumbers: true,
matchBrackets: true,
indentUnit: 4,
diff --git a/js/transformations/sql_editor.js b/js/transformations/sql_editor.js
index 3c7b305a43..83e560e88d 100644
--- a/js/transformations/sql_editor.js
+++ b/js/transformations/sql_editor.js
@@ -6,25 +6,7 @@
*/
AJAX.registerOnload('transformations/sql_editor.js', function() {
- $.each($('textarea.transform_sql_editor'), function (i, e) {
- var height = $(e).css('height');
- var codemirror_editor = CodeMirror.fromTextArea(e, {
- lineNumbers: true,
- matchBrackets: true,
- extraKeys: {"Ctrl-Space": "autocomplete"},
- hintOptions: {"completeSingle": false, "completeOnSingleClick": true},
- indentUnit: 4,
- mode: "text/x-mysql",
- lineWrapping: true
- });
- codemirror_editor.on("inputRead", codemirrorAutocompleteOnInputRead);
- codemirror_editor.getScrollerElement().style.height = height;
- codemirror_editor.refresh();
- codemirror_editor.focus();
- $(codemirror_editor.getWrapperElement()).bind(
- 'keydown',
- catchKeypressesFromSqlTextboxes
- );
+ $('textarea.transform_sql_editor').each(function () {
+ PMA_getSQLEditor($(this), {}, 'both');
});
-
});
diff --git a/js/transformations/xml_editor.js b/js/transformations/xml_editor.js
index c10b8f845c..4492b9e730 100644
--- a/js/transformations/xml_editor.js
+++ b/js/transformations/xml_editor.js
@@ -5,8 +5,8 @@
* @package PhpMyAdmin
*/
AJAX.registerOnload('transformations/xml_editor.js', function() {
- $.each($('textarea.transform_xml_editor'), function (i, e) {
- CodeMirror.fromTextArea(e, {
+ $('textarea.transform_xml_editor').each( function () {
+ CodeMirror.fromTextArea(this, {
lineNumbers: true,
indentUnit: 4,
mode: "application/xml",
diff --git a/js/whitelist.php b/js/whitelist.php
index af9ec56fcf..ead8c146ce 100644
--- a/js/whitelist.php
+++ b/js/whitelist.php
@@ -25,9 +25,11 @@ session_write_close();
require_once './libraries/OutputBuffering.class.php';
$buffer = PMA_OutputBuffering::getInstance();
$buffer->start();
-register_shutdown_function(function() {
- echo PMA_OutputBuffering::getInstance()->getContents();
-});
+register_shutdown_function(
+ function () {
+ echo PMA_OutputBuffering::getInstance()->getContents();
+ }
+);
echo "var PMA_gotoWhitelist = new Array();\n";
$i = -1;
@@ -35,4 +37,3 @@ foreach ($GLOBALS['goto_whitelist'] as $one_whitelist) {
$i++;
echo 'PMA_gotoWhitelist[' . $i . ']="' . $one_whitelist . '";' . "\n";
}
-?>
diff --git a/libraries/Advisor.class.php b/libraries/Advisor.class.php
index 41612bdbed..6ae5cfe050 100644
--- a/libraries/Advisor.class.php
+++ b/libraries/Advisor.class.php
@@ -176,7 +176,7 @@ class Advisor
public function translate($str, $param = null)
{
$string = _gettext(Advisor::escapePercent($str));
- if ( ! is_null($param)) {
+ if (! is_null($param)) {
$params = $this->ruleExprEvaluate('array(' . $param . ')');
} else {
$params = array();
@@ -522,5 +522,3 @@ function ADVISOR_formatByteDown($value, $limes = 6, $comma = 0)
{
return implode(' ', PMA_Util::formatByteDown($value, $limes, $comma));
}
-
-?>
diff --git a/libraries/Config.class.php b/libraries/Config.class.php
index 790f54eb10..6d5d3eb41c 100644
--- a/libraries/Config.class.php
+++ b/libraries/Config.class.php
@@ -91,7 +91,7 @@ class PMA_Config
*
* @param string $source source to read config from
*/
- function __construct($source = null)
+ public function __construct($source = null)
{
$this->settings = array();
@@ -112,9 +112,9 @@ class PMA_Config
*
* @return void
*/
- function checkSystem()
+ public function checkSystem()
{
- $this->set('PMA_VERSION', '4.4.15');
+ $this->set('PMA_VERSION', '4.5.0.1');
/**
* @deprecated
*/
@@ -139,7 +139,7 @@ class PMA_Config
*
* @return void
*/
- function checkOutputCompression()
+ public function checkOutputCompression()
{
// If zlib output compression is set in the php configuration file, no
// output buffering should be run
@@ -161,6 +161,30 @@ class PMA_Config
}
/**
+ * Sets the client platform based on user agent
+ *
+ * @param string $user_agent the user agent
+ *
+ * @return void
+ */
+ private function _setClientPlatform($user_agent)
+ {
+ if (/*overload*/mb_strstr($user_agent, 'Win')) {
+ $this->set('PMA_USR_OS', 'Win');
+ } elseif (/*overload*/mb_strstr($user_agent, 'Mac')) {
+ $this->set('PMA_USR_OS', 'Mac');
+ } elseif (/*overload*/mb_strstr($user_agent, 'Linux')) {
+ $this->set('PMA_USR_OS', 'Linux');
+ } elseif (/*overload*/mb_strstr($user_agent, 'Unix')) {
+ $this->set('PMA_USR_OS', 'Unix');
+ } elseif (/*overload*/mb_strstr($user_agent, 'OS/2')) {
+ $this->set('PMA_USR_OS', 'OS/2');
+ } else {
+ $this->set('PMA_USR_OS', 'Other');
+ }
+ }
+
+ /**
* Determines platform (OS), browser and version of the user
* Based on a phpBuilder article:
*
@@ -168,7 +192,7 @@ class PMA_Config
*
* @return void
*/
- function checkClient()
+ public function checkClient()
{
if (PMA_getenv('HTTP_USER_AGENT')) {
$HTTP_USER_AGENT = PMA_getenv('HTTP_USER_AGENT');
@@ -177,19 +201,7 @@ class PMA_Config
}
// 1. Platform
- if (/*overload*/mb_strstr($HTTP_USER_AGENT, 'Win')) {
- $this->set('PMA_USR_OS', 'Win');
- } elseif (/*overload*/mb_strstr($HTTP_USER_AGENT, 'Mac')) {
- $this->set('PMA_USR_OS', 'Mac');
- } elseif (/*overload*/mb_strstr($HTTP_USER_AGENT, 'Linux')) {
- $this->set('PMA_USR_OS', 'Linux');
- } elseif (/*overload*/mb_strstr($HTTP_USER_AGENT, 'Unix')) {
- $this->set('PMA_USR_OS', 'Unix');
- } elseif (/*overload*/mb_strstr($HTTP_USER_AGENT, 'OS/2')) {
- $this->set('PMA_USR_OS', 'OS/2');
- } else {
- $this->set('PMA_USR_OS', 'Other');
- }
+ $this->_setClientPlatform($HTTP_USER_AGENT);
// 2. browser and version
// (must check everything else before Mozilla)
@@ -284,7 +296,7 @@ class PMA_Config
*
* @return void
*/
- function checkGd2()
+ public function checkGd2()
{
if ($this->get('GD2Available') == 'yes') {
$this->set('PMA_IS_GD2', 1);
@@ -318,7 +330,7 @@ class PMA_Config
*
* @return void
*/
- function checkWebServer()
+ public function checkWebServer()
{
// some versions return Microsoft-IIS, some Microsoft/IIS
// we could use a preg_match() but it's slower
@@ -337,7 +349,7 @@ class PMA_Config
*
* @return void
*/
- function checkWebServerOs()
+ public function checkWebServerOs()
{
// Default to Unix or Equiv
$this->set('PMA_IS_WINDOWS', 0);
@@ -358,7 +370,7 @@ class PMA_Config
*
* @return void
*/
- function checkPhpVersion()
+ public function checkPhpVersion()
{
$match = array();
if (! preg_match(
@@ -394,8 +406,12 @@ class PMA_Config
*
* @return boolean
*/
- function isGitRevision()
+ public function isGitRevision()
{
+ if (!$this->get('ShowGitRevision')) {
+ return false;
+ }
+
// caching
if (isset($_SESSION['is_git_revision'])) {
if ($_SESSION['is_git_revision']) {
@@ -420,7 +436,7 @@ class PMA_Config
*
* @return void
*/
- function checkGitRevision()
+ public function checkGitRevision()
{
// find out if there is a .git folder
$git_folder = '.git';
@@ -746,22 +762,27 @@ class PMA_Config
*
* @return string|boolean test result or data
*/
- function checkHTTP($link, $get_body = false)
+ public function checkHTTP($link, $get_body = false)
{
if (! function_exists('curl_init')) {
return null;
}
- $ch = curl_init($link);
- PMA_Util::configureCurl($ch);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
- curl_setopt($ch, CURLOPT_HEADER, 1);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
- curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+ $handle = curl_init($link);
+ if ($handle === false) {
+ return null;
+ }
+ PMA_Util::configureCurl($handle);
+ curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 0);
+ curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0);
+ curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
+ curl_setopt($handle, CURLOPT_TIMEOUT, 5);
+ curl_setopt($handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
if (! defined('TESTSUITE')) {
session_write_close();
}
- $data = @curl_exec($ch);
+ $data = @curl_exec($handle);
if (! defined('TESTSUITE')) {
ini_set('session.use_only_cookies', '0');
ini_set('session.use_cookies', '0');
@@ -772,24 +793,13 @@ class PMA_Config
if ($data === false) {
return null;
}
- $httpOk = 'HTTP/1.1 200 OK';
- $httpNotFound = 'HTTP/1.1 404 Not Found';
+ $http_status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
- if (substr($data, 0, strlen($httpOk)) === $httpOk) {
- return $get_body
- ? /*overload*/mb_substr(
- $data,
- /*overload*/mb_strpos($data, "\r\n\r\n") + 4
- )
- : true;
+ if ($http_status == 200) {
+ return $get_body ? $data : true;
}
- $httpNOK = substr(
- $data,
- 0,
- strlen($httpNotFound)
- );
- if ($httpNOK === $httpNotFound) {
+ if ($http_status == 404) {
return false;
}
return null;
@@ -800,7 +810,7 @@ class PMA_Config
*
* @return boolean success
*/
- function loadDefaults()
+ public function loadDefaults()
{
$cfg = array();
if (! file_exists($this->default_source)) {
@@ -830,7 +840,7 @@ class PMA_Config
*
* @return bool
*/
- function load($source = null)
+ public function load($source = null)
{
$this->loadDefaults();
@@ -909,12 +919,54 @@ class PMA_Config
}
/**
+ * Saves the connection collation
+ *
+ * @param array $config_data configuration data from user preferences
+ *
+ * @return void
+ */
+ private function _saveConnectionCollation($config_data)
+ {
+ if (!PMA_DRIZZLE) {
+ // just to shorten the lines
+ $collation = 'collation_connection';
+ if (isset($GLOBALS[$collation])
+ && (isset($_COOKIE['pma_collation_connection'])
+ || isset($_POST[$collation]))
+ ) {
+ if ((! isset($config_data[$collation])
+ && $GLOBALS[$collation] != 'utf8_general_ci')
+ || isset($config_data[$collation])
+ && $GLOBALS[$collation] != $config_data[$collation]
+ ) {
+ $this->setUserValue(
+ null,
+ $collation,
+ $GLOBALS[$collation],
+ 'utf8_general_ci'
+ );
+ }
+ } else {
+ // read collation from settings
+ if (isset($config_data[$collation])) {
+ $GLOBALS[$collation]
+ = $config_data[$collation];
+ $this->setCookie(
+ 'pma_collation_connection',
+ $GLOBALS[$collation]
+ );
+ }
+ }
+ }
+ }
+
+ /**
* Loads user preferences and merges them with current config
* must be called after control connection has been established
*
* @return void
*/
- function loadUserPreferences()
+ public function loadUserPreferences()
{
// index.php should load these settings, so that phpmyadmin.css.php
// will have everything available in session cache
@@ -973,6 +1025,7 @@ class PMA_Config
// in frames
// save theme
+ /** @var PMA_Theme_Manager $tmanager */
$tmanager = $_SESSION['PMA_Theme_Manager'];
if ($tmanager->getThemeCookie() || isset($_REQUEST['set_theme'])) {
if ((! isset($config_data['ThemeDefault'])
@@ -1024,37 +1077,7 @@ class PMA_Config
}
// save connection collation
- if (!PMA_DRIZZLE) {
- // just to shorten the lines
- $collation = 'collation_connection';
- if (isset($GLOBALS[$collation])
- && (isset($_COOKIE['pma_collation_connection'])
- || isset($_POST[$collation]))
- ) {
- if ((! isset($config_data[$collation])
- && $GLOBALS[$collation] != 'utf8_general_ci')
- || isset($config_data[$collation])
- && $GLOBALS[$collation] != $config_data[$collation]
- ) {
- $this->setUserValue(
- null,
- $collation,
- $GLOBALS[$collation],
- 'utf8_general_ci'
- );
- }
- } else {
- // read collation from settings
- if (isset($config_data['collation_connection'])) {
- $GLOBALS['collation_connection']
- = $config_data['collation_connection'];
- $this->setCookie(
- 'pma_collation_connection',
- $GLOBALS['collation_connection']
- );
- }
- }
- }
+ $this->_saveConnectionCollation($config_data);
}
/**
@@ -1072,7 +1095,7 @@ class PMA_Config
*
* @return void
*/
- function setUserValue($cookie_name, $cfg_path, $new_cfg_value,
+ public function setUserValue($cookie_name, $cfg_path, $new_cfg_value,
$default_value = null
) {
// use permanent user preferences if possible
@@ -1103,7 +1126,7 @@ class PMA_Config
*
* @return mixed
*/
- function getUserValue($cookie_name, $cfg_value)
+ public function getUserValue($cookie_name, $cfg_value)
{
$cookie_exists = isset($_COOKIE) && !empty($_COOKIE[$cookie_name]);
$prefs_type = $this->get('user_preferences');
@@ -1126,7 +1149,7 @@ class PMA_Config
*
* @return void
*/
- function setSource($source)
+ public function setSource($source)
{
$this->source = trim($source);
}
@@ -1136,7 +1159,7 @@ class PMA_Config
*
* @return boolean whether source is valid or not
*/
- function checkConfigSource()
+ public function checkConfigSource()
{
if (! $this->getSource()) {
// no configuration file set at all
@@ -1181,7 +1204,7 @@ class PMA_Config
*
* @return void
*/
- function checkPermissions()
+ public function checkPermissions()
{
// Check for permissions (on platforms that support it):
if ($this->get('CheckConfigurationPermissions')) {
@@ -1209,7 +1232,7 @@ class PMA_Config
*
* @return mixed value
*/
- function get($setting)
+ public function get($setting)
{
if (isset($this->settings[$setting])) {
return $this->settings[$setting];
@@ -1225,7 +1248,7 @@ class PMA_Config
*
* @return void
*/
- function set($setting, $value)
+ public function set($setting, $value)
{
if (! isset($this->settings[$setting])
|| $this->settings[$setting] !== $value
@@ -1240,7 +1263,7 @@ class PMA_Config
*
* @return string config source
*/
- function getSource()
+ public function getSource()
{
return $this->source;
}
@@ -1254,7 +1277,7 @@ class PMA_Config
* @return int Summary of unix timestamps and fontsize,
* to be unique on theme parameters change
*/
- function getThemeUniqueValue()
+ public function getThemeUniqueValue()
{
if (null !== $this->get('fontsize')) {
$fontsize = intval($this->get('fontsize'));
@@ -1279,7 +1302,7 @@ class PMA_Config
*
* @return void
*/
- function checkPmaAbsoluteUri()
+ public function checkPmaAbsoluteUri()
{
// Setup a default value to let the people and lazy sysadmins work anyway,
// they'll get an error if the autodetect code doesn't work
@@ -1349,8 +1372,10 @@ class PMA_Config
// Add hostname
$pma_absolute_uri .= $url['host'];
// Add port, if it not the default one
+ // (or 80 for https which is most likely a bug)
if (! empty($url['port'])
&& (($url['scheme'] == 'http' && $url['port'] != 80)
+ || ($url['scheme'] == 'https' && $url['port'] != 80)
|| ($url['scheme'] == 'https' && $url['port'] != 443))
) {
$pma_absolute_uri .= ':' . $url['port'];
@@ -1432,7 +1457,7 @@ class PMA_Config
*
* @return String witch adjusted URI
*/
- function getSSLUri()
+ public function getSSLUri()
{
// grab current URL
$url = $this->get('PmaAbsoluteUri');
@@ -1459,7 +1484,7 @@ class PMA_Config
*
* @return void
*/
- function checkCollationConnection()
+ public function checkCollationConnection()
{
if (! empty($_REQUEST['collation_connection'])) {
$collation = strip_tags($_REQUEST['collation_connection']);
@@ -1476,7 +1501,7 @@ class PMA_Config
*
* @return void
*/
- function checkFontsize()
+ public function checkFontsize()
{
$new_fontsize = '';
@@ -1504,7 +1529,7 @@ class PMA_Config
*
* @return void
*/
- function checkUpload()
+ public function checkUpload()
{
if (!ini_get('file_uploads')) {
$this->set('enable_upload', false);
@@ -1527,7 +1552,7 @@ class PMA_Config
*
* @return void
*/
- function checkUploadSize()
+ public function checkUploadSize()
{
if (! $filesize = ini_get('upload_max_filesize')) {
$filesize = "5M";
@@ -1578,7 +1603,7 @@ class PMA_Config
*
* @return bool
*/
- function detectHttps()
+ public function detectHttps()
{
$url = array();
@@ -1633,7 +1658,7 @@ class PMA_Config
*
* @return void
*/
- function checkCookiePath()
+ public function checkCookiePath()
{
$this->set('cookie_path', $this->getCookiePath());
}
@@ -1663,7 +1688,7 @@ class PMA_Config
*
* @return void
*/
- function enableBc()
+ public function enableBc()
{
$GLOBALS['cfg'] = $this->settings;
$GLOBALS['default_server'] = $this->default_server;
@@ -1701,10 +1726,8 @@ class PMA_Config
* @param string $current_size current selected font size with unit
*
* @return array selectable font sizes
- *
- * @static
*/
- static protected function getFontsizeOptions($current_size = '82%')
+ protected static function getFontsizeOptions($current_size = '82%')
{
$unit = preg_replace('/[0-9.]*/', '', $current_size);
$value = preg_replace('/[^0-9.]*/', '', $current_size);
@@ -1761,11 +1784,9 @@ class PMA_Config
/**
* returns html selectbox for font sizes
*
- * @static
- *
* @return string html selectbox
*/
- static protected function getFontsizeSelection()
+ protected static function getFontsizeSelection()
{
$current_size = $GLOBALS['PMA_Config']->get('fontsize');
// for the case when there is no config file (this is supported)
@@ -1797,11 +1818,9 @@ class PMA_Config
/**
* return complete font size selection form
*
- * @static
- *
* @return string html selectbox
*/
- static public function getFontsizeForm()
+ public static function getFontsizeForm()
{
return '<form name="form_fontsize_selection" id="form_fontsize_selection"'
. ' method="get" action="index.php" class="disableAjax">' . "\n"
@@ -1817,7 +1836,7 @@ class PMA_Config
*
* @return boolean result of setcookie()
*/
- function removeCookie($cookie)
+ public function removeCookie($cookie)
{
if (defined('TESTSUITE')) {
if (isset($_COOKIE[$cookie])) {
@@ -1847,8 +1866,8 @@ class PMA_Config
*
* @return boolean result of setcookie()
*/
- function setCookie($cookie, $value, $default = null, $validity = null,
- $httponly = true
+ public function setCookie($cookie, $value, $default = null,
+ $validity = null, $httponly = true
) {
if (/*overload*/mb_strlen($value) && null !== $default && $value === $default
) {
@@ -1922,5 +1941,3 @@ function PMA_Config_fatalErrorHandler()
if (!defined('TESTSUITE')) {
register_shutdown_function('PMA_Config_fatalErrorHandler');
}
-
-?>
diff --git a/libraries/Console.class.php b/libraries/Console.class.php
index 2c9baa5266..2ab28fc28f 100644
--- a/libraries/Console.class.php
+++ b/libraries/Console.class.php
@@ -56,7 +56,7 @@ class PMA_Console
*/
public function setAjax($isAjax)
{
- $this->_isAjax = ($isAjax == true);
+ $this->_isAjax = !!$isAjax;
}
/**
@@ -123,7 +123,7 @@ class PMA_Console
}
unset($count_bookmarks, $private_message, $shared_message);
$output .= '</span></div>';
- foreach ($bookmarks as $key => $val) {
+ foreach ($bookmarks as $val) {
$output .= '<div class="message collapsed bookmark" bookmarkid="'
. $val['id'] . '" targetdb="' . htmlspecialchars($val['db'])
. '"><div class="action_content">'
@@ -150,6 +150,48 @@ class PMA_Console
}
/**
+ * Gets the history
+ *
+ * @param string $tpl_query_actions the template for query actions
+ *
+ * @return string $output the generated HTML for history
+ *
+ * @access private
+ *
+ */
+ private function _getHistory($tpl_query_actions)
+ {
+ $output = '';
+
+ $_sql_history = PMA_getHistory($GLOBALS['cfg']['Server']['user']);
+ if (! empty($_sql_history)) {
+ foreach (array_reverse($_sql_history) as $record) {
+ $isSelect = preg_match(
+ '@^SELECT[[:space:]]+@i', $record['sqlquery']
+ );
+ $output .= '<div class="message history collapsed hide'
+ . ($isSelect ? ' select' : '')
+ . '" targetdb="'
+ . htmlspecialchars($record['db'])
+ . '" targettable="' . htmlspecialchars($record['table'])
+ . '"><div class="action_content">'
+ . sprintf(
+ $tpl_query_actions,
+ htmlspecialchars($record['db']),
+ (isset($record['timevalue'])
+ ? $record['timevalue']
+ : __('During current session')
+ )
+ )
+ . '</div><span class="query">'
+ . htmlspecialchars($record['sqlquery'])
+ . '</span></div>';
+ }
+ }
+ return $output;
+ }
+
+ /**
* Renders the console
*
* @access public
@@ -202,41 +244,22 @@ class PMA_Console
. __('Bookmarks') . '</span></div>';
}
+ $output .= '<div class="button debug hide"><span>'
+ . __('Debug SQL') . '</span></div>';
+
$output .= '</div>'; // Toolbar end
// Console messages
$output .= '<div class="content">';
$output .= '<div class="console_message_container">'
. '<div class="message welcome"><span>'
- . __('Press Ctrl+Enter to execute query')
+ . '<span id="instructions-0">'
+ . __('Press Ctrl+Enter to execute query') . '</span>'
+ . '<span class="hide" id="instructions-1">'
+ . __('Press Enter to execute query') . '</span>'
. '</span></div>';
- // History support
- $_sql_history = PMA_getHistory($GLOBALS['cfg']['Server']['user']);
- if ($_sql_history) {
- foreach (array_reverse($_sql_history) as $record) {
- $isSelect = preg_match(
- '@^SELECT[[:space:]]+@i', $record['sqlquery']
- );
- $output .= '<div class="message history collapsed hide'
- . ($isSelect ? ' select' : '')
- . '" targetdb="'
- . htmlspecialchars($record['db'])
- . '" targettable="' . htmlspecialchars($record['table'])
- . '"><div class="action_content">'
- . sprintf(
- $tpl_query_actions,
- htmlspecialchars($record['db']),
- (isset($record['timevalue'])
- ? $record['timevalue']
- : __('During current session')
- )
- )
- . '</div><span class="query">'
- . htmlspecialchars($record['sqlquery'])
- . '</span></div>';
- }
- }
+ $output .= $this->_getHistory($tpl_query_actions);
$output .= '</div>'; // .console_message_container
$output .= '<div class="query_input">'
@@ -247,6 +270,60 @@ class PMA_Console
// Dark the console while other cards cover it
$output .= '<div class="mid_layer"></div>';
+ // Debug SQL card
+ $output .= '<div class="card" id="debug_console">';
+ $output .= '<div class="toolbar">'
+ . '<div class="button order order_asc">'
+ . '<span>' . __('ascending') . '</span>'
+ . '</div>'
+ . '<div class="button order order_desc">'
+ . '<span>' . __('descending') . '</span>'
+ . '</div>'
+ . '<div class="text">'
+ . '<span>' . __('Order:') . '</span>'
+ . '</div>'
+ . '<div class="switch_button">'
+ . '<span>' . __('Debug SQL') . '</span>'
+ . '</div>'
+ . '<div class="button order_by sort_count">'
+ . '<span>' . __('Count') . '</span>'
+ . '</div>'
+ . '<div class="button order_by sort_exec">'
+ . '<span>' . __('Execution order') . '</span>'
+ . '</div>'
+ . '<div class="button order_by sort_time">'
+ . '<span>' . __('Time taken') . '</span>'
+ . '</div>'
+ . '<div class="text">'
+ . '<span>' . __('Order by:') . '</span>'
+ . '</div>'
+ . '<div class="button group_queries">'
+ . '<span>' . __('Group queries') . '</span>'
+ . '</div>'
+ . '<div class="button ungroup_queries">'
+ . '<span>' . __('Ungroup queries') . '</span>'
+ . '</div>'
+ . '</div>'; // Toolbar
+ $output .= '<div class="content debug">';
+ $output .= '<div class="message welcome"></div>';
+ $output .= '<div class="debugLog"></div>';
+ $output .= '</div>'; // Content
+ $output .= '<div class="templates">'
+ . '<div class="debug_query action_content">'
+ . '<span class="action collapse">' . __('Collapse') . '</span> '
+ . '<span class="action expand">' . __('Expand') . '</span> '
+ . '<span class="action dbg_show_trace">' . __('Show trace')
+ . '</span> '
+ . '<span class="action dbg_hide_trace">' . __('Hide trace')
+ . '</span> '
+ . '<span class="text count hide">' . __('Count:')
+ . ' <span></span></span>'
+ . '<span class="text time">' . __('Time taken:')
+ . ' <span></span></span>'
+ . '</div>'
+ . '</div>'; // Template
+ $output .= '</div>'; // Debug SQL card
+
// Bookmarks card:
if ($cfgBookmark) {
@@ -303,6 +380,13 @@ class PMA_Console
. __('Show query history at start') . '</label><br>'
. '<label><input type="checkbox" name="current_query">'
. __('Show current browsing query') . '</label><br>'
+ . '<label><input type="checkbox" name="enter_executes">'
+ . __(
+ 'Execute queries on Enter and insert new line with Shift + '
+ . 'Enter. To make this permanent, view settings.'
+ ) . '</label><br>'
+ . '<label><input type="checkbox" name="dark_theme">'
+ . __('Switch to dark theme') . '</label><br>'
. '</div>';
$output .= '</div>'; // Options card
diff --git a/libraries/DBQbe.class.php b/libraries/DBQbe.class.php
index 085ae10006..86cdba0dc2 100644
--- a/libraries/DBQbe.class.php
+++ b/libraries/DBQbe.class.php
@@ -129,6 +129,13 @@ class PMA_DbQbe
*/
private $_curField;
/**
+ * Current alias
+ *
+ * @access private
+ * @var array
+ */
+ private $_curAlias;
+ /**
* Current criteria Sort options
*
* @access private
@@ -136,6 +143,13 @@ class PMA_DbQbe
*/
private $_curSort;
/**
+ * Current criteria sort order
+ *
+ * @access private
+ * @var array
+ */
+ private $_curSortOrder;
+ /**
* Current criteria Show options
*
* @access private
@@ -399,6 +413,50 @@ class PMA_DbQbe
}
/**
+ * Provides select options list containing sort order
+ *
+ * @param integer $columnNumber Column Number (0,1,2) or more
+ * @param integer $sortOrder Sort order
+ *
+ * @return string HTML for select options
+ */
+ private function _getSortOrderSelectCell($columnNumber, $sortOrder)
+ {
+ $totalColumnCount = $this->_getNewColumnCount();
+ $html_output = '<td class="center">';
+ $html_output .= '<select name="criteriaSortOrder[' . $columnNumber . ']">';
+ $html_output .= '<option value="1000">'
+ . '&nbsp;</option>';
+ for ($a = 1; $a <= $totalColumnCount; $a++) {
+ $html_output .= '<option value="' . $a . '"';
+ if ($a == $sortOrder) {
+ $html_output .= ' selected="selected"';
+ }
+ $html_output .= '>' . $a . '</option>';
+ }
+ $html_output .= '</select>';
+ $html_output .= '</td>';
+ return $html_output;
+ }
+
+ /**
+ * Returns the new column count after adding and removing columns as instructed
+ *
+ * @return int new column count
+ */
+ private function _getNewColumnCount()
+ {
+ $totalColumnCount = $this->_criteria_column_count;
+ if (! empty($this->_criteriaColumnInsert)) {
+ $totalColumnCount += count($this->_criteriaColumnInsert);
+ }
+ if (! empty($this->_criteriaColumnDelete)) {
+ $totalColumnCount -= count($this->_criteriaColumnDelete);
+ }
+ return $totalColumnCount;
+ }
+
+ /**
* Provides search form's row containing column select options
*
* @return string HTML for search table's row
@@ -445,6 +503,59 @@ class PMA_DbQbe
}
/**
+ * Provides search form's row containing column aliases
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getColumnAliasRow()
+ {
+ $html_output = '<tr class="even noclick">';
+ $html_output .= '<th>' . __('Alias:') . '</th>';
+ $new_column_count = 0;
+
+ for (
+ $colInd = 0;
+ $colInd < $this->_criteria_column_count;
+ $colInd++
+ ) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$colInd])
+ && $this->_criteriaColumnInsert[$colInd] == 'on'
+ ) {
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="criteriaAlias[' . $new_column_count . ']"'
+ . ' value="" />';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end if
+
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$colInd])
+ && $this->_criteriaColumnDelete[$colInd] == 'on'
+ ) {
+ continue;
+ }
+
+ $tmp_alias = '';
+ if (! empty($_REQUEST['criteriaAlias'][$colInd])) {
+ $tmp_alias
+ = $this->_curAlias[$new_column_count]
+ = $_REQUEST['criteriaAlias'][$colInd];
+ }// end if
+
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="criteriaAlias[' . $new_column_count . ']"'
+ . ' value="' . htmlspecialchars($tmp_alias) . '" />';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
* Provides search form's row containing sort(ASC/DESC) select options
*
* @return string HTML for search table's row
@@ -482,26 +593,23 @@ class PMA_DbQbe
) {
$_REQUEST['criteriaSort'][$colInd] = '';
} //end if
- // Set asc_selected
- if (isset($_REQUEST['criteriaSort'][$colInd])
- && $_REQUEST['criteriaSort'][$colInd] == 'ASC'
- ) {
- $this->_curSort[$new_column_count]
- = $_REQUEST['criteriaSort'][$colInd];
- $asc_selected = ' selected="selected"';
- } else {
- $asc_selected = '';
- } // end if
- // Set desc selected
- if (isset($_REQUEST['criteriaSort'][$colInd])
- && $_REQUEST['criteriaSort'][$colInd] == 'DESC'
- ) {
+
+ $asc_selected = ''; $desc_selected = '';
+ if (isset($_REQUEST['criteriaSort'][$colInd])) {
$this->_curSort[$new_column_count]
= $_REQUEST['criteriaSort'][$colInd];
- $desc_selected = ' selected="selected"';
+ // Set asc_selected
+ if ($_REQUEST['criteriaSort'][$colInd] == 'ASC') {
+ $asc_selected = ' selected="selected"';
+ } // end if
+ // Set desc selected
+ if ($_REQUEST['criteriaSort'][$colInd] == 'DESC') {
+ $desc_selected = ' selected="selected"';
+ } // end if
} else {
- $desc_selected = '';
- } // end if
+ $this->_curSort[$new_column_count] = '';
+ }
+
$html_output .= $this->_getSortSelectCell(
$new_column_count, $asc_selected, $desc_selected
);
@@ -512,6 +620,55 @@ class PMA_DbQbe
}
/**
+ * Provides search form's row containing sort order
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getSortOrder()
+ {
+ $html_output = '<tr class="even noclick">';
+ $html_output .= '<th>' . __('Sort order:') . '</th>';
+ $new_column_count = 0;
+
+ for (
+ $colInd = 0;
+ $colInd < $this->_criteria_column_count;
+ $colInd++
+ ) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$colInd])
+ && $this->_criteriaColumnInsert[$colInd] == 'on'
+ ) {
+ $html_output .= $this->_getSortOrderSelectCell(
+ $new_column_count, null
+ );
+ $new_column_count++;
+ } // end if
+
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$colInd])
+ && $this->_criteriaColumnDelete[$colInd] == 'on'
+ ) {
+ continue;
+ }
+
+ $sortOrder = null;
+ if (! empty($_REQUEST['criteriaSortOrder'][$colInd])) {
+ $sortOrder
+ = $this->_curSortOrder[$new_column_count]
+ = $_REQUEST['criteriaSortOrder'][$colInd];
+ }
+
+ $html_output .= $this->_getSortOrderSelectCell(
+ $new_column_count, $sortOrder
+ );
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
* Provides search form's row containing SHOW checkboxes
*
* @return string HTML for search table's row
@@ -708,20 +865,24 @@ class PMA_DbQbe
*
* @param integer $column_number Column Number (0,1,2) or more
* @param array $selected Selected criteria column name
+ * @param bool $last_column Whether this is the last column
*
* @return string HTML for modification cell
*/
- private function _getAndOrColCell($column_number, $selected = null)
- {
+ private function _getAndOrColCell(
+ $column_number, $selected = null, $last_column = false
+ ) {
$html_output = '<td class="center">';
- $html_output .= '<strong>' . __('Or:') . '</strong>';
- $html_output .= '<input type="radio"'
- . ' name="criteriaAndOrColumn[' . $column_number . ']"'
- . ' value="or"' . $selected['or'] . ' />';
- $html_output .= '&nbsp;&nbsp;<strong>' . __('And:') . '</strong>';
- $html_output .= '<input type="radio"'
- . ' name="criteriaAndOrColumn[' . $column_number . ']"'
- . ' value="and"' . $selected['and'] . ' />';
+ if (! $last_column) {
+ $html_output .= '<strong>' . __('Or:') . '</strong>';
+ $html_output .= '<input type="radio"'
+ . ' name="criteriaAndOrColumn[' . $column_number . ']"'
+ . ' value="or"' . $selected['or'] . ' />';
+ $html_output .= '&nbsp;&nbsp;<strong>' . __('And:') . '</strong>';
+ $html_output .= '<input type="radio"'
+ . ' name="criteriaAndOrColumn[' . $column_number . ']"'
+ . ' value="and"' . $selected['and'] . ' />';
+ }
$html_output .= '<br />' . __('Ins');
$html_output .= '<input type="checkbox"'
. ' name="criteriaColumnInsert[' . $column_number . ']" />';
@@ -779,7 +940,8 @@ class PMA_DbQbe
}
$html_output .= $this->_getAndOrColCell(
$new_column_count,
- $checked_options
+ $checked_options,
+ ($column_index + 1 == $this->_criteria_column_count)
);
$new_column_count++;
} // end for
@@ -978,10 +1140,15 @@ class PMA_DbQbe
&& isset($this->_curShow[$column_index])
&& $this->_curShow[$column_index] == 'on'
) {
- $select_clauses[] = $this->_curField[$column_index];
+ $select = $this->_curField[$column_index];
+ if (! empty($this->_curAlias[$column_index])) {
+ $select .= " AS "
+ . PMA_Util::backquote($this->_curAlias[$column_index]);
+ }
+ $select_clauses[] = $select;
}
} // end for
- if ($select_clauses) {
+ if (!empty($select_clauses)) {
$select_clause = 'SELECT '
. htmlspecialchars(implode(", ", $select_clauses)) . "\n";
}
@@ -1092,6 +1259,18 @@ class PMA_DbQbe
$orderby_clause = '';
$orderby_clauses = array();
+ // Create copy of instance variables
+ $field = $this->_curField;
+ $sort = $this->_curSort;
+ $sortOrder = $this->_curSortOrder;
+ if (!empty($sortOrder)
+ && count($sortOrder) == count($sort)
+ && count($sortOrder) == count($field)
+ ) {
+ // Sort all three arrays based on sort order
+ array_multisort($sortOrder, $sort, $field);
+ }
+
for (
$column_index = 0;
$column_index < $this->_criteria_column_count;
@@ -1100,22 +1279,22 @@ class PMA_DbQbe
// if all columns are chosen with * selector,
// then sorting isn't available
// Fix for Bug #570698
- if (empty($this->_curField[$column_index])
- && empty($this->_curSort[$column_index])
+ if (empty($field[$column_index])
+ && empty($sort[$column_index])
) {
continue;
}
- if (/*overload*/mb_substr($this->_curField[$column_index], -2) == '.*') {
+ if (/*overload*/mb_substr($field[$column_index], -2) == '.*') {
continue;
}
- if (! empty($this->_curSort[$column_index])) {
- $orderby_clauses[] = $this->_curField[$column_index] . ' '
- . $this->_curSort[$column_index];
+ if (! empty($sort[$column_index])) {
+ $orderby_clauses[] = $field[$column_index] . ' '
+ . $sort[$column_index];
}
} // end for
- if ($orderby_clauses) {
+ if (!empty($orderby_clauses)) {
$orderby_clause = 'ORDER BY '
. htmlspecialchars(implode(", ", $orderby_clauses)) . "\n";
}
@@ -1125,23 +1304,23 @@ class PMA_DbQbe
/**
* Provides UNIQUE columns and INDEX columns present in criteria tables
*
- * @param array $all_tables Tables involved in the search
- * @param array $all_columns Columns involved in the search
+ * @param array $search_tables Tables involved in the search
+ * @param array $search_columns Columns involved in the search
* @param array $where_clause_columns Columns having criteria where clause
*
* @return array having UNIQUE and INDEX columns
*/
- private function _getIndexes($all_tables, $all_columns,
+ private function _getIndexes($search_tables, $search_columns,
$where_clause_columns
) {
$unique_columns = array();
$index_columns = array();
- foreach ($all_tables as $table) {
+ foreach ($search_tables as $table) {
$indexes = $GLOBALS['dbi']->getTableIndexes($this->_db, $table);
foreach ($indexes as $index) {
$column = $table . '.' . $index['Column_name'];
- if (isset($all_columns[$column])) {
+ if (isset($search_columns[$column])) {
if ($index['Non_unique'] == 0) {
if (isset($where_clause_columns[$column])) {
$unique_columns[$column] = 'Y';
@@ -1168,27 +1347,30 @@ class PMA_DbQbe
/**
* Provides UNIQUE columns and INDEX columns present in criteria tables
*
- * @param array $all_tables Tables involved in the search
- * @param array $all_columns Columns involved in the search
+ * @param array $search_tables Tables involved in the search
+ * @param array $search_columns Columns involved in the search
* @param array $where_clause_columns Columns having criteria where clause
*
* @return array having UNIQUE and INDEX columns
*/
- private function _getLeftJoinColumnCandidates($all_tables, $all_columns,
+ private function _getLeftJoinColumnCandidates($search_tables, $search_columns,
$where_clause_columns
) {
$GLOBALS['dbi']->selectDb($this->_db);
// Get unique columns and index columns
$indexes = $this->_getIndexes(
- $all_tables, $all_columns, $where_clause_columns
+ $search_tables, $search_columns, $where_clause_columns
);
$unique_columns = $indexes['unique'];
$index_columns = $indexes['index'];
list($candidate_columns, $needsort)
= $this->_getLeftJoinColumnCandidatesBest(
- $all_tables, $where_clause_columns, $unique_columns, $index_columns
+ $search_tables,
+ $where_clause_columns,
+ $unique_columns,
+ $index_columns
);
// If we came up with $unique_columns (very good) or $index_columns (still
@@ -1199,22 +1381,22 @@ class PMA_DbQbe
return $candidate_columns;
}
- $vg = array();
- $sg = array();
+ $very_good = array();
+ $still_good = array();
foreach ($candidate_columns as $column => $is_where) {
$table = explode('.', $column);
$table = $table[0];
if ($is_where == 'Y') {
- $vg[$column] = $table;
+ $very_good[$column] = $table;
} else {
- $sg[$column] = $table;
+ $still_good[$column] = $table;
}
}
- if (count($vg) > 0) {
- $candidate_columns = $vg;
+ if (count($very_good) > 0) {
+ $candidate_columns = $very_good;
// Candidates restricted in index+where
} else {
- $candidate_columns = $sg;
+ $candidate_columns = $still_good;
// None of the candidates where in a where-clause
}
@@ -1224,14 +1406,14 @@ class PMA_DbQbe
/**
* Provides the main table to form the LEFT JOIN clause
*
- * @param array $all_tables Tables involved in the search
- * @param array $all_columns Columns involved in the search
+ * @param array $search_tables Tables involved in the search
+ * @param array $search_columns Columns involved in the search
* @param array $where_clause_columns Columns having criteria where clause
* @param array $where_clause_tables Tables having criteria where clause
*
* @return string table name
*/
- private function _getMasterTable($all_tables, $all_columns,
+ private function _getMasterTable($search_tables, $search_columns,
$where_clause_columns, $where_clause_tables
) {
if (count($where_clause_tables) == 1) {
@@ -1246,7 +1428,7 @@ class PMA_DbQbe
// because he is using one of his databases as pmadb,
// the last db selected is not always the one where we need to work)
$candidate_columns = $this->_getLeftJoinColumnCandidates(
- $all_tables, $all_columns, $where_clause_columns
+ $search_tables, $search_columns, $where_clause_columns
);
// Generally, we need to display all the rows of foreign (referenced)
@@ -1292,11 +1474,8 @@ class PMA_DbQbe
$csize = array();
foreach ($candidate_columns as $table) {
if ($checked_tables[$table] != 1) {
- $tsize[$table] = PMA_Table::countRecords(
- $this->_db,
- $table,
- false
- );
+ $_table = new PMA_Table($table, $this->_db);
+ $tsize[$table] = $_table->countRecords();
$checked_tables[$table] = 1;
}
$csize[$table] = $tsize[$table];
@@ -1356,46 +1535,251 @@ class PMA_DbQbe
private function _getFromClause()
{
$from_clause = '';
- if (isset($_POST['criteriaColumn']) && count($_POST['criteriaColumn']) > 0) {
- // Initialize some variables
- $all_tables = $all_columns = array();
-
- // We only start this if we have fields, otherwise it would be dumb
- foreach ($_POST['criteriaColumn'] as $value) {
- $parts = explode('.', $value);
- if (! empty($parts[0]) && ! empty($parts[1])) {
- $table = str_replace('`', '', $parts[0]);
- $all_tables[$table] = $table;
- $all_columns[] = $table . '.' . str_replace('`', '', $parts[1]);
- }
- } // end while
-
- // Create LEFT JOINS out of Relations
- if (count($all_tables) > 0) {
- // Get tables and columns with valid where clauses
- $valid_where_clauses = $this->_getWhereClauseTablesAndColumns();
- $where_clause_tables = $valid_where_clauses['where_clause_tables'];
- $where_clause_columns = $valid_where_clauses['where_clause_columns'];
- // Get master table
- $master = $this->_getMasterTable(
- $all_tables, $all_columns,
- $where_clause_columns, $where_clause_tables
+ if (!isset($_POST['criteriaColumn'])
+ || count($_POST['criteriaColumn']) <= 0
+ ) {
+ return $from_clause;
+ }
+
+ // Initialize some variables
+ $search_tables = $search_columns = array();
+
+ // We only start this if we have fields, otherwise it would be dumb
+ foreach ($_POST['criteriaColumn'] as $value) {
+ $parts = explode('.', $value);
+ if (! empty($parts[0]) && ! empty($parts[1])) {
+ $table = str_replace('`', '', $parts[0]);
+ $search_tables[$table] = $table;
+ $search_columns[] = $table . '.' . str_replace(
+ '`', '', $parts[1]
);
- $from_clause = PMA_Util::backquote($master)
- . PMA_getRelatives($all_tables, $master);
+ }
+ } // end while
- } // end if (count($all_tables) > 0)
- } // end count($_POST['criteriaColumn']) > 0
+ // Create LEFT JOINS out of Relations
+ $from_clause = $this->_getJoinForFromClause(
+ $search_tables, $search_columns
+ );
// In case relations are not defined, just generate the FROM clause
// from the list of tables, however we don't generate any JOIN
- if (empty($from_clause) && isset($all_tables)) {
- $from_clause = implode(', ', $all_tables);
+ if (empty($from_clause)) {
+ // Create cartesian product
+ $from_clause = implode(
+ ", ", array_map('PMA_Util::backquote', $search_tables)
+ );
}
+
return $from_clause;
}
/**
+ * Formulates the WHERE clause by JOINing tables
+ *
+ * @param array $searchTables Tables involved in the search
+ * @param array $searchColumns Columns involved in the search
+ *
+ * @return string table name
+ */
+ private function _getJoinForFromClause($searchTables, $searchColumns)
+ {
+ // $relations[master_table][foreign_table] => clause
+ $relations = array();
+
+ // Fill $relations with inter table relationship data
+ foreach ($searchTables as $oneTable) {
+ $this->_loadRelationsForTable($relations, $oneTable);
+ }
+
+ // Get tables and columns with valid where clauses
+ $validWhereClauses = $this->_getWhereClauseTablesAndColumns();
+ $whereClauseTables = $validWhereClauses['where_clause_tables'];
+ $whereClauseColumns = $validWhereClauses['where_clause_columns'];
+
+ // Get master table
+ $master = $this->_getMasterTable(
+ $searchTables, $searchColumns,
+ $whereClauseColumns, $whereClauseTables
+ );
+
+ // Will incldue master tables and all tables that can be combined into
+ // a cluster by their relation
+ $finalized = array();
+ if (mb_strlen($master) > 0) {
+ // Add master tables
+ $finalized[$master] = '';
+ }
+ // Fill the $finalized array with JOIN clauses for each table
+ $this->_fillJoinClauses($finalized, $relations, $searchTables);
+
+ // JOIN clause
+ $join = '';
+
+ // Tables that can not be combined with the table cluster
+ // which includes master table
+ $unfinalized = array_diff($searchTables, array_keys($finalized));
+ if (count($unfinalized) > 0) {
+
+ // We need to look for intermediary tables to JOIN unfinalized tables
+ // Heuristic to chose intermediary tables is to look for tables
+ // having relationships with unfinalized tables
+ foreach ($unfinalized as $oneTable) {
+
+ $references = PMA_getChildReferences($this->_db, $oneTable);
+ foreach ($references as $column => $columnReferences) {
+ foreach ($columnReferences as $reference) {
+
+ // Only from this schema
+ if ($reference['table_schema'] != $this->_db) {
+ continue;
+ }
+
+ $table = $reference['table_name'];
+
+ $this->_loadRelationsForTable($relations, $table);
+
+ // Make copies
+ $tempFinalized = $finalized;
+ $tempSearchTables = $searchTables;
+ $tempSearchTables[] = $table;
+
+ // Try joining with the added table
+ $this->_fillJoinClauses(
+ $tempFinalized, $relations, $tempSearchTables
+ );
+
+ $tempUnfinalized = array_diff(
+ $tempSearchTables, array_keys($tempFinalized)
+ );
+ // Take greedy approach.
+ // If the unfinalized count drops we keep the new table
+ // and switch temporary varibles with the original ones
+ if (count($tempUnfinalized) < count($unfinalized)) {
+ $finalized = $tempFinalized;
+ $searchTables = $tempSearchTables;
+ }
+
+ // We are done if no unfinalized tables anymore
+ if (count($tempUnfinalized) == 0) {
+ break 3;
+ }
+ }
+ }
+ }
+
+ $unfinalized = array_diff($searchTables, array_keys($finalized));
+ // If there are still unfinalized tables
+ if (count($unfinalized) > 0) {
+ // Add these tables as cartesian product before joined tables
+ $join .= implode(
+ ', ', array_map('PMA_Util::backquote', $unfinalized)
+ );
+ }
+ }
+
+ $first = true;
+ // Add joined tables
+ foreach ($finalized as $table => $clause) {
+ if ($first) {
+ if (! empty($join)) {
+ $join .= ", ";
+ }
+ $join .= PMA_Util::backquote($table);
+ $first = false;
+ } else {
+ $join .= "\n LEFT JOIN " . PMA_Util::backquote(
+ $table
+ ) . " ON " . $clause;
+ }
+ }
+
+ return $join;
+ }
+
+ /**
+ * Loads relations for a given table into the $relations array
+ *
+ * @param array &$relations array of relations
+ * @param string $oneTable the table
+ *
+ * @return void
+ */
+ private function _loadRelationsForTable(&$relations, $oneTable)
+ {
+ $relations[$oneTable] = array();
+
+ $foreigners = PMA_getForeigners($GLOBALS['db'], $oneTable);
+ foreach ($foreigners as $field => $foreigner) {
+ // Foreign keys data
+ if ($field == 'foreign_keys_data') {
+ foreach ($foreigner as $oneKey) {
+ $clauses = array();
+ // There may be multiple column relations
+ foreach ($oneKey['index_list'] as $index => $oneField) {
+ $clauses[]
+ = PMA_Util::backquote($oneTable) . "."
+ . PMA_Util::backquote($oneField) . " = "
+ . PMA_Util::backquote($oneKey['ref_table_name']) . "."
+ . PMA_Util::backquote($oneKey['ref_index_list'][$index]);
+ }
+ // Combine multiple column relations with AND
+ $relations[$oneTable][$oneKey['ref_table_name']]
+ = implode(" AND ", $clauses);
+ }
+ } else { // Internal relations
+ $relations[$oneTable][$foreigner['foreign_table']]
+ = PMA_Util::backquote($oneTable) . "."
+ . PMA_Util::backquote($field) . " = "
+ . PMA_Util::backquote($foreigner['foreign_table']) . "."
+ . PMA_Util::backquote($foreigner['foreign_field']);
+ }
+ }
+ }
+
+ /**
+ * Fills the $finalized arrays with JOIN clauses for each of the tables
+ *
+ * @param array &$finalized JOIN clauses for each table
+ * @param array $relations Relations among tables
+ * @param array $searchTables Tables involved in the search
+ *
+ * @return void
+ */
+ private function _fillJoinClauses(&$finalized, $relations, $searchTables)
+ {
+ while (true) {
+ $added = false;
+ foreach ($searchTables as $masterTable) {
+ $foreignData = $relations[$masterTable];
+ foreach ($foreignData as $foreignTable => $clause) {
+ if (! isset($finalized[$masterTable])
+ && isset($finalized[$foreignTable])
+ ) {
+ $finalized[$masterTable] = $clause;
+ $added = true;
+ } elseif (! isset($finalized[$foreignTable])
+ && isset($finalized[$masterTable])
+ && in_array($foreignTable, $searchTables)
+ ) {
+ $finalized[$foreignTable] = $clause;
+ $added = true;
+ }
+ if ($added) {
+ // We are done if all tables are in $finalized
+ if (count($finalized) == count($searchTables)) {
+ return;
+ }
+ }
+ }
+ }
+ // If no new tables were added during this iteration, break;
+ if (! $added) {
+ return;
+ }
+ }
+ }
+
+ /**
* Provides the generated SQL query
*
* @return string SQL query
@@ -1424,7 +1808,8 @@ class PMA_DbQbe
*/
public function getSelectionForm()
{
- $html_output = '<form action="db_qbe.php" method="post" id="formQBE">';
+ $html_output = '<form action="db_qbe.php" method="post" id="formQBE" '
+ . 'class="lock-page">';
$html_output .= '<fieldset>';
if ($GLOBALS['cfgRelation']['savedsearcheswork']) {
@@ -1434,8 +1819,10 @@ class PMA_DbQbe
$html_output .= '<table class="data" style="width: 100%;">';
// Get table's <tr> elements
$html_output .= $this->_getColumnNamesRow();
- $html_output .= $this->_getSortRow();
+ $html_output .= $this->_getColumnAliasRow();
$html_output .= $this->_getShowRow();
+ $html_output .= $this->_getSortRow();
+ $html_output .= $this->_getSortOrder();
$html_output .= $this->_getCriteriaInputboxRow();
$html_output .= $this->_getInsDelAndOrCriteriaRows();
$html_output .= $this->_getModifyColumnsRow();
@@ -1452,10 +1839,10 @@ class PMA_DbQbe
// get tables select list
$html_output .= $this->_getTablesList();
$html_output .= '</form>';
- $html_output .= '<form action="db_qbe.php" method="post">';
+ $html_output .= '<form action="db_qbe.php" method="post" class="lock-page">';
$html_output .= PMA_URL_getHiddenInputs(array('db' => $this->_db));
// get SQL query
- $html_output .= '<div class="floatleft">';
+ $html_output .= '<div class="floatleft" style="width:50%">';
$html_output .= '<fieldset>';
$html_output .= '<legend>'
. sprintf(
@@ -1560,7 +1947,7 @@ class PMA_DbQbe
/**
* Get best
*
- * @param array $all_tables All tables
+ * @param array $search_tables Tables involved in the search
* @param array $where_clause_columns Columns with where clause
* @param array $unique_columns Unique columns
* @param array $index_columns Indexed columns
@@ -1568,7 +1955,7 @@ class PMA_DbQbe
* @return array
*/
private function _getLeftJoinColumnCandidatesBest(
- $all_tables, $where_clause_columns, $unique_columns, $index_columns
+ $search_tables, $where_clause_columns, $unique_columns, $index_columns
) {
// now we want to find the best.
if (isset($unique_columns) && count($unique_columns) > 0) {
@@ -1584,10 +1971,9 @@ class PMA_DbQbe
$needsort = 0;
return array($candidate_columns, $needsort);
} else {
- $candidate_columns = $all_tables;
+ $candidate_columns = $search_tables;
$needsort = 0;
return array($candidate_columns, $needsort);
}
}
}
-?>
diff --git a/libraries/DatabaseInterface.class.php b/libraries/DatabaseInterface.class.php
index f564078dba..b99decc960 100644
--- a/libraries/DatabaseInterface.class.php
+++ b/libraries/DatabaseInterface.class.php
@@ -11,6 +11,10 @@ if (! defined('PHPMYADMIN')) {
require_once './libraries/logging.lib.php';
require_once './libraries/Index.class.php';
+require_once './libraries/SystemDatabase.class.php';
+require_once './libraries/util.lib.php';
+
+use PMA\Util;
/**
* Main interface for database interactions
@@ -42,13 +46,19 @@ class PMA_DatabaseInterface
private $_extension;
/**
+ * @var array Table data cache
+ */
+ private $_table_cache;
+
+ /**
* Constructor
*
* @param PMA_DBI_Extension $ext Object to be used for database queries
*/
- public function __construct(PMA_DBI_Extension $ext)
+ public function __construct($ext)
{
$this->_extension = $ext;
+ $this->_table_cache = array();
}
/**
@@ -86,6 +96,62 @@ class PMA_DatabaseInterface
return $res;
}
+ /**
+ * Get a cached value from table cache.
+ *
+ * @param string $contentPath Dot notation of the target value
+ * @param mixed $default Return value on cache miss
+ *
+ * @return mixed cached value or default
+ */
+ public function getCachedTableContent($contentPath, $default = null)
+ {
+ return Util\get($this->_table_cache, $contentPath, $default);
+ }
+
+ /**
+ * Set an item in table cache using dot notation.
+ *
+ * @param string $contentPath Dot notation of the target path
+ * @param mixed $value Target value
+ *
+ * @return void
+ */
+ public function cacheTableContent($contentPath, $value)
+ {
+ $loc = &$this->_table_cache;
+
+ if (!isset($contentPath)) {
+ $loc = $value;
+ return;
+ }
+
+ $keys = explode('.', $contentPath);
+
+ while (count($keys) > 1) {
+ $key = array_shift($keys);
+
+ // If the key doesn't exist at this depth, we will just create an empty array
+ // to hold the next value, allowing us to create the arrays to hold final
+ // values at the correct depth. Then we'll keep digging into the array.
+ if (!isset($loc[$key]) || !is_array($loc[$key])) {
+ $loc[$key] = array();
+ }
+ $loc = &$loc[$key];
+ }
+
+ $loc[array_shift($keys)] = $value;
+ }
+
+ /**
+ * Clear the table cache.
+ *
+ * @return void
+ */
+ public function clearTableCache()
+ {
+ $this->_table_cache = array();
+ }
/**
* Caches table data so PMA_Table does not require to issue
@@ -106,18 +172,18 @@ class PMA_DatabaseInterface
// we would lose a db name that consists only of numbers
foreach ($tables as $one_database => $its_tables) {
- if (isset(PMA_Table::$cache[$one_database])) {
+ if (isset($this->_table_cache[$one_database])) {
// the + operator does not do the intended effect
// when the cache for one table already exists
if ($table
- && isset(PMA_Table::$cache[$one_database][$table])
+ && isset($this->_table_cache[$one_database][$table])
) {
- unset(PMA_Table::$cache[$one_database][$table]);
+ unset($this->_table_cache[$one_database][$table]);
}
- PMA_Table::$cache[$one_database]
- = PMA_Table::$cache[$one_database] + $tables[$one_database];
+ $this->_table_cache[$one_database]
+ = $this->_table_cache[$one_database] + $tables[$one_database];
} else {
- PMA_Table::$cache[$one_database] = $tables[$one_database];
+ $this->_table_cache[$one_database] = $tables[$one_database];
}
}
}
@@ -125,37 +191,34 @@ class PMA_DatabaseInterface
/**
* Stores query data into session data for debugging purposes
*
- * @param string $query Query text
- * @param object $link database link
- * @param object $result Query result
- * @param integer $time Time to execute query
+ * @param string $query Query text
+ * @param object $link database link
+ * @param object|boolean $result Query result
+ * @param integer $time Time to execute query
*
* @return void
*/
private function _dbgQuery($query, $link, $result, $time)
{
- $hash = md5($query);
-
- if (isset($_SESSION['debug']['queries'][$hash])) {
- $_SESSION['debug']['queries'][$hash]['count']++;
- } else {
- $_SESSION['debug']['queries'][$hash] = array();
- $error_message = $this->getError($link);
- if ($result == false && is_string($error_message)) {
- $_SESSION['debug']['queries'][$hash]['error']
- = '<b style="color:red">'
- . htmlspecialchars($error_message) . '</b>';
+ $dbgInfo = array();
+ $error_message = $this->getError($link);
+ if ($result == false && is_string($error_message)) {
+ $dbgInfo['error']
+ = '<span style="color:red">'
+ . htmlspecialchars($error_message) . '</span>';
+ }
+ $dbgInfo['query'] = htmlspecialchars($query);
+ $dbgInfo['time'] = $time;
+ // Get and slightly format backtrace
+ $dbgInfo['trace'] = debug_backtrace();
+ foreach ($dbgInfo['trace'] as $key => $step) {
+ if (isset($step['file'])) {
+ $dbgInfo['trace'][$key]['file'] = PMA_Error::relPath($step['file']);
}
- $_SESSION['debug']['queries'][$hash]['count'] = 1;
- $_SESSION['debug']['queries'][$hash]['query'] = htmlspecialchars($query);
- $_SESSION['debug']['queries'][$hash]['time'] = $time;
}
+ $dbgInfo['hash'] = md5($query);
- $_SESSION['debug']['queries'][$hash]['trace'][] = PMA_Error::formatBacktrace(
- debug_backtrace(),
- " ",
- "\n"
- );
+ $_SESSION['debug']['queries'][] = $dbgInfo;
}
/**
@@ -190,7 +253,8 @@ class PMA_DatabaseInterface
$time = microtime(true) - $time;
$this->_dbgQuery($query, $link, $result, $time);
}
- if ($result != false && PMA_Tracker::isActive() == true ) {
+
+ if ((!empty($result)) && (PMA_Tracker::isActive())) {
PMA_Tracker::handleQuery($query);
}
@@ -255,10 +319,11 @@ class PMA_DatabaseInterface
'de' => 'CP1252', //'latin1',
);
- $server_language = $this->fetchValue(
- 'SELECT @@lc_messages;',
- 0,
- 0
+ $server_language = PMA_Util::cacheGet(
+ 'server_language',
+ function () {
+ return $GLOBALS['dbi']->fetchValue("SELECT @@lc_messages;");
+ }
);
if ($server_language) {
@@ -322,8 +387,7 @@ class PMA_DatabaseInterface
)
. '%\'';
} else {
- $sql_where_table = 'AND t.`TABLE_NAME` '
- . PMA_Util::getCollateForIS() . ' = \''
+ $sql_where_table = 'AND t.`TABLE_NAME` = \''
. PMA_Util::sqlAddSlashes($table) . '\'';
}
} else {
@@ -425,7 +489,7 @@ class PMA_DatabaseInterface
`CREATE_OPTIONS` AS `Create_options`,
`TABLE_COMMENT` AS `Comment`
FROM `information_schema`.`TABLES` t
- WHERE `TABLE_SCHEMA` ' . PMA_Util::getCollateForIS() . '
+ WHERE ' . (PMA_IS_WINDOWS ? '' : 'BINARY') . ' `TABLE_SCHEMA`
IN (\'' . implode("', '", $this_databases) . '\')
' . $sql_where_table;
}
@@ -477,7 +541,7 @@ class PMA_DatabaseInterface
$tables = array();
- if (! $GLOBALS['cfg']['Server']['DisableIS']) {
+ if (! isset($GLOBALS['cfg']['Server']['DisableIS']) || !$GLOBALS['cfg']['Server']['DisableIS']) {
$sql_where_table = $this->_getTableCondition(
$table, $tbl_is_group, $table_type
);
@@ -553,7 +617,7 @@ class PMA_DatabaseInterface
// this is why we fall back to SHOW TABLE STATUS even for MySQL >= 50002
if (empty($tables) && !PMA_DRIZZLE) {
foreach ($databases as $each_database) {
- if ($table || (true === $tbl_is_group) || $table_type) {
+ if ($table || (true === $tbl_is_group) || ! empty($table_type)) {
$sql = 'SHOW TABLE STATUS FROM '
. PMA_Util::backquote($each_database)
. ' WHERE';
@@ -566,7 +630,7 @@ class PMA_DatabaseInterface
. "%'";
$needAnd = true;
}
- if ($table_type) {
+ if (! empty($table_type)) {
if ($needAnd) {
$sql .= " AND";
}
@@ -874,7 +938,8 @@ class PMA_DatabaseInterface
foreach ($tables_full as $table=>$tmp) {
- if (PMA_Table::isView($db, $table)) {
+ $_table = $this->getTable($db, $table);
+ if ($_table->isView()) {
$views[] = $table;
}
@@ -929,7 +994,7 @@ class PMA_DatabaseInterface
}
// get table information from information_schema
- if ($database) {
+ if (! empty($database)) {
$sql_where_schema = 'WHERE `SCHEMA_NAME` LIKE \''
. PMA_Util::sqlAddSlashes($database) . '\'';
} else {
@@ -1030,45 +1095,51 @@ class PMA_DatabaseInterface
$databases[$database_name]['DEFAULT_COLLATION_NAME']
= PMA_getDbCollation($database_name);
- if ($force_stats) {
+ if (!$force_stats) {
+ continue;
+ }
- // get additional info about tables
- $databases[$database_name]['SCHEMA_TABLES'] = 0;
- $databases[$database_name]['SCHEMA_TABLE_ROWS'] = 0;
- $databases[$database_name]['SCHEMA_DATA_LENGTH'] = 0;
- $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH'] = 0;
- $databases[$database_name]['SCHEMA_INDEX_LENGTH'] = 0;
- $databases[$database_name]['SCHEMA_LENGTH'] = 0;
- $databases[$database_name]['SCHEMA_DATA_FREE'] = 0;
-
- $res = $this->query(
- 'SHOW TABLE STATUS FROM '
- . PMA_Util::backquote($database_name) . ';'
- );
+ // get additional info about tables
+ $databases[$database_name]['SCHEMA_TABLES'] = 0;
+ $databases[$database_name]['SCHEMA_TABLE_ROWS'] = 0;
+ $databases[$database_name]['SCHEMA_DATA_LENGTH'] = 0;
+ $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH'] = 0;
+ $databases[$database_name]['SCHEMA_INDEX_LENGTH'] = 0;
+ $databases[$database_name]['SCHEMA_LENGTH'] = 0;
+ $databases[$database_name]['SCHEMA_DATA_FREE'] = 0;
+
+ $res = $this->query(
+ 'SHOW TABLE STATUS FROM '
+ . PMA_Util::backquote($database_name) . ';'
+ );
- while ($row = $this->fetchAssoc($res)) {
- $databases[$database_name]['SCHEMA_TABLES']++;
- $databases[$database_name]['SCHEMA_TABLE_ROWS']
- += $row['Rows'];
- $databases[$database_name]['SCHEMA_DATA_LENGTH']
- += $row['Data_length'];
- $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH']
- += $row['Max_data_length'];
- $databases[$database_name]['SCHEMA_INDEX_LENGTH']
- += $row['Index_length'];
-
- // for InnoDB, this does not contain the number of
- // overhead bytes but the total free space
- if ('InnoDB' != $row['Engine']) {
- $databases[$database_name]['SCHEMA_DATA_FREE']
- += $row['Data_free'];
- }
- $databases[$database_name]['SCHEMA_LENGTH']
- += $row['Data_length'] + $row['Index_length'];
- }
- $this->freeResult($res);
+ if ($res === false) {
unset($res);
+ continue;
+ }
+
+ while ($row = $this->fetchAssoc($res)) {
+ $databases[$database_name]['SCHEMA_TABLES']++;
+ $databases[$database_name]['SCHEMA_TABLE_ROWS']
+ += $row['Rows'];
+ $databases[$database_name]['SCHEMA_DATA_LENGTH']
+ += $row['Data_length'];
+ $databases[$database_name]['SCHEMA_MAX_DATA_LENGTH']
+ += $row['Max_data_length'];
+ $databases[$database_name]['SCHEMA_INDEX_LENGTH']
+ += $row['Index_length'];
+
+ // for InnoDB, this does not contain the number of
+ // overhead bytes but the total free space
+ if ('InnoDB' != $row['Engine']) {
+ $databases[$database_name]['SCHEMA_DATA_FREE']
+ += $row['Data_free'];
+ }
+ $databases[$database_name]['SCHEMA_LENGTH']
+ += $row['Data_length'] + $row['Index_length'];
}
+ $this->freeResult($res);
+ unset($res);
}
}
@@ -1150,6 +1221,50 @@ class PMA_DatabaseInterface
} // end of the '_usortComparisonCallback()' method
/**
+ * returns detailed array with all columns for sql
+ *
+ * @param string $sql_query target SQL query to get columns
+ * @param array $view_columns alias for columns
+ *
+ * @return array
+ */
+ public function getColumnMapFromSql($sql_query, $view_columns = array())
+ {
+ $result = $this->tryQuery($sql_query);
+
+ if ($result === false) {
+ return array();
+ }
+
+ $meta = $this->getFieldsMeta(
+ $result
+ );
+
+ $nbFields = count($meta);
+ if ($nbFields <= 0) {
+ return array();
+ }
+
+ $column_map = array();
+ $nbColumns = count($view_columns);
+
+ for ($i=0; $i < $nbFields; $i++) {
+
+ $map = array();
+ $map['table_name'] = $meta[$i]->table;
+ $map['refering_column'] = $meta[$i]->name;
+
+ if ($nbColumns > 1) {
+ $map['real_column'] = $view_columns[$i];
+ }
+
+ $column_map[] = $map;
+ }
+
+ return $column_map;
+ }
+
+ /**
* returns detailed array with all columns for given table in database,
* or all tables/databases
*
@@ -1388,7 +1503,7 @@ class PMA_DatabaseInterface
WHERE table_schema = '" . PMA_Util::sqlAddSlashes($database) . "'
AND table_name = '" . PMA_Util::sqlAddSlashes($table) . "'
" . (
- ($column != null)
+ ($column !== null)
? "
AND column_name = '" . PMA_Util::sqlAddSlashes($column) . "'"
: ''
@@ -1397,7 +1512,7 @@ class PMA_DatabaseInterface
} else {
$sql = 'SHOW ' . ($full ? 'FULL' : '') . ' COLUMNS FROM '
. PMA_Util::backquote($database) . '.' . PMA_Util::backquote($table)
- . (($column != null) ? "LIKE '"
+ . (($column !== null) ? "LIKE '"
. PMA_Util::sqlAddSlashes($column, true) . "'" : '');
}
return $sql;
@@ -1412,8 +1527,8 @@ class PMA_DatabaseInterface
* @param boolean $full whether to return full info or only column names
* @param mixed $link mysql link resource
*
- * @return array array indexed by column names or,
- * if $column is given, flat array description
+ * @return false|array array indexed by column names or,
+ * if $column is given, flat array description
*/
public function getColumns($database, $table, $column = null, $full = false,
$link = null
@@ -1421,7 +1536,7 @@ class PMA_DatabaseInterface
$sql = $this->getColumnsSql($database, $table, $column, $full);
$fields = $this->fetchResult($sql, 'Field', null, $link);
if (! is_array($fields) || count($fields) == 0) {
- return array();
+ return null;
}
// Check if column is a part of multiple-column index and set its 'Key'.
$indexes = PMA_Index::getFromTable($table, $database);
@@ -1499,7 +1614,7 @@ class PMA_DatabaseInterface
// We only need the 'Field' column which contains the table's column names
$fields = array_keys($this->fetchResult($sql, 'Field', null, $link));
- if ( ! is_array($fields) || count($fields) == 0 ) {
+ if (! is_array($fields) || count($fields) == 0) {
return null;
}
return $fields;
@@ -1606,6 +1721,31 @@ class PMA_DatabaseInterface
}
/**
+ * Sets new value for a variable if it is different from the current value
+ *
+ * @param string $var variable name
+ * @param string $value value to set
+ * @param mixed $link mysql link resource|object
+ *
+ * @return bool whether query was a successful
+ */
+ public function setVariable($var, $value, $link = null)
+ {
+ $link = $this->getLink($link);
+ if ($link === false) {
+ return false;
+ }
+ $current_value = $GLOBALS['dbi']->getVariable(
+ $var, self::GETVAR_SESSION, $link
+ );
+ if ($current_value == $value) {
+ return true;
+ }
+
+ return $this->query("SET " . $var . " = " . $value . ';', $link);
+ }
+
+ /**
* Function called just after a connection to the MySQL database server has
* been established. It sets the connection collation, and determines the
* version of MySQL which is running.
@@ -1635,6 +1775,10 @@ class PMA_DatabaseInterface
PMA_Util::cacheGet('PMA_MYSQL_VERSION_COMMENT')
);
define(
+ 'PMA_MARIADB',
+ PMA_Util::cacheGet('PMA_MARIADB')
+ );
+ define(
'PMA_DRIZZLE',
PMA_Util::cacheGet('PMA_DRIZZLE')
);
@@ -1681,10 +1825,23 @@ class PMA_DatabaseInterface
'PMA_MYSQL_VERSION_COMMENT',
PMA_MYSQL_VERSION_COMMENT
);
+ /* Detect MariaDB */
+ if (mb_strpos(PMA_MYSQL_STR_VERSION, 'MariaDB') !== false) {
+ define('PMA_MARIADB', true);
+ } else {
+ define('PMA_MARIADB', false);
+ }
+ PMA_Util::cacheSet(
+ 'PMA_MARIADB',
+ PMA_MARIADB
+ );
/* Detect Drizzle - it does not support charsets */
$charset_result = $this->query(
- "SHOW VARIABLES LIKE 'character_set_results'",
+ // The following does not work in MySQL 5.7:
+ //"SHOW VARIABLES LIKE 'character_set_results'",
+ // so a workaround was implemented:
+ "SELECT @@character_set_results",
$link
);
if ($this->numRows($charset_result) == 0) {
@@ -2093,6 +2250,169 @@ class PMA_DatabaseInterface
}
/**
+ * returns details about the PROCEDUREs or FUNCTIONs for a specific database
+ * or details about a specific routine
+ *
+ * @param string $db db name
+ * @param string $which PROCEDURE | FUNCTION or null for both
+ * @param string $name name of the routine (to fetch a specific routine)
+ *
+ * @return array information about ROCEDUREs or FUNCTIONs
+ */
+ public function getRoutines($db, $which = null, $name = '')
+ {
+ if (PMA_DRIZZLE) {
+ // Drizzle doesn't support functions and procedures
+ return array();
+ }
+
+ $routines = array();
+ if (! $GLOBALS['cfg']['Server']['DisableIS']) {
+ $query = "SELECT"
+ . " `ROUTINE_SCHEMA` AS `Db`,"
+ . " `SPECIFIC_NAME` AS `Name`,"
+ . " `ROUTINE_TYPE` AS `Type`,"
+ . " `DEFINER` AS `Definer`,"
+ . " `LAST_ALTERED` AS `Modified`,"
+ . " `CREATED` AS `Created`,"
+ . " `SECURITY_TYPE` AS `Security_type`,"
+ . " `ROUTINE_COMMENT` AS `Comment`,"
+ . " `CHARACTER_SET_CLIENT` AS `character_set_client`,"
+ . " `COLLATION_CONNECTION` AS `collation_connection`,"
+ . " `DATABASE_COLLATION` AS `Database Collation`,"
+ . " `DTD_IDENTIFIER`"
+ . " FROM `information_schema`.`ROUTINES`"
+ . " WHERE `ROUTINE_SCHEMA` " . PMA_Util::getCollateForIS()
+ . " = '" . PMA_Util::sqlAddSlashes($db) . "'";
+ if (PMA_isValid($which, array('FUNCTION','PROCEDURE'))) {
+ $query .= " AND `ROUTINE_TYPE` = '" . $which . "'";
+ }
+ if (! empty($name)) {
+ $query .= " AND `SPECIFIC_NAME`"
+ . " = '" . PMA_Util::sqlAddSlashes($name) . "'";
+ }
+ $result = $this->fetchResult($query);
+ if (!empty($result)) {
+ $routines = $result;
+ }
+ } else {
+ if ($which == 'FUNCTION' || $which == null) {
+ $query = "SHOW FUNCTION STATUS"
+ . " WHERE `Db` = '" . PMA_Util::sqlAddSlashes($db) . "'";
+ if (! empty($name)) {
+ $query .= " AND `Name` = '"
+ . PMA_Util::sqlAddSlashes($name) . "'";
+ }
+ $result = $this->fetchResult($query);
+ if (!empty($result)) {
+ $routines = array_merge($routines, $result);
+ }
+ }
+ if ($which == 'PROCEDURE' || $which == null) {
+ $query = "SHOW PROCEDURE STATUS"
+ . " WHERE `Db` = '" . PMA_Util::sqlAddSlashes($db) . "'";
+ if (! empty($name)) {
+ $query .= " AND `Name` = '"
+ . PMA_Util::sqlAddSlashes($name) . "'";
+ }
+ $result = $this->fetchResult($query);
+ if (!empty($result)) {
+ $routines = array_merge($routines, $result);
+ }
+ }
+ }
+
+ $ret = array();
+ foreach ($routines as $routine) {
+ $one_result = array();
+ $one_result['db'] = $routine['Db'];
+ $one_result['name'] = $routine['Name'];
+ $one_result['type'] = $routine['Type'];
+ $one_result['definer'] = $routine['Definer'];
+ $one_result['returns'] = isset($routine['DTD_IDENTIFIER'])
+ ? $routine['DTD_IDENTIFIER'] : "";
+ $ret[] = $one_result;
+ }
+
+ // Sort results by name
+ $name = array();
+ foreach ($ret as $value) {
+ $name[] = $value['name'];
+ }
+ array_multisort($name, SORT_ASC, $ret);
+
+ return($ret);
+ }
+
+ /**
+ * returns details about the EVENTs for a specific database
+ *
+ * @param string $db db name
+ * @param string $name event name
+ *
+ * @return array information about EVENTs
+ */
+ public function getEvents($db, $name = '')
+ {
+ if (PMA_DRIZZLE) {
+ // Drizzle doesn't support events
+ return array();
+ }
+
+ if (! $GLOBALS['cfg']['Server']['DisableIS']) {
+ $query = "SELECT"
+ . " `EVENT_SCHEMA` AS `Db`,"
+ . " `EVENT_NAME` AS `Name`,"
+ . " `DEFINER` AS `Definer`,"
+ . " `TIME_ZONE` AS `Time zone`,"
+ . " `EVENT_TYPE` AS `Type`,"
+ . " `EXECUTE_AT` AS `Execute at`,"
+ . " `INTERVAL_VALUE` AS `Interval value`,"
+ . " `INTERVAL_FIELD` AS `Interval field`,"
+ . " `STARTS` AS `Starts`,"
+ . " `ENDS` AS `Ends`,"
+ . " `STATUS` AS `Status`,"
+ . " `ORIGINATOR` AS `Originator`,"
+ . " `CHARACTER_SET_CLIENT` AS `character_set_client`,"
+ . " `COLLATION_CONNECTION` AS `collation_connection`, "
+ . "`DATABASE_COLLATION` AS `Database Collation`"
+ . " FROM `information_schema`.`EVENTS`"
+ . " WHERE `EVENT_SCHEMA` " . PMA_Util::getCollateForIS()
+ . " = '" . PMA_Util::sqlAddSlashes($db) . "'";
+ if (! empty($name)) {
+ $query .= " AND `EVENT_NAME`"
+ . " = '" . PMA_Util::sqlAddSlashes($name) . "'";
+ }
+ } else {
+ $query = "SHOW EVENTS FROM " . PMA_Util::backquote($db);
+ if (! empty($name)) {
+ $query .= " AND `Name` = '"
+ . PMA_Util::sqlAddSlashes($name) . "'";
+ }
+ }
+
+ $result = array();
+ if ($events = $this->fetchResult($query)) {
+ foreach ($events as $event) {
+ $one_result = array();
+ $one_result['name'] = $event['Name'];
+ $one_result['type'] = $event['Type'];
+ $one_result['status'] = $event['Status'];
+ $result[] = $one_result;
+ }
+ }
+
+ // Sort results by name
+ $name = array();
+ foreach ($result as $value) {
+ $name[] = $value['name'];
+ }
+ array_multisort($name, SORT_ASC, $result);
+
+ return $result;
+ }
+
+ /**
* returns details about the TRIGGERs for a specific table or database
*
* @param string $db db name
@@ -2118,8 +2438,8 @@ class PMA_DatabaseInterface
. ' \'' . PMA_Util::sqlAddSlashes($db) . '\'';
if (! empty($table)) {
- $query .= " AND EVENT_OBJECT_TABLE = '"
- . PMA_Util::sqlAddSlashes($table) . "';";
+ $query .= " AND EVENT_OBJECT_TABLE " . PMA_Util::getCollateForIS()
+ . " = '" . PMA_Util::sqlAddSlashes($table) . "';";
}
} else {
$query = "SHOW TRIGGERS FROM " . PMA_Util::backquote($db);
@@ -2377,7 +2697,8 @@ class PMA_DatabaseInterface
public function getSystemSchemas()
{
$schemas = array(
- 'information_schema', 'performance_schema', 'data_dictionary', 'mysql'
+ 'information_schema', 'performance_schema', 'data_dictionary', 'mysql',
+ 'sys'
);
$systemSchemas = array();
foreach ($schemas as $schema) {
@@ -2400,16 +2721,12 @@ class PMA_DatabaseInterface
*/
public function isSystemSchema($schema_name, $testForMysqlSchema = false)
{
- if (!defined("PMA_DRIZZLE")) {
- define("PMA_DRIZZLE", false);
- }
-
- return strtolower($schema_name) == 'information_schema'
- || (!PMA_DRIZZLE
- && strtolower($schema_name) == 'performance_schema')
- || (PMA_DRIZZLE
- && strtolower($schema_name) == 'data_dictionary')
- || ($testForMysqlSchema && !PMA_DRIZZLE && $schema_name == 'mysql');
+ $schema_name = strtolower($schema_name);
+ return $schema_name == 'information_schema'
+ || (!PMA_DRIZZLE && $schema_name == 'performance_schema')
+ || (!PMA_DRIZZLE && $schema_name == 'mysql' && $testForMysqlSchema)
+ || (!PMA_DRIZZLE && $schema_name == 'sys')
+ || ( PMA_DRIZZLE && $schema_name == 'data_dictionary');
}
/**
@@ -2818,7 +3135,7 @@ class PMA_DatabaseInterface
*/
public function getLink($link = null)
{
- if ( ! is_null($link) && $link !== false) {
+ if (! is_null($link) && $link !== false) {
return $link;
}
@@ -2862,5 +3179,27 @@ class PMA_DatabaseInterface
return 'KILL ' . $process . ';';
}
}
+
+ /**
+ * Get the phpmyadmin database manager
+ *
+ * @return PMA\SystemDatabase
+ */
+ public function getSystemDatabase()
+ {
+ return new PMA\SystemDatabase($this);
+ }
+
+ /**
+ * Get a table with database name and table name
+ *
+ * @param string $db_name DB name
+ * @param string $table_name Table name
+ *
+ * @return PMA_Table
+ */
+ public function getTable($db_name, $table_name)
+ {
+ return new PMA_Table($table_name, $db_name, $this);
+ }
}
-?>
diff --git a/libraries/DbSearch.class.php b/libraries/DbSearch.class.php
index a6a1e831d0..bce102f90d 100644
--- a/libraries/DbSearch.class.php
+++ b/libraries/DbSearch.class.php
@@ -243,7 +243,7 @@ class PMA_DbSearch
} // end for
// Use 'OR' if 'at least one word' is to be searched, else use 'AND'
$implode_str = ($this->_criteriaSearchType == 1 ? ' OR ' : ' AND ');
- if ( empty($likeClauses)) {
+ if (empty($likeClauses)) {
// this could happen when the "inside column" does not exist
// in any selected tables
$where_clause = ' WHERE FALSE';
@@ -380,7 +380,7 @@ class PMA_DbSearch
{
$html_output = '<a id="db_search"></a>';
$html_output .= '<form id="db_search_form"'
- . ' class="ajax"'
+ . ' class="ajax lock-page"'
. ' method="post" action="db_search.php" name="db_search">';
$html_output .= PMA_URL_getHiddenInputs($GLOBALS['db']);
$html_output .= '<fieldset>';
@@ -443,11 +443,11 @@ class PMA_DbSearch
$alter_select = '<a href="#" '
. 'onclick="setSelectOptions(\'db_search\','
. ' \'criteriaTables[]\', true); return false;">'
- . __('Select All') . '</a> &nbsp;/&nbsp;';
+ . __('Select all') . '</a> &nbsp;/&nbsp;';
$alter_select .= '<a href="#" '
. 'onclick="setSelectOptions(\'db_search\','
. ' \'criteriaTables[]\', false); return false;">'
- . __('Unselect All') . '</a>';
+ . __('Unselect all') . '</a>';
$html_output .= '<tr><td class="right vbottom">'
. $alter_select . '</td></tr>';
// Inputbox for column name entry
diff --git a/libraries/DisplayResults.class.php b/libraries/DisplayResults.class.php
index d70c9f5fab..e435a217f7 100644
--- a/libraries/DisplayResults.class.php
+++ b/libraries/DisplayResults.class.php
@@ -150,8 +150,8 @@ class PMA_DisplayResults
/** array column names to highlight */
'highlight_columns' => null,
- /** array information used with vertical display mode */
- 'vertical_display' => null,
+ /** array holding various display information */
+ 'display_params' => null,
/** array mime types information of fields */
'mime_map' => null,
@@ -160,7 +160,10 @@ class PMA_DisplayResults
'editable' => null,
/** random unique ID to distinguish result set */
- 'unique_id' => null
+ 'unique_id' => null,
+
+ /** where clauses for each row, each table in the row */
+ 'whereClauseMap' => array(),
);
/**
@@ -331,6 +334,11 @@ class PMA_DisplayResults
'search_data' => $json_highlighting_data
);
}
+ if (! empty($cfgRelation['designer_settings'])) {
+ $relDb[$cfgRelation['designer_settings']] = array(
+ 'settings_data' => $json_highlighting_data
+ );
+ }
if (! empty($cfgRelation['table_uiprefs'])) {
$relDb[$cfgRelation['table_uiprefs']] = array(
'prefs' => $json_highlighting_data
@@ -341,6 +349,11 @@ class PMA_DisplayResults
'config_data' => $json_highlighting_data
);
}
+ if (! empty($cfgRelation['export_templates'])) {
+ $relDb[$cfgRelation['export_templates']] = array(
+ 'template_data' => $json_highlighting_data
+ );
+ }
}
}
@@ -367,7 +380,7 @@ class PMA_DisplayResults
* @param string $printview print view was requested
* @param string $url_query URL query
* @param boolean $editable whether the results set is editable
- * @param boolean $browse_dist whether browsing distinct values
+ * @param boolean $is_browse_dist whether browsing distinct values
*
* @return void
*
@@ -404,9 +417,167 @@ class PMA_DisplayResults
/**
+ * Defines the parts to display for a print view
+ *
+ * @param array $displayParts the parts to display
+ *
+ * @return array $displayParts the modified display parts
+ *
+ * @access private
+ *
+ */
+ private function _setDisplayPartsForPrintView($displayParts)
+ {
+ // set all elements to false!
+ $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE; // no edit link
+ $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE; // no delete link
+ $displayParts['sort_lnk'] = (string) '0';
+ $displayParts['nav_bar'] = (string) '0';
+ $displayParts['bkm_form'] = (string) '0';
+ $displayParts['text_btn'] = (string) '0';
+ $displayParts['pview_lnk'] = (string) '0';
+
+ return $displayParts;
+ }
+
+ /**
+ * Defines the parts to display for a SHOW statement
+ *
+ * @param array $displayParts the parts to display
+ *
+ * @return array $displayParts the modified display parts
+ *
+ * @access private
+ *
+ */
+ private function _setDisplayPartsForShow($displayParts)
+ {
+ preg_match(
+ '@^SHOW[[:space:]]+(VARIABLES|(FULL[[:space:]]+)?'
+ . 'PROCESSLIST|STATUS|TABLE|GRANTS|CREATE|LOGS|DATABASES|FIELDS'
+ . ')@i',
+ $this->__get('sql_query'), $which
+ );
+
+ $bIsProcessList = isset($which[1]);
+ if ($bIsProcessList) {
+ $str = ' ' . strtoupper($which[1]);
+ $bIsProcessList = $bIsProcessList
+ && strpos($str, 'PROCESSLIST') > 0;
+ }
+
+ if ($bIsProcessList) {
+ // no edit link
+ $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE;
+ // "kill process" type edit link
+ $displayParts['del_lnk'] = self::KILL_PROCESS;
+ } else {
+ // Default case -> no links
+ // no edit link
+ $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE;
+ // no delete link
+ $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE;
+ }
+ // Other settings
+ $displayParts['sort_lnk'] = (string) '0';
+ $displayParts['nav_bar'] = (string) '0';
+ $displayParts['bkm_form'] = (string) '1';
+ $displayParts['text_btn'] = (string) '1';
+ $displayParts['pview_lnk'] = (string) '1';
+
+ return $displayParts;
+ }
+
+ /**
+ * Defines the parts to display for statements not related to data
+ *
+ * @param array $displayParts the parts to display
+ *
+ * @return array $displayParts the modified display parts
+ *
+ * @access private
+ *
+ */
+ private function _setDisplayPartsForNonData($displayParts)
+ {
+ // Statement is a "SELECT COUNT", a
+ // "CHECK/ANALYZE/REPAIR/OPTIMIZE/CHECKSUM", an "EXPLAIN" one or
+ // contains a "PROC ANALYSE" part
+ $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE; // no edit link
+ $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE; // no delete link
+ $displayParts['sort_lnk'] = (string) '0';
+ $displayParts['nav_bar'] = (string) '0';
+ $displayParts['bkm_form'] = (string) '1';
+
+ if ($this->__get('is_maint')) {
+ $displayParts['text_btn'] = (string) '1';
+ } else {
+ $displayParts['text_btn'] = (string) '0';
+ }
+ $displayParts['pview_lnk'] = (string) '1';
+
+ return $displayParts;
+ }
+
+ /**
+ * Defines the parts to display for other statements (probably SELECT)
+ *
+ * @param array $displayParts the parts to display
+ *
+ * @return array $displayParts the modified display parts
+ *
+ * @access private
+ *
+ */
+ private function _setDisplayPartsForSelect($displayParts)
+ {
+ // Other statements (ie "SELECT" ones) -> updates
+ // $displayParts['edit_lnk'], $displayParts['del_lnk'] and
+ // $displayParts['text_btn'] (keeps other default values)
+
+ $fields_meta = $this->__get('fields_meta');
+ $prev_table = '';
+ $displayParts['text_btn'] = (string) '1';
+ $number_of_columns = $this->__get('fields_cnt');
+
+ for ($i = 0; $i < $number_of_columns; $i++) {
+
+ $is_link = ($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
+ || ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)
+ || ($displayParts['sort_lnk'] != '0');
+
+ // Displays edit/delete/sort/insert links?
+ if ($is_link
+ && $prev_table != ''
+ && $fields_meta[$i]->table != ''
+ && $fields_meta[$i]->table != $prev_table
+ ) {
+ // don't display links
+ $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE;
+ $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE;
+ /**
+ * @todo May be problematic with same field names
+ * in two joined table.
+ */
+ // $displayParts['sort_lnk'] = (string) '0';
+ if ($displayParts['text_btn'] == '1') {
+ break;
+ }
+ } // end if
+
+ // Always display print view link
+ $displayParts['pview_lnk'] = (string) '1';
+ if ($fields_meta[$i]->table != '') {
+ $prev_table = $fields_meta[$i]->table;
+ }
+ } // end for
+ return $displayParts;
+ }
+
+ /**
* Defines the parts to display for the results of a SQL query
*
- * @param string $displayParts the parts to display (see a few
+ * @param array $displayParts the parts to display (see a few
* lines above for explanations)
* @param integer &$the_total the total number of rows returned by the SQL
* query without any programmatically appended
@@ -423,131 +594,29 @@ class PMA_DisplayResults
*/
private function _setDisplayParts($displayParts, &$the_total)
{
-
// 1. Following variables are needed for use in isset/empty or
// use with array indexes or safe use in foreach
$db = $this->__get('db');
$table = $this->__get('table');
$unlim_num_rows = $this->__get('unlim_num_rows');
$num_rows = $this->__get('num_rows');
- $fields_meta = $this->__get('fields_meta');
$printview = $this->__get('printview');
- // 2. Updates the display mode
- if (isset($printview) && ($printview == '1')) {
- // 2.0 Print view -> set all elements to false!
- $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE; // no edit link
- $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE; // no delete link
- $displayParts['sort_lnk'] = (string) '0';
- $displayParts['nav_bar'] = (string) '0';
- $displayParts['ins_row'] = (string) '0';
- $displayParts['bkm_form'] = (string) '0';
- $displayParts['text_btn'] = (string) '0';
- $displayParts['pview_lnk'] = (string) '0';
+ // 2. Updates the display parts
+ if ($printview == '1') {
+ $displayParts = $this->_setDisplayPartsForPrintView($displayParts);
} elseif ($this->__get('is_count') || $this->__get('is_analyse')
|| $this->__get('is_maint') || $this->__get('is_explain')
) {
- // 2.1 Statement is a "SELECT COUNT", a
- // "CHECK/ANALYZE/REPAIR/OPTIMIZE", an "EXPLAIN" one or
- // contains a "PROC ANALYSE" part
- $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE; // no edit link
- $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE; // no delete link
- $displayParts['sort_lnk'] = (string) '0';
- $displayParts['nav_bar'] = (string) '0';
- $displayParts['ins_row'] = (string) '0';
- $displayParts['bkm_form'] = (string) '1';
-
- if ($this->__get('is_maint')) {
- $displayParts['text_btn'] = (string) '1';
- } else {
- $displayParts['text_btn'] = (string) '0';
- }
- $displayParts['pview_lnk'] = (string) '1';
+ $displayParts = $this->_setDisplayPartsForNonData($displayParts);
} elseif ($this->__get('is_show')) {
- // 2.2 Statement is a "SHOW..."
- /**
- * 2.2.1
- * @todo defines edit/delete links depending on show statement
- */
- preg_match(
- '@^SHOW[[:space:]]+(VARIABLES|(FULL[[:space:]]+)?'
- . 'PROCESSLIST|STATUS|TABLE|GRANTS|CREATE|LOGS|DATABASES|FIELDS'
- . ')@i',
- $this->__get('sql_query'), $which
- );
-
- $bIsProcessList = isset($which[1]);
- if ($bIsProcessList) {
- $str = ' ' . strtoupper($which[1]);
- $bIsProcessList = $bIsProcessList
- && strpos($str, 'PROCESSLIST') > 0;
- }
-
- if ($bIsProcessList) {
- // no edit link
- $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE;
- // "kill process" type edit link
- $displayParts['del_lnk'] = self::KILL_PROCESS;
- } else {
- // Default case -> no links
- // no edit link
- $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE;
- // no delete link
- $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE;
- }
- unset($bIsProcessList);
- // 2.2.2 Other settings
- $displayParts['sort_lnk'] = (string) '0';
- $displayParts['nav_bar'] = (string) '0';
- $displayParts['ins_row'] = (string) '0';
- $displayParts['bkm_form'] = (string) '1';
- $displayParts['text_btn'] = (string) '1';
- $displayParts['pview_lnk'] = (string) '1';
+ $displayParts = $this->_setDisplayPartsForShow($displayParts);
} else {
- // 2.3 Other statements (ie "SELECT" ones) -> updates
- // $displayParts['edit_lnk'], $displayParts['del_lnk'] and
- // $displayParts['text_btn'] (keeps other default values)
- $prev_table = '';
- $displayParts['text_btn'] = (string) '1';
-
- for ($i = 0; $i < $this->__get('fields_cnt'); $i++) {
-
- $is_link = ($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
- || ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)
- || ($displayParts['sort_lnk'] != '0')
- || ($displayParts['ins_row'] != '0');
-
- // 2.3.2 Displays edit/delete/sort/insert links?
- if ($is_link
- && $prev_table != ''
- && $fields_meta[$i]->table != ''
- && $fields_meta[$i]->table != $prev_table
- ) {
- // don't display links
- $displayParts['edit_lnk'] = self::NO_EDIT_OR_DELETE;
- $displayParts['del_lnk'] = self::NO_EDIT_OR_DELETE;
- /**
- * @todo May be problematic with same field names
- * in two joined table.
- */
- // $displayParts['sort_lnk'] = (string) '0';
- $displayParts['ins_row'] = (string) '0';
- if ($displayParts['text_btn'] == '1') {
- break;
- }
- } // end if (2.3.2)
-
- // 2.3.3 Always display print view link
- $displayParts['pview_lnk'] = (string) '1';
- if ($fields_meta[$i]->table != '') {
- $prev_table = $fields_meta[$i]->table;
- }
-
- } // end for
- } // end if..elseif...else (2.1 -> 2.3)
+ $displayParts = $this->_setDisplayPartsForSelect($displayParts);
+ } // end if..elseif...else
// 3. Gets the total number of rows if it is unknown
if (isset($unlim_num_rows) && $unlim_num_rows != '') {
@@ -556,10 +625,11 @@ class PMA_DisplayResults
|| ($displayParts['sort_lnk'] == '1'))
&& (/*overload*/mb_strlen($db) && !empty($table))
) {
- $the_total = PMA_Table::countRecords($db, $table);
+ $the_total = $GLOBALS['dbi']->getTable($db, $table)->countRecords();
}
- // if for COUNT query, number of rows returned more than 1 (may be being used GROUP BY)
+ // if for COUNT query, number of rows returned more than 1
+ // (may be being used GROUP BY)
if ($this->__get('is_count') && isset($num_rows) && $num_rows > 1) {
$displayParts['nav_bar'] = (string) '1';
$displayParts['sort_lnk'] = (string) '1';
@@ -573,9 +643,10 @@ class PMA_DisplayResults
// - For a VIEW we (probably) did not count the number of rows
// so don't test this number here, it would remove the possibility
// of sorting VIEW results.
+ $_table = new PMA_Table($table, $db);
if (isset($unlim_num_rows)
&& ($unlim_num_rows < 2)
- && ! PMA_Table::isView($db, $table)
+ && ! $_table->isView()
) {
$displayParts['sort_lnk'] = (string) '0';
}
@@ -590,7 +661,7 @@ class PMA_DisplayResults
* Return true if we are executing a query in the form of
* "SELECT * FROM <a table> ..."
*
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return boolean
*
@@ -598,17 +669,16 @@ class PMA_DisplayResults
*
* @see _getTableHeaders(), _getColumnParams()
*/
- private function _isSelect($analyzed_sql)
+ private function _isSelect($analyzed_sql_results)
{
- if (!isset($analyzed_sql[0]['select_expr'])) {
- $analyzed_sql[0]['select_expr'] = 0;
- }
-
- return ! ($this->__get('is_count') || $this->__get('is_export')
- || $this->__get('is_func') || $this->__get('is_analyse'))
- && (count($analyzed_sql[0]['select_expr']) == 0)
- && isset($analyzed_sql[0]['queryflags']['select_from'])
- && (count($analyzed_sql[0]['table_ref']) == 1);
+ return ! ($this->__get('is_count')
+ || $this->__get('is_export')
+ || $this->__get('is_func')
+ || $this->__get('is_analyse'))
+ && !empty($analyzed_sql_results['select_from'])
+ && !empty($analyzed_sql_results['statement']->from)
+ && (count($analyzed_sql_results['statement']->from) == 1)
+ && !empty($analyzed_sql_results['statement']->from[0]->table);
}
@@ -677,6 +747,56 @@ class PMA_DisplayResults
/**
+ * Possibly return a page selector for table navigation
+ *
+ * @param string $table_navigation_html the current navigation HTML
+ *
+ * @return array ($table_navigation_html, $nbTotalPage)
+ *
+ * @access private
+ *
+ */
+ private function _getHtmlPageSelector($table_navigation_html)
+ {
+ $pageNow = @floor(
+ $_SESSION['tmpval']['pos']
+ / $_SESSION['tmpval']['max_rows']
+ ) + 1;
+
+ $nbTotalPage = @ceil(
+ $this->__get('unlim_num_rows')
+ / $_SESSION['tmpval']['max_rows']
+ );
+
+ if ($nbTotalPage > 1) {
+ $table_navigation_html .= '<td>';
+ $_url_params = array(
+ 'db' => $this->__get('db'),
+ 'table' => $this->__get('table'),
+ 'sql_query' => $this->__get('sql_query'),
+ 'goto' => $this->__get('goto'),
+ 'is_browse_distinct' => $this->__get('is_browse_distinct'),
+ );
+
+ //<form> to keep the form alignment of button < and <<
+ // and also to know what to execute when the selector changes
+ $table_navigation_html .= '<form action="sql.php'
+ . PMA_URL_getCommon($_url_params)
+ . '" method="post">';
+
+ $table_navigation_html .= PMA_Util::pageselector(
+ 'pos',
+ $_SESSION['tmpval']['max_rows'],
+ $pageNow, $nbTotalPage, 200, 5, 5, 20, 10
+ );
+
+ $table_navigation_html .= '</form>'
+ . '</td>';
+ }
+ return array($table_navigation_html, $nbTotalPage);
+ }
+
+ /**
* Get a navigation bar to browse among the results of a SQL query
*
* @param integer $pos_next the offset for the "next" page
@@ -700,7 +820,7 @@ class PMA_DisplayResults
$html_sql_query = htmlspecialchars($this->__get('sql_query'));
// Navigation bar
- $table_navigation_html .= '<table class="navigation nospacing nopadding">'
+ $table_navigation_html .= '<table class="navigation nospacing nopadding print_ignore">'
. '<tr>'
. '<td class="navigation_separator"></td>';
@@ -719,45 +839,12 @@ class PMA_DisplayResults
$nbTotalPage = 1;
//page redirection
// (unless we are showing all records)
- if ($_SESSION['tmpval']['max_rows'] != self::ALL_ROWS) { //if1
-
- $pageNow = @floor(
- $_SESSION['tmpval']['pos']
- / $_SESSION['tmpval']['max_rows']
- ) + 1;
-
- $nbTotalPage = @ceil(
- $this->__get('unlim_num_rows')
- / $_SESSION['tmpval']['max_rows']
- );
-
- if ($nbTotalPage > 1) { //if2
-
- $table_navigation_html .= '<td>';
- $_url_params = array(
- 'db' => $this->__get('db'),
- 'table' => $this->__get('table'),
- 'sql_query' => $this->__get('sql_query'),
- 'goto' => $this->__get('goto'),
- 'is_browse_distinct' => $this->__get('is_browse_distinct'),
- );
-
- //<form> to keep the form alignment of button < and <<
- // and also to know what to execute when the selector changes
- $table_navigation_html .= '<form action="sql.php'
- . PMA_URL_getCommon($_url_params)
- . '" method="post">';
-
- $table_navigation_html .= PMA_Util::pageselector(
- 'pos',
- $_SESSION['tmpval']['max_rows'],
- $pageNow, $nbTotalPage, 200, 5, 5, 20, 10
- );
-
- $table_navigation_html .= '</form>'
- . '</td>';
- } //_if2
- } //_if1
+ if ($_SESSION['tmpval']['max_rows'] != self::ALL_ROWS) {
+ list(
+ $table_navigation_html,
+ $nbTotalPage
+ ) = $this->_getHtmlPageSelector($table_navigation_html);
+ }
$showing_all = false;
if ($_SESSION['tmpval']['max_rows'] == self::ALL_ROWS) {
@@ -1039,7 +1126,8 @@ class PMA_DisplayResults
$additional_fields_html .= __('Number of rows:') . ' ';
$additional_fields_html .= PMA_Util::getDropdown(
'session_max_rows', $numberOfRowsChoices,
- $_SESSION['tmpval']['max_rows'], '', 'autosubmit', $numberOfRowsPlaceholder
+ $_SESSION['tmpval']['max_rows'], '',
+ 'autosubmit', $numberOfRowsPlaceholder
);
return $additional_fields_html;
@@ -1048,36 +1136,30 @@ class PMA_DisplayResults
/**
- * Get the headers of the results table
+ * Get the headers of the results table, for all of the columns
*
- * @param array &$displayParts which elements to display
- * @param array $analyzed_sql the analyzed query
- * @param string $sort_expression sort expression
+ * @param array $displayParts which elements to display
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param array $sort_expression sort expression
* @param string $sort_expression_nodirection sort expression
* without direction
* @param string $sort_direction sort direction
* @param boolean $is_limited_display with limited operations
* or not
+ * @param string $unsorted_sql_query query without the sort part
*
* @return string html content
*
* @access private
*
- * @see getTable()
+ * @see getTableHeaders()
*/
- private function _getTableHeaders(
- &$displayParts, $analyzed_sql,
- $sort_expression = '', $sort_expression_nodirection = '',
- $sort_direction = '', $is_limited_display = false
+ private function _getTableHeadersForColumns(
+ $displayParts, $analyzed_sql_results, $sort_expression,
+ $sort_expression_nodirection, $sort_direction, $is_limited_display,
+ $unsorted_sql_query
) {
-
- $table_headers_html = '';
- // Following variable are needed for use in isset/empty or
- // use with array indexes/safe use in foreach
- $fields_meta = $this->__get('fields_meta');
- $highlight_columns = $this->__get('highlight_columns');
- $printview = $this->__get('printview');
- $vertical_display = $this->__get('vertical_display');
+ $html = '';
// required to generate sort links that will remember whether the
// "Show all" button has been clicked
@@ -1086,25 +1168,130 @@ class PMA_DisplayResults
? 0
: $_SESSION['tmpval']['query'][$sql_md5]['max_rows'];
- if ($analyzed_sql == '') {
- $analyzed_sql = array();
- }
+ // Following variable are needed for use in isset/empty or
+ // use with array indexes/safe use in the for loop
+ $highlight_columns = $this->__get('highlight_columns');
+ $fields_meta = $this->__get('fields_meta');
+
+ // Prepare Display column comments if enabled
+ // ($GLOBALS['cfg']['ShowBrowseComments']).
+ $comments_map = $this->_getTableCommentsArray($analyzed_sql_results);
+
+ list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql_results);
+
+ // optimize: avoid calling a method on each iteration
+ $number_of_columns = $this->__get('fields_cnt');
+
+ for ($j = 0; $j < $number_of_columns; $j++) {
+
+ // assign $i with the appropriate column order
+ $i = $col_order ? $col_order[$j] : $j;
+
+ // See if this column should get highlight because it's used in the
+ // where-query.
+ $condition_field = (isset($highlight_columns[$fields_meta[$i]->name])
+ || isset(
+ $highlight_columns[PMA_Util::backquote($fields_meta[$i]->name)])
+ )
+ ? true
+ : false;
+
+ // Prepare comment-HTML-wrappers for each row, if defined/enabled.
+ $comments = $this->_getCommentForRow($comments_map, $fields_meta[$i]);
+ $display_params = $this->__get('display_params');
+
+ if (($displayParts['sort_lnk'] == '1') && ! $is_limited_display) {
+
+ list($order_link, $sorted_header_html)
+ = $this->_getOrderLinkAndSortedHeaderHtml(
+ $fields_meta[$i], $sort_expression,
+ $sort_expression_nodirection, $i, $unsorted_sql_query,
+ $session_max_rows, $comments,
+ $sort_direction, $col_visib,
+ $col_visib[$j]
+ );
+
+ $html .= $sorted_header_html;
+
+ $display_params['desc'][] = ' <th '
+ . 'class="draggable'
+ . ($condition_field ? ' condition' : '')
+ . '" data-column="' . htmlspecialchars($fields_meta[$i]->name)
+ . '">' . "\n" . $order_link . $comments . ' </th>' . "\n";
+ } else {
+ // Results can't be sorted
+ $html
+ .= $this->_getDraggableClassForNonSortableColumns(
+ $col_visib, $col_visib[$j], $condition_field,
+ $fields_meta[$i], $comments
+ );
+
+ $display_params['desc'][] = ' <th '
+ . 'class="draggable'
+ . ($condition_field ? ' condition"' : '')
+ . '" data-column="' . htmlspecialchars($fields_meta[$i]->name)
+ . '">' . ' '
+ . htmlspecialchars($fields_meta[$i]->name)
+ . $comments . ' </th>';
+ } // end else
+
+ $this->__set('display_params', $display_params);
+
+ } // end for
+ return $html;
+ }
+
+ /**
+ * Get the headers of the results table
+ *
+ * @param array &$displayParts which elements to display
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param array $sort_expression sort expression
+ * @param string $sort_expression_nodirection sort expression
+ * without direction
+ * @param string $sort_direction sort direction
+ * @param boolean $is_limited_display with limited operations
+ * or not
+ *
+ * @return string html content
+ *
+ * @access private
+ *
+ * @see getTable()
+ */
+ private function _getTableHeaders(
+ &$displayParts, $analyzed_sql_results, $sort_expression = array(),
+ $sort_expression_nodirection = '', $sort_direction = '',
+ $is_limited_display = false
+ ) {
+
+ $table_headers_html = '';
+ // Needed for use in isset/empty or
+ // use with array indexes/safe use in foreach
+ $printview = $this->__get('printview');
+ $display_params = $this->__get('display_params');
// can the result be sorted?
if ($displayParts['sort_lnk'] == '1') {
+ // At this point, $sort_expression is an array but we only verify
+ // the first element in case we could find that the table is
+ // sorted by one of the choices listed in the
+ // "Sort by key" drop-down
list($unsorted_sql_query, $drop_down_html)
= $this->_getUnsortedSqlAndSortByKeyDropDown(
- $analyzed_sql, $sort_expression
+ $analyzed_sql_results, $sort_expression[0]
);
$table_headers_html .= $drop_down_html;
+ } else {
+ $unsorted_sql_query = '';
}
// Output data needed for grid editing
- $table_headers_html .= '<input class="save_cells_at_once" type="hidden" value="'
- . $GLOBALS['cfg']['SaveCellsAtOnce'] . '" />'
+ $table_headers_html .= '<input class="save_cells_at_once" type="hidden"'
+ . ' value="' . $GLOBALS['cfg']['SaveCellsAtOnce'] . '" />'
. '<div class="common_hidden_inputs">'
. PMA_URL_getHiddenInputs(
$this->__get('db'), $this->__get('table')
@@ -1112,16 +1299,16 @@ class PMA_DisplayResults
. '</div>';
// Output data needed for column reordering and show/hide column
- if ($this->_isSelect($analyzed_sql)) {
+ if ($this->_isSelect($analyzed_sql_results)) {
$table_headers_html .= $this->_getDataForResettingColumnOrder();
}
- $vertical_display['emptypre'] = 0;
- $vertical_display['emptyafter'] = 0;
- $vertical_display['textbtn'] = '';
+ $display_params['emptypre'] = 0;
+ $display_params['emptyafter'] = 0;
+ $display_params['textbtn'] = '';
$full_or_partial_text_link = null;
- $this->__set('vertical_display', $vertical_display);
+ $this->__set('display_params', $display_params);
// Display options (if we are not in print view)
if (! (isset($printview) && ($printview == '1')) && ! $is_limited_display) {
@@ -1150,74 +1337,16 @@ class PMA_DisplayResults
// 2.0 If sorting links should be used, checks if the query is a "JOIN"
// statement (see 2.1.3)
- // 2.0.1 Prepare Display column comments if enabled
- // ($GLOBALS['cfg']['ShowBrowseComments']).
- $comments_map = $this->_getTableCommentsArray($analyzed_sql);
-
// See if we have to highlight any header fields of a WHERE query.
// Uses SQL-Parser results.
- $this->_setHighlightedColumnGlobalField($analyzed_sql);
-
- list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql);
-
- for ($j = 0; $j < $this->__get('fields_cnt'); $j++) {
-
- // assign $i with appropriate column order
- $i = $col_order ? $col_order[$j] : $j;
-
- // See if this column should get highlight because it's used in the
- // where-query.
- $condition_field = (isset($highlight_columns[$fields_meta[$i]->name])
- || isset(
- $highlight_columns[PMA_Util::backquote($fields_meta[$i]->name)])
- )
- ? true
- : false;
-
- // 2.0 Prepare comment-HTML-wrappers for each row, if defined/enabled.
- $comments = $this->_getCommentForRow($comments_map, $fields_meta[$i]);
-
- $vertical_display = $this->__get('vertical_display');
+ $this->_setHighlightedColumnGlobalField($analyzed_sql_results);
- if (($displayParts['sort_lnk'] == '1') && ! $is_limited_display) {
-
- list($order_link, $sorted_header_html)
- = $this->_getOrderLinkAndSortedHeaderHtml(
- $fields_meta[$i], $sort_expression,
- $sort_expression_nodirection, $i, $unsorted_sql_query,
- $session_max_rows, $comments,
- $sort_direction, $col_visib,
- $col_visib[$j]
- );
-
- $table_headers_html .= $sorted_header_html;
-
- $vertical_display['desc'][] = ' <th '
- . 'class="draggable'
- . ($condition_field ? ' condition' : '')
- . '" data-column="' . htmlspecialchars($fields_meta[$i]->name)
- . '">' . "\n" . $order_link . $comments . ' </th>' . "\n";
- } else {
- // 2.2 Results can't be sorted
-
- $table_headers_html
- .= $this->_getDraggableClassForNonSortableColumns(
- $col_visib, $col_visib[$j], $condition_field,
- $fields_meta[$i], $comments
- );
-
- $vertical_display['desc'][] = ' <th '
- . 'class="draggable'
- . ($condition_field ? ' condition"' : '')
- . '" data-column="' . htmlspecialchars($fields_meta[$i]->name)
- . '">' . "\n" . ' '
- . htmlspecialchars($fields_meta[$i]->name)
- . "\n" . $comments . ' </th>';
- } // end else (2.2)
-
- $this->__set('vertical_display', $vertical_display);
-
- } // end for
+ // Get the headers for all of the columns
+ $table_headers_html .= $this->_getTableHeadersForColumns(
+ $displayParts, $analyzed_sql_results, $sort_expression,
+ $sort_expression_nodirection, $sort_direction,
+ $is_limited_display, $unsorted_sql_query
+ );
// Display column at rightside - checkboxes or empty column
if (! $printview) {
@@ -1235,8 +1364,8 @@ class PMA_DisplayResults
/**
* Prepare unsorted sql query and sort by key drop down
*
- * @param array $analyzed_sql the analyzed query
- * @param string $sort_expression sort expression
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param string $sort_expression sort expression
*
* @return array two element array - $unsorted_sql_query, $drop_down_html
*
@@ -1245,29 +1374,19 @@ class PMA_DisplayResults
* @see _getTableHeaders()
*/
private function _getUnsortedSqlAndSortByKeyDropDown(
- $analyzed_sql, $sort_expression
+ $analyzed_sql_results, $sort_expression
) {
-
$drop_down_html = '';
- // Just as fallback
- $unsorted_sql_query = $this->__get('sql_query');
- if (isset($analyzed_sql[0]['unsorted_query'])) {
- $unsorted_sql_query = $analyzed_sql[0]['unsorted_query'];
- }
- // Handles the case of multiple clicks on a column's header
- // which would add many spaces before "ORDER BY" in the
- // generated query.
- $unsorted_sql_query = trim($unsorted_sql_query);
-
- // sorting by indexes, only if it makes sense (only one table ref)
- if (isset($analyzed_sql)
- && isset($analyzed_sql[0])
- && isset($analyzed_sql[0]['querytype'])
- && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT)
- && isset($analyzed_sql[0]['table_ref'])
- && (count($analyzed_sql[0]['table_ref']) == 1)
- ) {
+ $unsorted_sql_query = SqlParser\Utils\Query::replaceClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'ORDER BY',
+ ''
+ );
+
+ // Data is sorted by indexes only if it there is only one table.
+ if ($this->_isSelect($analyzed_sql_results)) {
// grab indexes data:
$indexes = PMA_Index::getFromTable(
$this->__get('table'),
@@ -1275,7 +1394,7 @@ class PMA_DisplayResults
);
// do we have any index?
- if ($indexes) {
+ if (! empty($indexes)) {
$drop_down_html = $this->_getSortByKeyDropDown(
$indexes, $sort_expression,
$unsorted_sql_query
@@ -1291,9 +1410,10 @@ class PMA_DisplayResults
/**
* Prepare sort by key dropdown - html code segment
*
- * @param array $indexes the indexes of the table for sort criteria
- * @param string $sort_expression the sort expression
- * @param string $unsorted_sql_query the unsorted sql query
+ * @param PMA_Index[] $indexes the indexes of the table for sort
+ * criteria
+ * @param string $sort_expression the sort expression
+ * @param string $unsorted_sql_query the unsorted sql query
*
* @return string $drop_down_html html content
*
@@ -1307,10 +1427,12 @@ class PMA_DisplayResults
$drop_down_html = '';
- $drop_down_html .= '<form action="sql.php" method="post">' . "\n"
+ $drop_down_html .= '<form action="sql.php" method="post" class="print_ignore">' . "\n"
. PMA_URL_getHiddenInputs(
$this->__get('db'), $this->__get('table')
)
+ // to avoid calling PMA_handleSortOrder() later
+ . PMA_getHiddenFields(array('sort_by_key' => '1'))
. __('Sort by key')
. ': <select name="sql_query" class="autosubmit">' . "\n";
@@ -1397,7 +1519,7 @@ class PMA_DisplayResults
) {
$button_html = '';
- $vertical_display = $this->__get('vertical_display');
+ $display_params = $this->__get('display_params');
// 1. Displays the full/partial text button (part 1)...
$button_html .= '<thead><tr>' . "\n";
@@ -1413,7 +1535,7 @@ class PMA_DisplayResults
&& ($displayParts['text_btn'] == '1')
) {
- $vertical_display['emptypre']
+ $display_params['emptypre']
= (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
&& ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 0;
@@ -1424,11 +1546,11 @@ class PMA_DisplayResults
// ... at the left column of the result table header if possible
// and required
- $vertical_display['emptypre']
+ $display_params['emptypre']
= (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
&& ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 0;
- $button_html .= '<th class="column_action" ' . $colspan . '>'
+ $button_html .= '<th class="column_action print_ignore" ' . $colspan . '>'
. $full_or_partial_text_link . '</th>';
} elseif ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
@@ -1438,7 +1560,7 @@ class PMA_DisplayResults
) {
// ... elseif no button, displays empty(ies) col(s) if required
- $vertical_display['emptypre']
+ $display_params['emptypre']
= (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
&& ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 0;
@@ -1450,7 +1572,7 @@ class PMA_DisplayResults
$button_html .= '<th class="column_action"></th>';
}
- $this->__set('vertical_display', $vertical_display);
+ $this->__set('display_params', $display_params);
return array($colspan, $button_html);
@@ -1460,35 +1582,34 @@ class PMA_DisplayResults
/**
* Get table comments as array
*
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results analyzed sql results
*
- * @return array $comments_map table comments when condition true
- * null when condition falls
+ * @return array $comments_map table comments
*
* @access private
*
* @see _getTableHeaders()
*/
- private function _getTableCommentsArray($analyzed_sql)
+ private function _getTableCommentsArray($analyzed_sql_results)
{
+ if ((!$GLOBALS['cfg']['ShowBrowseComments'])
+ || (empty($analyzed_sql_results['statement']->from))
+ ) {
+ return array();
+ }
- $comments_map = null;
-
- if ($GLOBALS['cfg']['ShowBrowseComments']) {
- $comments_map = array();
- if (isset($analyzed_sql[0])
- && is_array($analyzed_sql[0])
- && isset($analyzed_sql[0]['table_ref'])
- ) {
- foreach ($analyzed_sql[0]['table_ref'] as $tbl) {
- $tb = $tbl['table_true_name'];
- $comments_map[$tb] = PMA_getComments($this->__get('db'), $tb);
- unset($tb);
- }
+ $ret = array();
+ foreach ($analyzed_sql_results['statement']->from as $field) {
+ if (empty($field->table)) {
+ continue;
}
+ $ret[$field->table] = PMA_getComments(
+ empty($field->database) ? $this->__get('db') : $field->database,
+ $field->table
+ );
}
- return $comments_map;
+ return $ret;
} // end of the '_getTableCommentsArray()' function
@@ -1496,7 +1617,7 @@ class PMA_DisplayResults
/**
* Set global array for store highlighted header fields
*
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return void
*
@@ -1504,16 +1625,15 @@ class PMA_DisplayResults
*
* @see _getTableHeaders()
*/
- private function _setHighlightedColumnGlobalField($analyzed_sql)
+ private function _setHighlightedColumnGlobalField($analyzed_sql_results)
{
-
$highlight_columns = array();
- if (isset($analyzed_sql) && isset($analyzed_sql[0])
- && isset($analyzed_sql[0]['where_clause_identifiers'])
- && is_array($analyzed_sql[0]['where_clause_identifiers'])
- ) {
- foreach ($analyzed_sql[0]['where_clause_identifiers'] as $wci) {
- $highlight_columns[$wci] = 'true';
+
+ if (!empty($analyzed_sql_results['statement']->where)) {
+ foreach ($analyzed_sql_results['statement']->where as $expr) {
+ foreach ($expr->identifiers as $identifier) {
+ $highlight_columns[$identifier] = 'true';
+ }
}
}
@@ -1553,11 +1673,13 @@ class PMA_DisplayResults
}
// generate table create time
- if (! PMA_Table::isView($this->__get('db'), $this->__get('table'))) {
+ $table = new PMA_Table($this->__get('table'), $this->__get('db'));
+ if (! $table->isView()) {
$data_html .= '<input class="table_create_time" type="hidden" value="'
- . PMA_Table::sGetStatusInfo(
- $this->__get('db'), $this->__get('table'), 'Create_time'
- ) . '" />';
+ . $GLOBALS['dbi']->getTable(
+ $this->__get('db'), $this->__get('table')
+ )->getStatusInfo('Create_time')
+ . '" />';
}
return $data_html;
@@ -1582,7 +1704,7 @@ class PMA_DisplayResults
$options_html .= '<form method="post" action="sql.php" '
. 'name="displayOptionsForm"';
- $options_html .= ' class="ajax" ';
+ $options_html .= ' class="ajax print_ignore" ';
$options_html .= '>';
$url_params = array(
@@ -1620,7 +1742,7 @@ class PMA_DisplayResults
$options_html .= '<div class="formelement">';
$choices = array(
'K' => __('Relational key'),
- 'D' => __('Relational display column')
+ 'D' => __('Display column for relations')
);
$options_html .= PMA_Util::getRadioFields(
@@ -1784,8 +1906,7 @@ class PMA_DisplayResults
private function _getCommentForRow($comments_map, $fields_meta)
{
$comments = '';
- if (isset($comments_map)
- && isset($comments_map[$fields_meta->table])
+ if (isset($comments_map[$fields_meta->table])
&& isset($comments_map[$fields_meta->table][$fields_meta->name])
) {
$sanitized_comments = htmlspecialchars(
@@ -1812,12 +1933,12 @@ class PMA_DisplayResults
*
* @param array $fields_meta set of field properties
* @param array $sort_expression sort expression
- * @param array $sort_expression_nodirection sort expression without direction
+ * @param string $sort_expression_nodirection sort expression without direction
* @param integer $column_index the index of the column
* @param string $unsorted_sql_query the unsorted sql query
* @param integer $session_max_rows maximum rows resulted by sql
* @param string $comments comment for row
- * @param array $sort_direction sort direction
+ * @param string $sort_direction sort direction
* @param boolean $col_visib column is visible(false)
* array column isn't visible(string array)
* @param string $col_visib_j element of $col_visib array
@@ -1910,12 +2031,12 @@ class PMA_DisplayResults
* Prepare parameters and html for sorted table header fields
*
* @param array $sort_expression sort expression
- * @param array $sort_expression_nodirection sort expression without direction
+ * @param string $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 string $sort_direction sort direction
* @param array $fields_meta set of field properties
* @param integer $column_index The index number to current column
*
@@ -2087,10 +2208,13 @@ class PMA_DisplayResults
// Another query to test this:
// SELECT p.*, FROM_UNIXTIME(p.temps) FROM mytable AS p
// (and try clicking on each column's header twice)
- if (! empty($sort_tbl)
- && /*overload*/mb_strpos($sort_expression_nodirection[$index_in_expression], $sort_tbl) === false
- && /*overload*/mb_strpos($sort_expression_nodirection[$index_in_expression], '(') === false
- ) {
+ $noSortTable = empty($sort_tbl) || /*overload*/mb_strpos(
+ $sort_expression_nodirection[$index_in_expression], $sort_tbl
+ ) === false;
+ $noOpenParenthesis = /*overload*/mb_strpos(
+ $sort_expression_nodirection[$index_in_expression], '('
+ ) === false;
+ if (! empty($sort_tbl) && $noSortTable && $noOpenParenthesis) {
$new_sort_expression_nodirection = $sort_tbl
. $sort_expression_nodirection[$index_in_expression];
} else {
@@ -2334,7 +2458,7 @@ class PMA_DisplayResults
) {
$right_column_html = '';
- $vertical_display = $this->__get('vertical_display');
+ $display_params = $this->__get('display_params');
// Displays the needed checkboxes at the right
// column of the result table header if possible and required...
@@ -2345,12 +2469,13 @@ class PMA_DisplayResults
&& ($displayParts['text_btn'] == '1')
) {
- $vertical_display['emptyafter']
+ $display_params['emptyafter']
= (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
&& ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 1;
$right_column_html .= "\n"
- . '<th class="column_action" ' . $colspan . '>' . $full_or_partial_text_link
+ . '<th class="column_action print_ignore" ' . $colspan . '>'
+ . $full_or_partial_text_link
. '</th>';
} elseif ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
@@ -2362,14 +2487,14 @@ class PMA_DisplayResults
// ... elseif no button, displays empty columns if required
// (unless coming from Browse mode print view)
- $vertical_display['emptyafter']
+ $display_params['emptyafter']
= (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
&& ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 1;
- $right_column_html .= "\n" . '<td ' . $colspan . '></td>';
+ $right_column_html .= "\n" . '<td class="print_ignore" ' . $colspan . '></td>';
}
- $this->__set('vertical_display', $vertical_display);
+ $this->__set('display_params', $display_params);
return $right_column_html;
@@ -2495,7 +2620,8 @@ class PMA_DisplayResults
}
$mime_map = $this->__get('mime_map');
- $orgFullColName = $this->__get('db') . '.' . $meta->orgtable . '.' . $meta->orgname;
+ $orgFullColName = $this->__get('db') . '.' . $meta->orgtable
+ . '.' . $meta->orgname;
if ($transformation_plugin != $default_function
|| !empty($mime_map[$orgFullColName]['input_transformation'])
) {
@@ -2526,12 +2652,12 @@ class PMA_DisplayResults
/**
* Prepare the body of the results table
*
- * @param integer &$dt_result the link id associated to the query
+ * @param integer &$dt_result the link id associated to the query which results have to be displayed
* which results have to be displayed
- * @param array &$displayParts which elements to display
- * @param array $map the list of relations
- * @param array $analyzed_sql the analyzed query
- * @param boolean $is_limited_display with limited operations or not
+ * @param array &$displayParts which elements to display
+ * @param array $map the list of relations
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param boolean $is_limited_display with limited operations or not
*
* @return string $table_body_html html content
*
@@ -2542,7 +2668,8 @@ class PMA_DisplayResults
* @see getTable()
*/
private function _getTableBody(
- &$dt_result, &$displayParts, $map, $analyzed_sql, $is_limited_display = false
+ &$dt_result, &$displayParts, $map, $analyzed_sql_results,
+ $is_limited_display = false
) {
global $row; // mostly because of browser transformations,
@@ -2552,21 +2679,21 @@ class PMA_DisplayResults
// query without conditions to shorten URLs when needed, 200 is just
// guess, it should depend on remaining URL length
- $url_sql_query = $this->_getUrlSqlQuery($analyzed_sql);
+ $url_sql_query = $this->_getUrlSqlQuery($analyzed_sql_results);
- $vertical_display = $this->__get('vertical_display');
+ $display_params = $this->__get('display_params');
if (! is_array($map)) {
$map = array();
}
- $row_no = 0;
- $vertical_display['edit'] = array();
- $vertical_display['copy'] = array();
- $vertical_display['delete'] = array();
- $vertical_display['data'] = array();
- $vertical_display['row_delete'] = array();
- $this->__set('vertical_display', $vertical_display);
+ $row_no = 0;
+ $display_params['edit'] = array();
+ $display_params['copy'] = array();
+ $display_params['delete'] = array();
+ $display_params['data'] = array();
+ $display_params['row_delete'] = array();
+ $this->__set('display_params', $display_params);
// name of the class added to all grid editable elements;
// if we don't have all the columns of a unique key in the result set,
@@ -2590,7 +2717,7 @@ class PMA_DisplayResults
}
// prepare to get the column order, if available
- list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql);
+ list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql_results);
// Correction University of Virginia 19991216 in the while below
// Previous code assumed that all tables have keys, specifically that
@@ -2606,6 +2733,7 @@ class PMA_DisplayResults
$odd_row = true;
+ $whereClauseMap = $this->__get('whereClauseMap');
while ($row = $GLOBALS['dbi']->fetchRow($dt_result)) {
// add repeating headers
@@ -2613,7 +2741,7 @@ class PMA_DisplayResults
&& !($row_no % $_SESSION['tmpval']['repeat_cells'])
) {
$table_body_html .= $this->_getRepeatingHeaders(
- $vertical_display
+ $display_params
);
}
@@ -2631,21 +2759,6 @@ class PMA_DisplayResults
$table_body_html .= '<tr class="' . implode(' ', $tr_class) . '">';
// 1. Prepares the row
- // 1.1 Results from a "SELECT" statement -> builds the
- // WHERE clause to use in links (a unique key if possible)
- /**
- * @todo $where_clause could be empty, for example a table
- * with only one field and it's a BLOB; in this case,
- * avoid to display the delete and edit links
- */
- list($where_clause, $clause_is_unique, $condition_array)
- = PMA_Util::getUniqueCondition(
- $dt_result,
- $this->__get('fields_cnt'),
- $this->__get('fields_meta'),
- $row
- );
- $where_clause_html = urlencode($where_clause);
// In print view these variable needs to be initialized
$del_url = $del_str = $edit_anchor_class
@@ -2656,6 +2769,29 @@ class PMA_DisplayResults
if (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
|| ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)
) {
+
+ // Results from a "SELECT" statement -> builds the
+ // WHERE clause to use in links (a unique key if possible)
+ /**
+ * @todo $where_clause could be empty, for example a table
+ * with only one field and it's a BLOB; in this case,
+ * avoid to display the delete and edit links
+ */
+ list($where_clause, $clause_is_unique, $condition_array)
+ = PMA_Util::getUniqueCondition(
+ $dt_result, // handle
+ $this->__get('fields_cnt'), // fields_cnt
+ $this->__get('fields_meta'), // fields_meta
+ $row, // row
+ false, // force_unique
+ $this->__get('table'), // restrict_to_table
+ $analyzed_sql_results // analyzed_sql_results
+ );
+ $whereClauseMap[$row_no][$this->__get('table')] = $where_clause;
+ $this->__set('whereClauseMap', $whereClauseMap);
+
+ $where_clause_html = urlencode($where_clause);
+
// 1.2.1 Modify link(s) - update row case
if ($displayParts['edit_lnk'] == self::UPDATE_ROW) {
@@ -2705,23 +2841,33 @@ class PMA_DisplayResults
$this->_setMimeMap();
}
$table_body_html .= $this->_getRowValues(
- $dt_result, $row, $row_no, $col_order, $map,
- $grid_edit_class, $col_visib, $where_clause,
- $url_sql_query, $analyzed_sql
+ $dt_result,
+ $row,
+ $row_no,
+ $col_order,
+ $map,
+ $grid_edit_class,
+ $col_visib,
+ $url_sql_query,
+ $analyzed_sql_results
);
// 3. Displays the modify/delete links on the right if required
- if (($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
- || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH)
+ if (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
+ || ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE)
) {
+ if (($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
+ || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH)
+ ) {
- $table_body_html .= $this->_getPlacedLinks(
- self::POSITION_RIGHT, $del_url, $displayParts, $row_no,
- $where_clause, $where_clause_html, $condition_array,
- $edit_url, $copy_url, $edit_anchor_class,
- $edit_str, $copy_str, $del_str, $js_conf
- );
+ $table_body_html .= $this->_getPlacedLinks(
+ self::POSITION_RIGHT, $del_url, $displayParts, $row_no,
+ $where_clause, $where_clause_html, $condition_array,
+ $edit_url, $copy_url, $edit_anchor_class,
+ $edit_str, $copy_str, $del_str, $js_conf
+ );
+ }
} // end if (3)
$table_body_html .= '</tr>';
@@ -2759,7 +2905,8 @@ class PMA_DisplayResults
&& empty($added[$orgFullTableName])
) {
$mimeMap = array_merge(
- $mimeMap, PMA_getMIME($this->__get('db'), $meta->orgtable, false, true)
+ $mimeMap,
+ PMA_getMIME($this->__get('db'), $meta->orgtable, false, true)
);
$added[$orgFullTableName] = true;
}
@@ -2805,19 +2952,18 @@ class PMA_DisplayResults
/**
* Get the values for one data row
*
- * @param integer &$dt_result the link id associated to the query
+ * @param integer &$dt_result the link id associated to the query which results have to be displayed
* which results have to be displayed
- * @param array $row current row data
- * @param integer $row_no the index of current row
- * @param array $col_order the column order
+ * @param array $row current row data
+ * @param integer $row_no the index of current row
+ * @param array $col_order the column order false when a property not found
* false when a property not found
- * @param array $map the list of relations
- * @param string $grid_edit_class the class for all editable columns
- * @param boolean $col_visib column is visible(false)
+ * @param array $map the list of relations
+ * @param string $grid_edit_class the class for all editable columns
+ * @param boolean $col_visib column is visible(false) array column isn't visible(string array)
* array column isn't visible(string array)
- * @param string $where_clause where clause
- * @param string $url_sql_query the analyzed sql query
- * @param array $analyzed_sql the analyzed query
+ * @param string $url_sql_query the analyzed sql query
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return string $row_values_html html content
*
@@ -2827,10 +2973,9 @@ class PMA_DisplayResults
*/
private function _getRowValues(
&$dt_result, $row, $row_no, $col_order, $map,
- $grid_edit_class, $col_visib, $where_clause,
- $url_sql_query, $analyzed_sql
+ $grid_edit_class, $col_visib,
+ $url_sql_query, $analyzed_sql_results
) {
-
$row_values_html = '';
// Following variable are needed for use in isset/empty or
@@ -2842,7 +2987,7 @@ class PMA_DisplayResults
$row_info = $this->_getRowInfoForSpecialLinks($row, $col_order);
- $uniqueConditionMap = array();
+ $whereClauseMap = $this->__get('whereClauseMap');
$columnCount = $this->__get('fields_cnt');
for ($currentColumn = 0;
@@ -2926,7 +3071,6 @@ class PMA_DisplayResults
} // end if transformation is set
} // end if mime/transformation works.
-
// Check whether the field needs to display with syntax highlighting
$dbLower = /*overload*/mb_strtolower($this->__get('db'));
@@ -2982,13 +3126,6 @@ class PMA_DisplayResults
}
- $_url_params = array(
- 'db' => $this->__get('db'),
- 'table' => $this->__get('table'),
- 'where_clause' => $where_clause,
- 'transform_key' => $meta->name,
- );
-
/*
* The result set can have columns from more than one table,
* this is why we have to check for the unique conditions
@@ -2996,45 +3133,51 @@ class PMA_DisplayResults
* costly and does not need to be called if we already know
* the conditions for the current table.
*/
- if (! isset($uniqueConditionMap[$meta->orgtable])) {
+ if (! isset($whereClauseMap[$row_no][$meta->orgtable])) {
$unique_conditions = PMA_Util::getUniqueCondition(
- $dt_result,
- $this->__get('fields_cnt'),
- $this->__get('fields_meta'),
- $row,
- false,
- $meta->orgtable
+ $dt_result, // handle
+ $this->__get('fields_cnt'), // fields_cnt
+ $this->__get('fields_meta'), // fields_meta
+ $row, // row
+ false, // force_unique
+ $meta->orgtable, // restrict_to_table
+ $analyzed_sql_results // analyzed_sql_results
);
- $uniqueConditionMap[$meta->orgtable] = $unique_conditions;
+ $whereClauseMap[$row_no][$meta->orgtable] = $unique_conditions[0];
}
- $transform_url_params = array(
+ $_url_params = array(
'db' => $this->__get('db'),
'table' => $meta->orgtable,
- 'where_clause' => $uniqueConditionMap[$meta->orgtable][0],
+ 'where_clause' => $whereClauseMap[$row_no][$meta->orgtable],
'transform_key' => $meta->orgname
);
if (! empty($sql_query)) {
$_url_params['sql_query'] = $url_sql_query;
- $transform_url_params['sql_query'] = $url_sql_query;
}
$transform_options['wrapper_link']
- = PMA_URL_getCommon($transform_url_params);
+ = PMA_URL_getCommon($_url_params);
- $vertical_display = $this->__get('vertical_display');
+ $display_params = $this->__get('display_params');
// in some situations (issue 11406), numeric returns 1
// even for a string type
if ($meta->numeric == 1 && $meta->type != 'string') {
// n u m e r i c
- $vertical_display['data'][$row_no][$i]
+ $display_params['data'][$row_no][$i]
= $this->_getDataCellForNumericColumns(
- $row[$i], $class, $condition_field, $meta, $map,
- $is_field_truncated, $analyzed_sql,
- $transformation_plugin, $default_function,
+ $row[$i],
+ $class,
+ $condition_field,
+ $meta,
+ $map,
+ $is_field_truncated,
+ $analyzed_sql_results,
+ $transformation_plugin,
+ $default_function,
$transform_options
);
@@ -3045,38 +3188,54 @@ class PMA_DisplayResults
// inline-edit geometry data.
$class = str_replace('grid_edit', '', $class);
- $vertical_display['data'][$row_no][$i]
+ $display_params['data'][$row_no][$i]
= $this->_getDataCellForGeometryColumns(
- $row[$i], $class, $meta, $map, $_url_params,
- $condition_field, $transformation_plugin,
- $default_function, $transform_options, $analyzed_sql
+ $row[$i],
+ $class,
+ $meta,
+ $map,
+ $_url_params,
+ $condition_field,
+ $transformation_plugin,
+ $default_function,
+ $transform_options,
+ $analyzed_sql_results
);
} else {
// n o t n u m e r i c
- $vertical_display['data'][$row_no][$i]
+ $display_params['data'][$row_no][$i]
= $this->_getDataCellForNonNumericColumns(
- $row[$i], $class, $meta, $map, $_url_params,
- $condition_field, $transformation_plugin,
- $default_function, $transform_options,
- $is_field_truncated, $analyzed_sql, $dt_result, $i
+ $row[$i],
+ $class,
+ $meta,
+ $map,
+ $_url_params,
+ $condition_field,
+ $transformation_plugin,
+ $default_function,
+ $transform_options,
+ $is_field_truncated,
+ $analyzed_sql_results,
+ $dt_result,
+ $i
);
}
// output stored cell
- $row_values_html .= $vertical_display['data'][$row_no][$i];
+ $row_values_html .= $display_params['data'][$row_no][$i];
- if (isset($vertical_display['rowdata'][$i][$row_no])) {
- $vertical_display['rowdata'][$i][$row_no]
- .= $vertical_display['data'][$row_no][$i];
+ if (isset($display_params['rowdata'][$i][$row_no])) {
+ $display_params['rowdata'][$i][$row_no]
+ .= $display_params['data'][$row_no][$i];
} else {
- $vertical_display['rowdata'][$i][$row_no]
- = $vertical_display['data'][$row_no][$i];
+ $display_params['rowdata'][$i][$row_no]
+ = $display_params['data'][$row_no][$i];
}
- $this->__set('vertical_display', $vertical_display);
+ $this->__set('display_params', $display_params);
} // end for
@@ -3168,11 +3327,10 @@ class PMA_DisplayResults
}
-
/**
* Get url sql query without conditions to shorten URLs
*
- * @param array $analyzed_sql analyzed query
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return string $url_sql analyzed sql query
*
@@ -3180,30 +3338,31 @@ class PMA_DisplayResults
*
* @see _getTableBody()
*/
- private function _getUrlSqlQuery($analyzed_sql)
+ private function _getUrlSqlQuery($analyzed_sql_results)
{
-
- if (isset($analyzed_sql)
- && isset($analyzed_sql[0])
- && isset($analyzed_sql[0]['querytype'])
- && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT)
- && (/*overload*/mb_strlen($this->__get('sql_query')) > 200)
+ if (($analyzed_sql_results['querytype'] != 'SELECT')
+ || (/*overload*/mb_strlen($this->__get('sql_query')) < 200)
) {
+ return $this->__get('sql_query');
+ }
- $url_sql_query = 'SELECT ';
- if (isset($analyzed_sql[0]['queryflags']['distinct'])) {
- $url_sql_query .= ' DISTINCT ';
- }
+ $query = 'SELECT ' . SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'SELECT'
+ );
- $url_sql_query .= $analyzed_sql[0]['select_expr_clause'];
- if (!empty($analyzed_sql[0]['from_clause'])) {
- $url_sql_query .= ' FROM ' . $analyzed_sql[0]['from_clause'];
- }
+ $from_clause = SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'FROM'
+ );
- return $url_sql_query;
+ if (!empty($from_clause)) {
+ $query .= ' FROM ' . $from_clause;
}
- return $this->__get('sql_query');
+ return $query;
} // end of the '_getUrlSqlQuery()' function
@@ -3211,7 +3370,7 @@ class PMA_DisplayResults
/**
* Get column order and column visibility
*
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return array 2 element array - $col_order, $col_visib
*
@@ -3219,9 +3378,9 @@ class PMA_DisplayResults
*
* @see _getTableBody()
*/
- private function _getColumnParams($analyzed_sql)
+ private function _getColumnParams($analyzed_sql_results)
{
- if ($this->_isSelect($analyzed_sql)) {
+ if ($this->_isSelect($analyzed_sql_results)) {
$pmatable = new PMA_Table($this->__get('table'), $this->__get('db'));
$col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER);
$col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB);
@@ -3237,8 +3396,7 @@ class PMA_DisplayResults
/**
* Get HTML for repeating headers
*
- * @param array $vertical_display information used with vertical
- * display mode
+ * @param array $display_params holds various display info
*
* @return string $header_html html content
*
@@ -3247,27 +3405,27 @@ class PMA_DisplayResults
* @see _getTableBody()
*/
private function _getRepeatingHeaders(
- $vertical_display
+ $display_params
) {
$header_html = '<tr>' . "\n";
- if ($vertical_display['emptypre'] > 0) {
+ if ($display_params['emptypre'] > 0) {
$header_html .= ' <th colspan="'
- . $vertical_display['emptypre'] . '">'
+ . $display_params['emptypre'] . '">'
. "\n" . ' &nbsp;</th>' . "\n";
} else if ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_NONE) {
$header_html .= ' <th></th>' . "\n";
}
- foreach ($vertical_display['desc'] as $val) {
+ foreach ($display_params['desc'] as $val) {
$header_html .= $val;
}
- if ($vertical_display['emptyafter'] > 0) {
+ if ($display_params['emptyafter'] > 0) {
$header_html
- .= ' <th colspan="' . $vertical_display['emptyafter']
+ .= ' <th colspan="' . $display_params['emptyafter']
. '">'
. "\n" . ' &nbsp;</th>' . "\n";
}
@@ -3324,7 +3482,7 @@ class PMA_DisplayResults
// Class definitions required for grid editing jQuery scripts
$edit_anchor_class = "edit_row_anchor";
- if ( $clause_is_unique == 0) {
+ if ($clause_is_unique == 0) {
$edit_anchor_class .= ' nonunique';
}
@@ -3368,7 +3526,6 @@ class PMA_DisplayResults
$lnk_goto = 'sql.php' . PMA_URL_getCommon($_url_params, 'text');
$del_query = 'DELETE FROM '
- . PMA_Util::backquote($this->__get('db')) . '.'
. PMA_Util::backquote($this->__get('table'))
. ' WHERE ' . $where_clause .
($clause_is_unique ? '' : ' LIMIT 1');
@@ -3382,8 +3539,7 @@ class PMA_DisplayResults
);
$del_url = 'sql.php' . PMA_URL_getCommon($_url_params);
- $js_conf = 'DELETE FROM ' . PMA_jsFormat($this->__get('db')) . '.'
- . PMA_jsFormat($this->__get('table'))
+ $js_conf = 'DELETE FROM ' . PMA_jsFormat($this->__get('table'))
. ' WHERE ' . PMA_jsFormat($where_clause, false)
. ($clause_is_unique ? '' : ' LIMIT 1');
@@ -3518,11 +3674,11 @@ class PMA_DisplayResults
/**
* Get the combined classes for a column
*
- * @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 $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
*
* @return string $class the combined classes
*
@@ -3575,7 +3731,7 @@ class PMA_DisplayResults
/**
* Prepare data cell for numeric type fields
*
- * @param string $column the relevant column in data row
+ * @param string $column the column's value
* @param string $class the html class for column
* @param boolean $condition_field the column should highlighted
* or not
@@ -3584,7 +3740,7 @@ class PMA_DisplayResults
* @param array $map the list of relations
* @param boolean $is_field_truncated the condition for blob data
* replacements
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results the analyzed query
* @param object|string $transformation_plugin the name of transformation plugin
* @param string $default_function the default transformation
* function
@@ -3598,7 +3754,7 @@ class PMA_DisplayResults
*/
private function _getDataCellForNumericColumns(
$column, $class, $condition_field, $meta, $map, $is_field_truncated,
- $analyzed_sql, $transformation_plugin, $default_function,
+ $analyzed_sql_results, $transformation_plugin, $default_function,
$transform_options
) {
@@ -3615,10 +3771,10 @@ class PMA_DisplayResults
$cell = $this->_getRowData(
'right ' . $class, $condition_field,
- $analyzed_sql, $meta, $map, $column,
+ $analyzed_sql_results, $meta, $map, $column,
$transformation_plugin, $default_function, $nowrap,
$where_comparison, $transform_options,
- $is_field_truncated
+ $is_field_truncated, ''
);
} else {
@@ -3635,16 +3791,20 @@ class PMA_DisplayResults
/**
* Get data cell for geometry type fields
*
- * @param string $column the relevant column in data row
- * @param string $class the html class for column
- * @param object $meta the meta-information about this field
- * @param array $map the list of relations
- * @param array $_url_params the parameters for generate url
- * @param boolean $condition_field the column should highlighted or not
- * @param string $transformation_plugin the name of transformation function
- * @param string $default_function the default transformation function
- * @param string $transform_options the transformation parameters
- * @param array $analyzed_sql the analyzed query
+ * @param string $column the relevant column in data row
+ * @param string $class the html class for column
+ * @param object $meta the meta-information about
+ * this field
+ * @param array $map the list of relations
+ * @param array $_url_params the parameters for generate url
+ * @param boolean $condition_field the column should highlighted
+ * or not
+ * @param object|string $transformation_plugin the name of transformation
+ * function
+ * @param string $default_function the default transformation
+ * function
+ * @param string $transform_options the transformation parameters
+ * @param array $analyzed_sql_results the analyzed query
*
* @return string $cell the prepared data cell, html content
*
@@ -3655,7 +3815,7 @@ class PMA_DisplayResults
private function _getDataCellForGeometryColumns(
$column, $class, $meta, $map, $_url_params, $condition_field,
$transformation_plugin, $default_function, $transform_options,
- $analyzed_sql
+ $analyzed_sql_results
) {
if (! isset($column) || is_null($column)) {
$cell = $this->_buildNullDisplay($class, $condition_field, $meta);
@@ -3670,9 +3830,8 @@ class PMA_DisplayResults
// Display as [GEOMETRY - (size)]
if ($_SESSION['tmpval']['geoOption'] == self::GEOMETRY_DISP_GEOM) {
$geometry_text = $this->_handleNonPrintableContents(
- strtoupper(self::GEOMETRY_FIELD),
- (isset($column) ? $column : ''), $transformation_plugin,
- $transform_options, $default_function, $meta
+ strtoupper(self::GEOMETRY_FIELD), $column, $transformation_plugin,
+ $transform_options, $default_function, $meta, $_url_params
);
$cell = $this->_buildValueDisplay(
@@ -3687,13 +3846,17 @@ class PMA_DisplayResults
// Convert to WKT format
$wktval = PMA_Util::asWKT($column);
- $is_field_truncated = $this->_getPartialText($wktval);
+ list(
+ $is_field_truncated,
+ $wktval,
+ // skip 3rd param
+ ) = $this->_getPartialText($wktval);
$cell = $this->_getRowData(
- $class, $condition_field, $analyzed_sql, $meta, $map,
+ $class, $condition_field, $analyzed_sql_results, $meta, $map,
$wktval, $transformation_plugin, $default_function, '',
$where_comparison, $transform_options,
- $is_field_truncated
+ $is_field_truncated, ''
);
return $cell;
}
@@ -3704,14 +3867,18 @@ class PMA_DisplayResults
$where_comparison = ' = ' . $column;
$wkbval = substr(bin2hex($column), 8);
- $is_field_truncated = $this->_getPartialText($wkbval);
+ list(
+ $is_field_truncated,
+ $wkbval,
+ // skip 3rd param
+ ) = $this->_getPartialText($wkbval);
$cell = $this->_getRowData(
$class, $condition_field,
- $analyzed_sql, $meta, $map, $wkbval,
+ $analyzed_sql_results, $meta, $map, $wkbval,
$transformation_plugin, $default_function, '',
$where_comparison, $transform_options,
- $is_field_truncated
+ $is_field_truncated, ''
);
return $cell;
}
@@ -3750,7 +3917,7 @@ class PMA_DisplayResults
* @param string $transform_options the transformation parameters
* @param boolean $is_field_truncated is data truncated due to
* LimitChars
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results the analyzed query
* @param integer &$dt_result the link id associated to
* the query which results
* have to be displayed
@@ -3765,8 +3932,10 @@ class PMA_DisplayResults
private function _getDataCellForNonNumericColumns(
$column, $class, $meta, $map, $_url_params, $condition_field,
$transformation_plugin, $default_function, $transform_options,
- $is_field_truncated, $analyzed_sql, &$dt_result, $col_index
+ $is_field_truncated, $analyzed_sql_results, &$dt_result, $col_index
) {
+ $original_length = 0;
+
$is_analyse = $this->__get('is_analyse');
$field_flags = $GLOBALS['dbi']->fieldFlags($dt_result, $col_index);
@@ -3805,7 +3974,11 @@ class PMA_DisplayResults
&& strpos($transformation_plugin->getName(), 'Link') !== false)
&& !stristr($field_flags, self::BINARY_FIELD)
) {
- $is_field_truncated = $this->_getPartialText($column);
+ list(
+ $is_field_truncated,
+ $column,
+ $original_length
+ ) = $this->_getPartialText($column);
}
$formatted = false;
@@ -3870,10 +4043,10 @@ class PMA_DisplayResults
$cell = $this->_getRowData(
$class, $condition_field,
- $analyzed_sql, $meta, $map, $column,
+ $analyzed_sql_results, $meta, $map, $column,
$transformation_plugin, $default_function, $nowrap,
$where_comparison, $transform_options,
- $is_field_truncated
+ $is_field_truncated, $original_length
);
return $cell;
@@ -3881,48 +4054,6 @@ class PMA_DisplayResults
} // end of the '_getDataCellForNonNumericColumns()' function
/**
- * Get checkboxes for multiple row data operations
- *
- * @param string $dir _left / _right
- * @param array $displayParts which elements to display
- *
- * @return String $checkBoxes_html html content
- *
- * @access private
- */
- private function _getCheckBoxesForMultipleRowOperations($dir, $displayParts)
- {
-
- $checkBoxes_html = '';
- $cell_displayed = 0;
- $vertical_display = $this->__get('vertical_display');
-
- foreach ($vertical_display['row_delete'] as $val) {
-
- if (($cell_displayed != 0)
- && ($_SESSION['tmpval']['repeat_cells'] != 0)
- && !($cell_displayed % $_SESSION['tmpval']['repeat_cells'])
- ) {
-
- $checkBoxes_html .= '<th'
- . (($displayParts['edit_lnk'] != self::NO_EDIT_OR_DELETE)
- && ($displayParts['del_lnk'] != self::NO_EDIT_OR_DELETE))
- ? ' rowspan="4"'
- : ''
- . '></th>' . "\n";
-
- }
-
- $checkBoxes_html .= str_replace('[%_PMA_CHECKBOX_DIR_%]', $dir, $val);
- $cell_displayed++;
- } // end while
-
- return $checkBoxes_html;
-
- } // end of the '_getCheckBoxesForMultipleRowOperations' function
-
-
- /**
* Checks the posted options for viewing query results
* and sets appropriate values in the session.
*
@@ -4081,15 +4212,14 @@ class PMA_DisplayResults
= $query['repeat_cells'];
}
-
/**
* Prepare a table of results returned by a SQL query.
*
- * @param integer &$dt_result the link id associated to the query
- * which results have to be displayed
- * @param array &$displayParts the parts to display
- * @param array $analyzed_sql the analyzed query
- * @param boolean $is_limited_display With limited operations or not
+ * @param integer &$dt_result the link id associated to the query
+ * which results have to be displayed
+ * @param array &$displayParts the parts to display
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param boolean $is_limited_display With limited operations or not
*
* @return string $table_html Generated HTML content for resulted table
*
@@ -4098,10 +4228,16 @@ class PMA_DisplayResults
* @see sql.php file
*/
public function getTable(
- &$dt_result, &$displayParts, $analyzed_sql,
+ &$dt_result, &$displayParts, $analyzed_sql_results,
$is_limited_display = false
) {
+ /**
+ * The statement this table is built for.
+ * @var SqlParser\Statements\SelectStatement
+ */
+ $statement = $analyzed_sql_results['statement'];
+
$table_html = '';
// Following variable are needed for use in isset/empty or
// use with array indexes/safe use in foreach
@@ -4120,10 +4256,7 @@ class PMA_DisplayResults
&& $showtable['Type'] == self::TABLE_TYPE_INNO_DB);
if ($is_innodb
- && ! isset($analyzed_sql[0]['queryflags']['union'])
- && ! isset($analyzed_sql[0]['table_ref'][1]['table_name'])
- && (empty($analyzed_sql[0]['where_clause'])
- || ($analyzed_sql[0]['where_clause'] == '1 '))
+ && PMA_isJustBrowsing($analyzed_sql_results, true)
) {
// "j u s t b r o w s i n g"
$pre_count = '~';
@@ -4148,19 +4281,28 @@ class PMA_DisplayResults
if ($displayParts['nav_bar'] == '1') {
list($pos_next, $pos_prev) = $this->_getOffsets();
} // end if
- if (!isset($analyzed_sql[0]['order_by_clause'])) {
- $analyzed_sql[0]['order_by_clause'] = "";
- }
- // 1.3 Find the sort expression
- // we need $sort_expression and $sort_expression_nodirection
- // even if there are many table references
- list(
- $sort_expression, $sort_expression_nodirection,
- $sort_direction
- ) = $this->_getSortParams($analyzed_sql[0]['order_by_clause']);
+ // 1.3 Extract sorting expressions.
+ // we need $sort_expression and $sort_expression_nodirection
+ // even if there are many table references
+ $sort_expression = array();
+ $sort_expression_nodirection = array();
+ $sort_direction = array();
+
+ if (!empty($statement->order)) {
+ foreach ($statement->order as $o) {
+ $sort_expression[] = $o->expr->expr . ' ' . $o->type;
+ $sort_expression_nodirection[] = $o->expr->expr;
+ $sort_direction[] = $o->type;
+ }
+ } else {
+ $sort_expression[] = '';
+ $sort_expression_nodirection[] = '';
+ $sort_direction[] = '';
+ }
$number_of_columns = count($sort_expression_nodirection);
+
// 1.4 Prepares display of first and last value of the sorted column
$sorted_column_message = '';
for ( $i = 0; $i < $number_of_columns; $i++ ) {
@@ -4175,8 +4317,12 @@ class PMA_DisplayResults
if (($displayParts['nav_bar'] == '1') && isset($pos_next)) {
$message = $this->_setMessageInformation(
- $sorted_column_message, $analyzed_sql[0]['limit_clause'],
- $total, $pos_next, $pre_count, $after_count
+ $sorted_column_message,
+ $analyzed_sql_results,
+ $total,
+ $pos_next,
+ $pre_count,
+ $after_count
);
$table_html .= PMA_Util::getMessage(
@@ -4194,9 +4340,7 @@ class PMA_DisplayResults
// 2.3 Prepare the navigation bars
if (!/*overload*/mb_strlen($this->__get('table'))) {
- if (isset($analyzed_sql[0]['query_type'])
- && ($analyzed_sql[0]['query_type'] == self::QUERY_TYPE_SELECT)
- ) {
+ if ($analyzed_sql_results['querytype'] == 'SELECT') {
// table does not always contain a real table name,
// for example in MySQL 5.0.x, the query SHOW STATUS
// returns STATUS as a table name
@@ -4207,15 +4351,11 @@ class PMA_DisplayResults
}
- if (($displayParts['nav_bar'] == '1')
- && empty($analyzed_sql[0]['limit_clause'])
- ) {
-
+ if (($displayParts['nav_bar'] == '1') && (empty($statement->limit))) {
$table_html .= $this->_getPlacedTableNavigations(
$pos_next, $pos_prev, self::PLACE_TOP_DIRECTION_DROPDOWN,
$is_innodb
);
-
} elseif (! isset($printview) || ($printview != '1')) {
$table_html .= "\n" . '<br /><br />' . "\n";
}
@@ -4226,18 +4366,13 @@ class PMA_DisplayResults
// initialize map
$map = array();
- // find tables
- $target=array();
- if (isset($analyzed_sql[0]['table_ref'])
- && is_array($analyzed_sql[0]['table_ref'])
- ) {
-
- foreach ($analyzed_sql[0]['table_ref']
- as $table_ref_position => $table_ref) {
- $target[] = $analyzed_sql[0]['table_ref']
- [$table_ref_position]['table_true_name'];
+ $target = array();
+ if (!empty($statement->from)) {
+ foreach ($statement->from as $field) {
+ if (!empty($field->table)) {
+ $target[] = $field->table;
+ }
}
-
}
if (/*overload*/mb_strlen($this->__get('table'))) {
@@ -4259,19 +4394,27 @@ class PMA_DisplayResults
// 3. ----- Prepare the results table -----
$table_html .= $this->_getTableHeaders(
- $displayParts, $analyzed_sql, $sort_expression,
- $sort_expression_nodirection, $sort_direction, $is_limited_display
- )
- . '<tbody>' . "\n";
+ $displayParts,
+ $analyzed_sql_results,
+ $sort_expression,
+ $sort_expression_nodirection,
+ $sort_direction,
+ $is_limited_display
+ );
+
+ $table_html .= '<tbody>' . "\n";
$table_html .= $this->_getTableBody(
- $dt_result, $displayParts, $map, $analyzed_sql, $is_limited_display
+ $dt_result,
+ $displayParts,
+ $map,
+ $analyzed_sql_results,
+ $is_limited_display
);
- $this->__set('vertical_display', null);
+ $this->__set('display_params', null);
- $table_html .= '</tbody>' . "\n"
- . '</table>';
+ $table_html .= '</tbody>' . "\n" . '</table>';
// 4. ----- Prepares the link for multi-fields edit and delete
@@ -4280,15 +4423,15 @@ class PMA_DisplayResults
) {
$table_html .= $this->_getMultiRowOperationLinks(
- $dt_result, $analyzed_sql, $displayParts['del_lnk']
+ $dt_result,
+ $analyzed_sql_results,
+ $displayParts['del_lnk']
);
}
// 5. ----- Get the navigation bar at the bottom if required -----
- if (($displayParts['nav_bar'] == '1')
- && empty($analyzed_sql[0]['limit_clause'])
- ) {
+ if (($displayParts['nav_bar'] == '1') && empty($statement->limit)) {
$table_html .= $this->_getPlacedTableNavigations(
$pos_next, $pos_prev, self::PLACE_BOTTOM_DIRECTION_DROPDOWN,
$is_innodb
@@ -4300,7 +4443,7 @@ class PMA_DisplayResults
// 6. ----- Prepare "Query results operations"
if ((! isset($printview) || ($printview != '1')) && ! $is_limited_display) {
$table_html .= $this->_getResultsOperations(
- $displayParts, $analyzed_sql
+ $displayParts, $analyzed_sql_results
);
}
@@ -4343,61 +4486,6 @@ class PMA_DisplayResults
/**
- * Get sort parameters
- *
- * @param string $order_by_clause the order by clause of the sql query
- *
- * @return array 3 element array: $sort_expression,
- * $sort_expression_nodirection, $sort_direction
- *
- * @access private
- *
- * @see getTable()
- */
- private function _getSortParams($order_by_clause)
- {
-
- $sort_expression = array();
- $sort_expression_nodirection = array();
- $sort_direction = array();
- if (! empty($order_by_clause)) {
- // Each order by clause is assumed to be delimited by a comma
- // A typical order by clause would be order by column1 asc, column2 desc
- // The following line counts the number of columns in order by clause
- $matches = explode(',', $order_by_clause);
- // Iterate over each column in order by clause
- foreach ($matches as $index=>$order_by_clause2) {
-
- $sort_expression[$index] = trim(
- str_replace(' ', ' ', $order_by_clause2)
- );
- /**
- * Get rid of ASC|DESC
- */
- preg_match(
- '@(.*)([[:space:]]*(ASC|DESC))@si',
- $sort_expression[$index], $matches
- );
-
- $sort_expression_nodirection[$index] = isset($matches[1])
- ? trim($matches[1])
- : $sort_expression[$index];
- $sort_direction[$index]
- = isset($matches[2]) ? trim($matches[2]) : '';
- }
- } else {
- $sort_expression[0] = $sort_expression_nodirection[0]
- = $sort_direction[0] = '';
- }
-
- return array($sort_expression, $sort_expression_nodirection,
- $sort_direction
- );
-
- } // end of the '_getSortParams()' function
-
-
- /**
* Prepare sorted column message
*
* @param integer &$dt_result the link id associated to the
@@ -4466,7 +4554,7 @@ class PMA_DisplayResults
$column_for_first_row = $this->_handleNonPrintableContents(
$meta->type, $row[$sorted_column_index],
$transformation_plugin, $transform_options,
- $default_function, $meta, null
+ $default_function, $meta
);
} else {
@@ -4476,7 +4564,7 @@ class PMA_DisplayResults
$column_for_first_row = /*overload*/mb_strtoupper(
/*overload*/mb_substr(
$column_for_first_row, 0, $GLOBALS['cfg']['LimitChars']
- )
+ ) . '...'
);
// fetch last row of the result set
@@ -4492,7 +4580,7 @@ class PMA_DisplayResults
$column_for_last_row = $this->_handleNonPrintableContents(
$meta->type, $row[$sorted_column_index],
$transformation_plugin, $transform_options,
- $default_function, $meta, null
+ $default_function, $meta
);
} else {
@@ -4502,7 +4590,7 @@ class PMA_DisplayResults
$column_for_last_row = /*overload*/mb_strtoupper(
/*overload*/mb_substr(
$column_for_last_row, 0, $GLOBALS['cfg']['LimitChars']
- )
+ ) . '...'
);
// reset to first row for the loop in _getTableBody()
@@ -4519,7 +4607,7 @@ class PMA_DisplayResults
* Set the content that needs to be shown in message
*
* @param string $sorted_column_message the message for sorted column
- * @param string $limit_clause the limit clause of analyzed query
+ * @param array $analyzed_sql_results the analyzed query
* @param integer $total the total number of rows returned by
* the SQL query without any
* programmatically appended LIMIT clause
@@ -4534,22 +4622,21 @@ class PMA_DisplayResults
* @see getTable()
*/
private function _setMessageInformation(
- $sorted_column_message, $limit_clause, $total,
+ $sorted_column_message, $analyzed_sql_results, $total,
$pos_next, $pre_count, $after_count
) {
$unlim_num_rows = $this->__get('unlim_num_rows'); // To use in isset()
- if (! empty($limit_clause)) {
+ if (!empty($analyzed_sql_results['statement']->limit)) {
- $limit_data
- = PMA_Util::analyzeLimitClause($limit_clause);
- $first_shown_rec = $limit_data['start'];
+ $first_shown_rec = $analyzed_sql_results['statement']->limit->offset;
+ $row_count = $analyzed_sql_results['statement']->limit->rowCount;
- if ($limit_data['length'] < $total) {
- $last_shown_rec = $limit_data['start'] + $limit_data['length'] - 1;
+ if ($row_count < $total) {
+ $last_shown_rec = $first_shown_rec + $row_count - 1;
} else {
- $last_shown_rec = $limit_data['start'] + $total - 1;
+ $last_shown_rec = $first_shown_rec + $total - 1;
}
} elseif (($_SESSION['tmpval']['max_rows'] == self::ALL_ROWS)
@@ -4566,7 +4653,8 @@ class PMA_DisplayResults
}
- if (PMA_Table::isView($this->__get('db'), $this->__get('table'))
+ $table = new PMA_Table($this->__get('table'), $this->__get('db'));
+ if ($table->isView()
&& ($total == $GLOBALS['cfg']['MaxExactCountViews'])
) {
@@ -4588,7 +4676,7 @@ class PMA_DisplayResults
$message = PMA_Message::success(__('Showing rows %1s - %2s'));
$message->addParam($first_shown_rec);
- if ($message_view_warning) {
+ if ($message_view_warning !== false) {
$message->addParam('... ' . $message_view_warning, false);
} else {
$message->addParam($last_shown_rec);
@@ -4596,7 +4684,7 @@ class PMA_DisplayResults
$message->addMessage('(');
- if (!$message_view_warning) {
+ if ($message_view_warning === false) {
if (isset($unlim_num_rows) && ($unlim_num_rows != $total)) {
$message_total = PMA_Message::notice(
@@ -4654,7 +4742,7 @@ class PMA_DisplayResults
$this->__get('db'), $this->__get('table'), '', self::POSITION_BOTH
);
- if ($exist_rel) {
+ if (! empty($exist_rel)) {
foreach ($exist_rel as $master_field => $rel) {
if ($master_field != 'foreign_keys_data') {
@@ -4697,10 +4785,10 @@ class PMA_DisplayResults
/**
* Prepare multi field edit/delete links
*
- * @param integer &$dt_result the link id associated to the query
+ * @param integer &$dt_result the link id associated to the query which results have to be displayed
* which results have to be displayed
- * @param array $analyzed_sql the analyzed query
- * @param string $del_link the display element - 'del_link'
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param string $del_link the display element - 'del_link'
*
* @return string $links_html html content
*
@@ -4709,10 +4797,10 @@ class PMA_DisplayResults
* @see getTable()
*/
private function _getMultiRowOperationLinks(
- &$dt_result, $analyzed_sql, $del_link
+ &$dt_result, $analyzed_sql_results, $del_link
) {
- $links_html = '';
+ $links_html = '<div class="print_ignore" >';
$url_query = $this->__get('url_query');
$delete_text = ($del_link == self::DELETE_ROW) ? __('Delete') : __('Kill');
@@ -4723,9 +4811,9 @@ class PMA_DisplayResults
$links_html .= '<input type="checkbox" '
. 'id="resultsForm_' . $this->__get('unique_id') . '_checkall" '
- . 'class="checkall_box" title="' . __('Check All') . '" /> '
+ . 'class="checkall_box" title="' . __('Check all') . '" /> '
. '<label for="resultsForm_' . $this->__get('unique_id') . '_checkall">'
- . __('Check All') . '</label> '
+ . __('Check all') . '</label> '
. '<i style="margin-left: 2em">' . __('With selected:') . '</i>' . "\n";
$links_html .= PMA_Util::getButtonOrImage(
@@ -4734,20 +4822,23 @@ class PMA_DisplayResults
);
$links_html .= PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_copy',
+ __('Copy'), 'b_insrow.png', 'copy'
+ );
+
+ $links_html .= PMA_Util::getButtonOrImage(
'submit_mult', 'mult_submit', 'submit_mult_delete',
$delete_text, 'b_drop.png', 'delete'
);
- if (isset($analyzed_sql[0])
- && $analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT
- ) {
+ if ($analyzed_sql_results['querytype'] == 'SELECT') {
$links_html .= PMA_Util::getButtonOrImage(
'submit_mult', 'mult_submit', 'submit_mult_export',
__('Export'), 'b_tblexport.png', 'export'
);
}
- $links_html .= "\n";
+ $links_html .= "</div>\n";
$links_html .= '<input type="hidden" name="sql_query"'
. ' value="' . htmlspecialchars($this->__get('sql_query')) . '" />'
@@ -4766,10 +4857,13 @@ class PMA_DisplayResults
// in the multi-edit and multi-delete form
list($where_clause, $clause_is_unique, $condition_array)
= PMA_Util::getUniqueCondition(
- $dt_result,
- $this->__get('fields_cnt'),
- $this->__get('fields_meta'),
- $row
+ $dt_result, // handle
+ $this->__get('fields_cnt'), // fields_cnt
+ $this->__get('fields_meta'), // fields_meta
+ $row, // row
+ false, // force_unique
+ false, // restrict_to_table
+ $analyzed_sql_results // analyzed_sql_results
);
unset($where_clause, $condition_array);
@@ -4825,8 +4919,8 @@ class PMA_DisplayResults
/**
* Generates HTML to display the Create view in span tag
*
- * @param array $analyzed_sql the analyzed Query
- * @param string $url_query String with URL Parameters
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param string $url_query String with URL Parameters
*
* @return string
*
@@ -4834,10 +4928,10 @@ class PMA_DisplayResults
*
* @see _getResultsOperations()
*/
- private function _getLinkForCreateView($analyzed_sql, $url_query)
+ private function _getLinkForCreateView($analyzed_sql_results, $url_query)
{
$results_operations_html = '';
- if (!PMA_DRIZZLE && !isset($analyzed_sql[0]['queryflags']['procedure'])) {
+ if (!PMA_DRIZZLE && empty($analyzed_sql_results['procedure'])) {
$ajax_class = ' ajax';
@@ -4845,7 +4939,7 @@ class PMA_DisplayResults
. PMA_Util::linkOrButton(
'view_create.php' . $url_query,
PMA_Util::getIcon(
- 'b_views.png', __('Create view'), true
+ 'b_view_add.png', __('Create view'), true
),
array('class' => 'create_view' . $ajax_class), true, true, ''
)
@@ -4858,14 +4952,14 @@ class PMA_DisplayResults
/**
* Calls the _getResultsOperations with $only_view as true
*
- * @param array $analyzed_sql the analyzed Query
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return string
*
* @access public
*
*/
- public function getCreateViewQueryResultOp($analyzed_sql)
+ public function getCreateViewQueryResultOp($analyzed_sql_results)
{
$results_operations_html = '';
@@ -4873,18 +4967,41 @@ class PMA_DisplayResults
//and setting only_view parameter to be true to generate just view
$results_operations_html .= $this->_getResultsOperations(
array(),
- $analyzed_sql,
+ $analyzed_sql_results,
true
);
return $results_operations_html;
}
/**
+ * Get printview links for results operations
+ *
+ * @return string $html
+ *
+ * @access private
+ */
+ private function _getPrintviewLinks()
+ {
+ $html = PMA_Util::linkOrButton(
+ '#',
+ PMA_Util::getIcon(
+ 'b_print.png', __('Print view'), true
+ ),
+ array('id' => 'printView'),
+ true,
+ true,
+ 'print_view'
+ );
+
+ return $html;
+ }
+
+ /**
* Get operations that are available on results.
*
- * @param array $displayParts the parts to display
- * @param array $analyzed_sql the analyzed query
- * @param boolean $only_view Whether to show only view
+ * @param array $displayParts the parts to display
+ * @param array $analyzed_sql_results analyzed sql results
+ * @param boolean $only_view Whether to show only view
*
* @return string $results_operations_html html content
*
@@ -4893,14 +5010,14 @@ class PMA_DisplayResults
* @see getTable()
*/
private function _getResultsOperations(
- $displayParts, $analyzed_sql, $only_view = false
+ $displayParts, $analyzed_sql_results, $only_view = false
) {
global $printview;
$results_operations_html = '';
$fields_meta = $this->__get('fields_meta'); // To safe use in foreach
$header_shown = false;
- $header = '<fieldset><legend>' . __('Query results operations')
+ $header = '<fieldset class="print_ignore" ><legend>' . __('Query results operations')
. '</legend>';
$_url_params = array(
@@ -4917,9 +5034,9 @@ class PMA_DisplayResults
}
// if empty result set was produced we need to
// show only view and not other options
- if ($only_view == true) {
+ if ($only_view) {
$results_operations_html .= $this->_getLinkForCreateView(
- $analyzed_sql, $url_query
+ $analyzed_sql_results, $url_query
);
if ($header_shown) {
@@ -4928,46 +5045,10 @@ class PMA_DisplayResults
return $results_operations_html;
}
- if (($displayParts['ins_row'] == '1')
- || ($displayParts['pview_lnk'] == '1')
- ) {
- // Displays "printable view" link if required
- if ($displayParts['pview_lnk'] == '1') {
-
- $results_operations_html
- .= PMA_Util::linkOrButton(
- 'sql.php' . $url_query,
- PMA_Util::getIcon(
- 'b_print.png', __('Print view'), true
- ),
- array('target' => 'print_view'),
- true,
- true,
- 'print_view'
- )
- . "\n";
-
- if ($_SESSION['tmpval']['pftext']) {
-
- $_url_params['pftext'] = self::DISPLAY_FULL_TEXT;
-
- $results_operations_html
- .= PMA_Util::linkOrButton(
- 'sql.php' . PMA_URL_getCommon($_url_params),
- PMA_Util::getIcon(
- 'b_print.png',
- __('Print view (with full texts)'), true
- ),
- array('target' => 'print_view'),
- true,
- true,
- 'print_view'
- )
- . "\n";
- unset($_url_params['pftext']);
- }
- } // end displays "printable view"
- }
+ // Displays "printable view" link if required
+ if ($displayParts['pview_lnk'] == '1') {
+ $results_operations_html .= $this->_getPrintviewLinks();
+ } // end displays "printable view"
// Export link
// (the url_query has extra parameters that won't be used to export)
@@ -4976,15 +5057,12 @@ class PMA_DisplayResults
// If the parser found a PROCEDURE clause
// (most probably PROCEDURE ANALYSE()) it makes no sense to
// display the Export link).
- if (isset($analyzed_sql[0])
- && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT)
+ if (($analyzed_sql_results['querytype'] == self::QUERY_TYPE_SELECT)
&& ! isset($printview)
- && ! isset($analyzed_sql[0]['queryflags']['procedure'])
+ && empty($analyzed_sql_results['procedure'])
) {
- if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name'])
- && ! isset($analyzed_sql[0]['table_ref'][1]['table_true_name'])
- ) {
+ if (count($analyzed_sql_results['select_tables']) == 1) {
$_url_params['single_table'] = 'true';
}
@@ -5077,7 +5155,7 @@ class PMA_DisplayResults
}
$results_operations_html .= $this->_getLinkForCreateView(
- $analyzed_sql, $url_query
+ $analyzed_sql_results, $url_query
);
if ($header_shown) {
@@ -5173,7 +5251,11 @@ class PMA_DisplayResults
) {
// in this case, restart from the original $content
$result = bin2hex($content);
- $is_truncated = $this->_getPartialText($result);
+ list(
+ $is_truncated,
+ $result,
+ // skip 3rd param
+ ) = $this->_getPartialText($result);
}
/* Create link to download */
@@ -5193,13 +5275,54 @@ class PMA_DisplayResults
/**
+ * Retrieves the associated foreign key info for a data cell
+ *
+ * @param array $map the list of relations
+ * @param object $meta the meta-information about the field
+ * @param string $where_comparison data for the where clause
+ *
+ * @return string formatted data
+ *
+ * @access private
+ *
+ */
+ private function _getFromForeign($map, $meta, $where_comparison)
+ {
+ $dispsql = 'SELECT '
+ . PMA_Util::backquote($map[$meta->name][2])
+ . ' FROM '
+ . PMA_Util::backquote($map[$meta->name][3])
+ . '.'
+ . PMA_Util::backquote($map[$meta->name][0])
+ . ' WHERE '
+ . PMA_Util::backquote($map[$meta->name][1])
+ . $where_comparison;
+
+ $dispresult = $GLOBALS['dbi']->tryQuery(
+ $dispsql,
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+
+ if ($dispresult && $GLOBALS['dbi']->numRows($dispresult) > 0) {
+ list($dispval) = $GLOBALS['dbi']->fetchRow($dispresult, 0);
+ } else {
+ $dispval = __('Link not found!');
+ }
+
+ @$GLOBALS['dbi']->freeResult($dispresult);
+
+ return $dispval;
+ }
+
+ /**
* Prepares the displayable content of a data cell in Browse mode,
* taking into account foreign key description field and transformations
*
* @param string $class css classes for the td element
* @param bool $condition_field whether the column is a part of
* the where clause
- * @param array $analyzed_sql the analyzed query
+ * @param array $analyzed_sql_results the analyzed query
* @param object $meta the meta-information about the
* field
* @param array $map the list of relations
@@ -5213,6 +5336,7 @@ class PMA_DisplayResults
* @param string $where_comparison data for the where clause
* @param array $transform_options options for transformation
* @param bool $is_field_truncated whether the field is truncated
+ * @param string $original_length of a truncated column, or ''
*
* @return string formatted data
*
@@ -5223,48 +5347,38 @@ class PMA_DisplayResults
*
*/
private function _getRowData(
- $class, $condition_field, $analyzed_sql, $meta, $map, $data,
+ $class, $condition_field, $analyzed_sql_results, $meta, $map, $data,
$transformation_plugin, $default_function, $nowrap, $where_comparison,
- $transform_options, $is_field_truncated
+ $transform_options, $is_field_truncated, $original_length=''
) {
-
$relational_display = $_SESSION['tmpval']['relational_display'];
$printview = $this->__get('printview');
$decimals = isset($meta->decimals) ? $meta->decimals : '-1';
- $result = '<td data-decimals="' . $decimals . '" data-type="'
- . $meta->type . '" class="'
+ $result = '<td data-decimals="' . $decimals . '"'
+ . ' data-type="' . $meta->type . '"';
+
+ if (! empty($original_length)) {
+ // cannot use data-original-length
+ $result .= ' data-originallength="' . $original_length . '"';
+ }
+
+ $result .= ' class="'
. $this->_addClass(
$class, $condition_field, $meta, $nowrap,
$is_field_truncated, $transformation_plugin, $default_function
)
. '">';
- if (isset($analyzed_sql[0]['select_expr'])
- && is_array($analyzed_sql[0]['select_expr'])
- ) {
-
- foreach ($analyzed_sql[0]['select_expr']
- as $select_expr_position => $select_expr
- ) {
-
- $alias = $analyzed_sql[0]['select_expr']
- [$select_expr_position]['alias'];
-
- if (!isset($alias) || !/*overload*/mb_strlen($alias)) {
+ if (!empty($analyzed_sql_results['statement']->expr)) {
+ foreach ($analyzed_sql_results['statement']->expr as $expr) {
+ if ((empty($expr->alias)) || (empty($expr->column))) {
continue;
- } // end if
-
- $true_column = $analyzed_sql[0]['select_expr']
- [$select_expr_position]['column'];
-
- if ($alias == $meta->name) {
- // this change in the parameter does not matter
- // outside of the function
- $meta->name = $true_column;
- } // end if
-
- } // end foreach
- } // end if
+ }
+ if (strcasecmp($meta->name, $expr->alias) == 0) {
+ $meta->name = $expr->column;
+ }
+ }
+ }
if (isset($map[$meta->name])) {
@@ -5272,33 +5386,11 @@ class PMA_DisplayResults
if (isset($map[$meta->name][2])
&& /*overload*/mb_strlen($map[$meta->name][2])
) {
-
- $dispsql = 'SELECT '
- . PMA_Util::backquote($map[$meta->name][2])
- . ' FROM '
- . PMA_Util::backquote($map[$meta->name][3])
- . '.'
- . PMA_Util::backquote($map[$meta->name][0])
- . ' WHERE '
- . PMA_Util::backquote($map[$meta->name][1])
- . $where_comparison;
-
- $dispresult = $GLOBALS['dbi']->tryQuery(
- $dispsql,
- null,
- PMA_DatabaseInterface::QUERY_STORE
+ $dispval = $this->_getFromForeign(
+ $map, $meta, $where_comparison
);
-
- if ($dispresult && $GLOBALS['dbi']->numRows($dispresult) > 0) {
- list($dispval) = $GLOBALS['dbi']->fetchRow($dispresult, 0);
- } else {
- $dispval = __('Link not found!');
- }
-
- @$GLOBALS['dbi']->freeResult($dispresult);
-
} else {
- $dispval = '';
+ $dispval = '';
} // end if... else...
if (isset($printview) && ($printview == '1')) {
@@ -5332,16 +5424,10 @@ class PMA_DisplayResults
'table' => $map[$meta->name][0],
'pos' => '0',
'sql_query' => 'SELECT * FROM '
- . PMA_Util::backquote(
- $map[$meta->name][3]
- ) . '.'
- . PMA_Util::backquote(
- $map[$meta->name][0]
- )
+ . PMA_Util::backquote($map[$meta->name][3]) . '.'
+ . PMA_Util::backquote($map[$meta->name][0])
. ' WHERE '
- . PMA_Util::backquote(
- $map[$meta->name][1]
- )
+ . PMA_Util::backquote($map[$meta->name][1])
. $where_comparison,
);
@@ -5360,7 +5446,7 @@ class PMA_DisplayResults
} else {
if ($relational_display == self::RELATIONAL_DISPLAY_COLUMN
- && ! empty($map[$meta->name][2])
+ && ! empty($map[$meta->name][2])
) {
// user chose "relational display field" in the
// display options, so show display field in the cell
@@ -5424,7 +5510,7 @@ class PMA_DisplayResults
$ret .= 'class="' . $class . '"';
}
- $ret .= ' class="center">'
+ $ret .= ' class="center print_ignore">'
. '<input type="checkbox" id="id_rows_to_delete'
. $row_no . $id_suffix
. '" name="rows_to_delete[' . $row_no . ']"'
@@ -5463,7 +5549,7 @@ class PMA_DisplayResults
$ret = '';
if (! empty($edit_url)) {
- $ret .= '<td class="' . $class . ' center" ' . ' ><span class="nowrap">'
+ $ret .= '<td class="' . $class . ' center print_ignore" ' . ' ><span class="nowrap">'
. PMA_Util::linkOrButton(
$edit_url, $edit_str, array(), false
);
@@ -5510,7 +5596,7 @@ class PMA_DisplayResults
$ret .= $class . ' ';
}
- $ret .= 'center" ' . ' ><span class="nowrap">'
+ $ret .= 'center print_ignore" ' . ' ><span class="nowrap">'
. PMA_Util::linkOrButton(
$copy_url, $copy_str, array(), false
);
@@ -5556,7 +5642,7 @@ class PMA_DisplayResults
$ret .= $class . ' ';
}
$ajax = PMA_Response::getInstance()->isAjax() ? ' ajax' : '';
- $ret .= 'center" ' . ' >'
+ $ret .= 'center print_ignore" ' . ' >'
. PMA_Util::linkOrButton(
$del_url, $del_str, array('class' => 'delete_row requireConfirm' . $ajax), false
)
@@ -5633,15 +5719,15 @@ class PMA_DisplayResults
);
$ret .= $this->_getCheckboxForMultiRowSubmissions(
- $del_url, $displayParts, $row_no, $where_clause_html, $condition_array,
- '_right', ''
+ $del_url, $displayParts, $row_no, $where_clause_html,
+ $condition_array, '_right', ''
);
} else { // $position == self::POSITION_NONE
$ret .= $this->_getCheckboxForMultiRowSubmissions(
- $del_url, $displayParts, $row_no, $where_clause_html, $condition_array,
- '_left', ''
+ $del_url, $displayParts, $row_no, $where_clause_html,
+ $condition_array, '_left', ''
);
}
@@ -5649,35 +5735,35 @@ class PMA_DisplayResults
} // end of the '_getCheckboxAndLinks()' function
-
/**
* Truncates given string based on LimitChars configuration
* and Session pftext variable
* (string is truncated only if necessary)
*
- * @param string &$str string to be truncated
+ * @param string $str string to be truncated
*
- * @return boolean true if truncated, otherwise false
+ * @return mixed
*
* @access private
*
* @see _handleNonPrintableContents(), _getDataCellForGeometryColumns(),
* _getDataCellForNonNumericColumns
*/
- private function _getPartialText(&$str)
+ private function _getPartialText($str)
{
- if (/*overload*/mb_strlen($str) > $GLOBALS['cfg']['LimitChars']
+ $original_length = /*overload*/mb_strlen($str);
+ if ($original_length > $GLOBALS['cfg']['LimitChars']
&& $_SESSION['tmpval']['pftext'] === self::DISPLAY_PARTIAL_TEXT
) {
$str = /*overload*/mb_substr(
$str, 0, $GLOBALS['cfg']['LimitChars']
) . '...';
-
- return true;
+ $truncated = true;
+ } else {
+ $truncated = false;
}
- return false;
+ return array($truncated, $str, $original_length);
}
}
-?>
diff --git a/libraries/Error.class.php b/libraries/Error.class.php
index 87d0ef9423..fddeceb874 100644
--- a/libraries/Error.class.php
+++ b/libraries/Error.class.php
@@ -288,9 +288,8 @@ class PMA_Error extends PMA_Message
* @param string $lines Lines separator to use
*
* @return string formatted backtrace
- * @static
*/
- static function formatBacktrace($backtrace, $separator, $lines)
+ public static function formatBacktrace($backtrace, $separator, $lines)
{
$retval = '';
@@ -316,9 +315,8 @@ class PMA_Error extends PMA_Message
* @param string $separator Arguments separator to use
*
* @return string
- * @static
*/
- static function getFunctionCall($step, $separator)
+ public static function getFunctionCall($step, $separator)
{
$retval = $step['function'] . '(';
if (isset($step['args'])) {
@@ -349,9 +347,8 @@ class PMA_Error extends PMA_Message
* @param string $function function name
*
* @return string
- * @static
*/
- static function getArg($arg, $function)
+ public static function getArg($arg, $function)
{
$retval = '';
$include_functions = array(
@@ -431,9 +428,8 @@ class PMA_Error extends PMA_Message
* @param string $dest path to be shorten
*
* @return string shortened path
- * @static
*/
- static function relPath($dest)
+ public static function relPath($dest)
{
$dest = realpath($dest);
@@ -467,4 +463,3 @@ class PMA_Error extends PMA_Message
);
}
}
-?>
diff --git a/libraries/Error_Handler.class.php b/libraries/Error_Handler.class.php
index 5cffd9880f..d8518a2d7a 100644
--- a/libraries/Error_Handler.class.php
+++ b/libraries/Error_Handler.class.php
@@ -25,7 +25,7 @@ class PMA_Error_Handler
/**
* holds errors to be displayed or reported later ...
*
- * @var array of PMA_Error
+ * @var PMA_Error[]
*/
protected $errors = array();
@@ -86,7 +86,7 @@ class PMA_Error_Handler
/**
* returns array with all errors
*
- * @return array PMA_Error_Handler::$_errors
+ * @return PMA_Error[]
*/
protected function getErrors()
{
@@ -98,7 +98,7 @@ class PMA_Error_Handler
* returns the errors occurred in the current run only.
* Does not include the errors save din the SESSION
*
- * @return array of current errors
+ * @return PMA_Error[]
*/
public function getCurrentErrors()
{
@@ -305,10 +305,7 @@ class PMA_Error_Handler
$retval .= $error->getDisplay();
}
} else {
- ob_start();
- var_dump($error);
- $retval .= ob_get_contents();
- ob_end_clean();
+ $retval .= var_export($error, true);
}
}
} else {
@@ -334,25 +331,23 @@ class PMA_Error_Handler
. '<input type="hidden" name="send_error_report" value="1" />'
. '<input type="submit" value="'
. __('Report')
- . '" id="pma_report_errors" style="float: right; margin: 20px;">'
+ . '" id="pma_report_errors" class="floatright">'
. '<input type="checkbox" name="always_send"'
. ' id="always_send_checkbox" value="true"/>'
. '<label for="always_send_checkbox">'
. __('Automatically send report next time')
- . '</label>'
- . '</form>';
+ . '</label>';
if ($GLOBALS['cfg']['SendErrorReports'] == 'ask') {
// add ignore buttons
$retval .= '<input type="submit" value="'
. __('Ignore')
- . '" id="pma_ignore_errors_bottom"'
- . ' style="float: right; margin: 20px;">';
+ . '" id="pma_ignore_errors_bottom" class="floatright">';
}
$retval .= '<input type="submit" value="'
. __('Ignore All')
- . '" id="pma_ignore_all_errors_bottom"'
- . ' style="float: right; margin: 20px;">';
+ . '" id="pma_ignore_all_errors_bottom" class="floatright">';
+ $retval .= '</form>';
}
return $retval;
}
@@ -500,7 +495,6 @@ class PMA_Error_Handler
*
* @return void
*/
-
public function reportErrors()
{
// if there're no actual errors,
@@ -541,11 +535,13 @@ class PMA_Error_Handler
function() {
PMA_ignorePhpErrors(false)
});'
- . '$("#pma_ignore_errors_bottom").bind("click", function() {
+ . '$("#pma_ignore_errors_bottom").bind("click", function(e) {
+ e.preventDefaulut();
PMA_ignorePhpErrors()
});'
. '$("#pma_ignore_all_errors_bottom").bind("click",
- function() {
+ function(e) {
+ e.preventDefault();
PMA_ignorePhpErrors(false)
});'
. '$("html, body").animate({
@@ -558,4 +554,3 @@ class PMA_Error_Handler
$response->getFooter()->getScripts()->addCode($jsCode);
}
}
-?>
diff --git a/libraries/File.class.php b/libraries/File.class.php
index fab384d994..1929f9603e 100644
--- a/libraries/File.class.php
+++ b/libraries/File.class.php
@@ -83,7 +83,7 @@ class PMA_File
*/
public function __construct($name = false)
{
- if ($name) {
+ if ($name && is_string($name)) {
$this->setName($name);
}
}
@@ -261,13 +261,21 @@ class PMA_File
case 4: //UPLOAD_ERR_NO_FILE:
break;
case 1: //UPLOAD_ERR_INI_SIZE:
- $this->_error_message = __('The uploaded file exceeds the upload_max_filesize directive in php.ini.');
+ $this->_error_message = __(
+ 'The uploaded file exceeds the upload_max_filesize directive in '
+ . 'php.ini.'
+ );
break;
case 2: //UPLOAD_ERR_FORM_SIZE:
- $this->_error_message = __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.');
+ $this->_error_message = __(
+ 'The uploaded file exceeds the MAX_FILE_SIZE directive that was '
+ . 'specified in the HTML form.'
+ );
break;
case 3: //UPLOAD_ERR_PARTIAL:
- $this->_error_message = __('The uploaded file was only partially uploaded.');
+ $this->_error_message = __(
+ 'The uploaded file was only partially uploaded.'
+ );
break;
case 6: //UPLOAD_ERR_NO_TMP_DIR:
$this->_error_message = __('Missing a temporary folder.');
@@ -458,7 +466,9 @@ class PMA_File
|| ! is_writable($GLOBALS['cfg']['TempDir'])
) {
// cannot create directory or access, point user to FAQ 1.11
- $this->_error_message = __('Error moving the uploaded file, see [doc@faq1-11]FAQ 1.11[/doc].');
+ $this->_error_message = __(
+ 'Error moving the uploaded file, see [doc@faq1-11]FAQ 1.11[/doc].'
+ );
return false;
}
@@ -484,7 +494,7 @@ class PMA_File
$this->isTemp(true);
if (! $this->isReadable()) {
- $this->_error_message = __('Cannot read (moved) upload file.');
+ $this->_error_message = __('Cannot read uploaded file.');
return false;
}
@@ -575,7 +585,11 @@ class PMA_File
public function errorUnsupported()
{
$this->_error_message = sprintf(
- __('You attempted to load file with unsupported compression (%s). Either support for it is not implemented or disabled by your configuration.'),
+ __(
+ 'You attempted to load file with unsupported compression (%s). '
+ . 'Either support for it is not implemented or disabled by your '
+ . 'configuration.'
+ ),
$this->getCompression()
);
}
@@ -729,4 +743,3 @@ class PMA_File
}
}
-?>
diff --git a/libraries/Font.class.php b/libraries/Font.class.php
index 78d561f142..31209f9185 100644
--- a/libraries/Font.class.php
+++ b/libraries/Font.class.php
@@ -142,4 +142,3 @@ class PMA_Font
return (int)ceil($textWidth * $modifier);
}
}
-?>
diff --git a/libraries/Footer.class.php b/libraries/Footer.class.php
index 19753ecee0..ddedcb4dba 100644
--- a/libraries/Footer.class.php
+++ b/libraries/Footer.class.php
@@ -85,35 +85,51 @@ class PMA_Footer
}
/**
+ * Remove recursions and iterator objects from an object
+ *
+ * @param object|array &$object Object to clean
+ * @param array $stack Stack used to keep track of recursion,
+ * need not be passed for the first time
+ *
+ * @return object Reference passed object
+ */
+ private static function _removeRecursion(&$object, $stack = array())
+ {
+ if ((is_object($object) || is_array($object)) && $object) {
+ if ($object instanceof Traversable) {
+ $object = "***ITERATOR***";
+ } else if (!in_array($object, $stack, true)) {
+ $stack[] = $object;
+ foreach ($object as &$subobject) {
+ self::_removeRecursion($subobject, $stack);
+ }
+ } else {
+ $object = "***RECURSION***";
+ }
+ }
+ return $object;
+ }
+
+ /**
* Renders the debug messages
*
* @return string
*/
public function getDebugMessage()
{
- $retval = '';
- if (! empty($_SESSION['debug'])) {
- $sum_time = 0;
- $sum_exec = 0;
- foreach ($_SESSION['debug']['queries'] as $query) {
- $sum_time += $query['count'] * $query['time'];
- $sum_exec += $query['count'];
- }
-
- $retval .= '<div id="session_debug">';
- $retval .= count($_SESSION['debug']['queries']) . ' queries executed ';
- $retval .= $sum_exec . ' times in ' . $sum_time . ' seconds';
- $retval .= '<pre>';
-
- ob_start();
- print_r($_SESSION['debug']);
- $retval .= ob_get_contents();
- ob_end_clean();
+ $retval = '\'null\'';
+ if ($GLOBALS['cfg']['DBG']['sql']
+ && empty($_REQUEST['no_debug'])
+ && !empty($_SESSION['debug'])
+ ) {
+ // Remove recursions and iterators from $_SESSION['debug']
+ self::_removeRecursion($_SESSION['debug']);
- $retval .= '</pre>';
- $retval .= '</div>';
+ $retval = JSON_encode($_SESSION['debug']);
$_SESSION['debug'] = array();
+ return json_last_error() ? '\'false\'' : $retval;
}
+ $_SESSION['debug'] = array();
return $retval;
}
@@ -257,7 +273,7 @@ class PMA_Footer
*/
public function setAjax($isAjax)
{
- $this->_isAjax = ($isAjax == true);
+ $this->_isAjax = !!$isAjax;
}
/**
@@ -306,7 +322,8 @@ class PMA_Footer
// prime the client-side cache
$this->_scripts->addCode(
sprintf(
- 'AJAX.cache.primer = {'
+ 'if (! (history && history.pushState)) '
+ . 'PMA_Microhistory.primer = {'
. ' url: "%s",'
. ' scripts: %s,'
. ' menuHash: "%s"'
@@ -323,7 +340,9 @@ class PMA_Footer
$url = $this->getSelfUrl();
$retval .= $this->_getSelfLink($url);
}
- $retval .= $this->getDebugMessage();
+ $this->_scripts->addCode(
+ 'var debugSQLInfo = ' . $this->getDebugMessage() . ';'
+ );
$retval .= $this->getErrorMessages();
$retval .= $this->_scripts->getDisplay();
if ($GLOBALS['cfg']['DBG']['demo']) {
diff --git a/libraries/Header.class.php b/libraries/Header.class.php
index 83dbde5b0e..bc3de55cea 100644
--- a/libraries/Header.class.php
+++ b/libraries/Header.class.php
@@ -205,6 +205,8 @@ class PMA_Header
$this->_scripts->addFile('navigation.js');
$this->_scripts->addFile('indexes.js');
$this->_scripts->addFile('common.js');
+ $this->_scripts->addFile('config.js');
+ $this->_scripts->addFile('page_settings.js');
$this->_scripts->addCode($this->getJsParamsCode());
}
@@ -228,7 +230,9 @@ class PMA_Header
$params = array(
'common_query' => PMA_URL_getCommon(array(), 'text'),
- 'opendb_url' => $GLOBALS['cfg']['DefaultTabDatabase'],
+ 'opendb_url' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ ),
'safari_browser' => PMA_USR_BROWSER_AGENT == 'SAFARI' ? 1 : 0,
'collation_connection' => $GLOBALS['collation_connection'],
'lang' => $GLOBALS['lang'],
@@ -252,7 +256,8 @@ class PMA_Header
'pftext' => $pftext,
'confirm' => $GLOBALS['cfg']['Confirm'],
'LoginCookieValidity' => $GLOBALS['cfg']['LoginCookieValidity'],
- 'logged_in' => isset($GLOBALS['userlink']) ? true : false
+ 'logged_in' => isset($GLOBALS['userlink']) ? true : false,
+ 'PMA_VERSION' => PMA_VERSION
);
if (isset($GLOBALS['cfg']['Server'])
&& isset($GLOBALS['cfg']['Server']['auth_type'])
@@ -298,7 +303,7 @@ class PMA_Header
*/
public function setAjax($isAjax)
{
- $this->_isAjax = ($isAjax == true);
+ $this->_isAjax = !!$isAjax;
$this->_console->setAjax($isAjax);
}
@@ -403,7 +408,17 @@ class PMA_Header
$this->_scripts->addFile('codemirror/addon/runmode/runmode.js');
$this->_scripts->addFile('codemirror/addon/hint/show-hint.js');
$this->_scripts->addFile('codemirror/addon/hint/sql-hint.js');
+ if ($GLOBALS['cfg']['LintEnable']) {
+ $this->_scripts->addFile('codemirror/addon/lint/lint.js');
+ $this->_scripts->addFile(
+ 'codemirror/addon/lint/sql-lint.js'
+ );
+ }
}
+ $this->_scripts->addCode(
+ 'ConsoleEnterExecutes='
+ . ($GLOBALS['cfg']['ConsoleEnterExecutes'] ? 'true' : 'false')
+ );
$this->_scripts->addFiles($this->_console->getScripts());
if ($this->_userprefsOfferImport) {
$this->_scripts->addFile('config.js');
@@ -439,7 +454,14 @@ class PMA_Header
$retval .= $this->_getWarnings();
if ($this->_menuEnabled && $GLOBALS['server'] > 0) {
$retval .= $this->_menu->getDisplay();
+ $retval .= '<span id="page_nav_icons">';
$retval .= '<span id="lock_page_icon"></span>';
+ $retval .= '<span id="page_settings_icon">'
+ . PMA_Util::getImage(
+ 's_cog.png',
+ __('Page-related settings')
+ )
+ . '</span>';
$retval .= sprintf(
'<a id="goto_pagetop" href="#">%s</a>',
PMA_Util::getImage(
@@ -447,6 +469,7 @@ class PMA_Header
__('Click on the bar to scroll to top of page')
)
);
+ $retval .= '</span>';
}
$retval .= $this->_console->getDisplay();
$retval .= '<div id="page_content">';
@@ -629,18 +652,28 @@ class PMA_Header
$basedir = defined('PMA_PATH_TO_BASEDIR') ? PMA_PATH_TO_BASEDIR : '';
$theme_id = $GLOBALS['PMA_Config']->getThemeUniqueValue();
$theme_path = $GLOBALS['pmaThemePath'];
+ $v = self::getVersionParameter();
if ($this->_isPrintView) {
$retval .= '<link rel="stylesheet" type="text/css" href="'
- . $basedir . 'print.css" />';
+ . $basedir . 'print.css?' . $v . '" />';
} else {
// load jQuery's CSS prior to our theme's CSS, to let the theme
// override jQuery's CSS
$retval .= '<link rel="stylesheet" type="text/css" href="'
. $theme_path . '/jquery/jquery-ui-1.11.2.css" />';
$retval .= '<link rel="stylesheet" type="text/css" href="'
+ . $basedir . 'js/codemirror/lib/codemirror.css?' . $v . '" />';
+ $retval .= '<link rel="stylesheet" type="text/css" href="'
+ . $basedir . 'js/codemirror/addon/hint/show-hint.css?' . $v . '" />';
+ $retval .= '<link rel="stylesheet" type="text/css" href="'
+ . $basedir . 'js/codemirror/addon/lint/lint.css?' . $v . '" />';
+ $retval .= '<link rel="stylesheet" type="text/css" href="'
. $basedir . 'phpmyadmin.css.php?'
. 'nocache=' . $theme_id . $GLOBALS['text_dir'] . '" />';
+ // load Print view's CSS last, so that it overrides all other CSS while 'printing'
+ $retval .= '<link rel="stylesheet" type="text/css" href="'
+ . $theme_path . '/css/printview.css?' . $v . '" />';
}
return $retval;
@@ -748,6 +781,16 @@ class PMA_Header
}
return $retval;
}
+
+ /**
+ * Returns the phpMyAdmin version to be appended to the url to avoid caching
+ * between versions
+ *
+ * @return string urlenocded pma version as a parameter
+ */
+ public static function getVersionParameter()
+ {
+ return "v=" . urlencode(PMA_VERSION);
+ }
}
-?>
diff --git a/libraries/Index.class.php b/libraries/Index.class.php
index f24d4343c9..555bbabd53 100644
--- a/libraries/Index.class.php
+++ b/libraries/Index.class.php
@@ -17,6 +17,12 @@ if (! defined('PHPMYADMIN')) {
*/
class PMA_Index
{
+ const PRIMARY = 1;
+ const UNIQUE = 2;
+ const INDEX = 4;
+ const SPATIAL = 8;
+ const FULLTEXT = 16;
+
/**
* Class-wide storage container for indexes (caching, singleton)
*
@@ -141,7 +147,7 @@ class PMA_Index
* @param string $table table
* @param string $schema schema
*
- * @return array array of indexes
+ * @return PMA_Index[] array of indexes
*/
static public function getFromTable($table, $schema)
{
@@ -155,6 +161,48 @@ class PMA_Index
}
/**
+ * Returns an array with all indexes from the given table of the requested types
+ *
+ * @param string $table table
+ * @param string $schema schema
+ * @param int $choices choices
+ *
+ * @return PMA_Index[] array of indexes
+ */
+ static public function getFromTableByChoice($table, $schema, $choices = 31)
+ {
+ $indexes = array();
+ foreach (self::getFromTable($table, $schema) as $index) {
+ if (($choices & PMA_Index::PRIMARY)
+ && $index->getChoice() == 'PRIMARY'
+ ) {
+ $indexes[] = $index;
+ }
+ if (($choices & PMA_Index::UNIQUE)
+ && $index->getChoice() == 'UNIQUE'
+ ) {
+ $indexes[] = $index;
+ }
+ if (($choices & PMA_Index::INDEX)
+ && $index->getChoice() == 'INDEX'
+ ) {
+ $indexes[] = $index;
+ }
+ if (($choices & PMA_Index::SPATIAL)
+ && $index->getChoice() == 'SPATIAL'
+ ) {
+ $indexes[] = $index;
+ }
+ if (($choices & PMA_Index::FULLTEXT)
+ && $index->getChoice() == 'FULLTEXT'
+ ) {
+ $indexes[] = $index;
+ }
+ }
+ return $indexes;
+ }
+
+ /**
* return primary if set, false otherwise
*
* @param string $table table
@@ -610,7 +658,7 @@ class PMA_Index
*
* @access public
*/
- static public function getView($table, $schema, $print_mode = false)
+ static public function getHtmlForIndexes($table, $schema, $print_mode = false)
{
$indexes = PMA_Index::getFromTable($table, $schema);
@@ -642,7 +690,7 @@ class PMA_Index
$r .= '<thead>';
$r .= '<tr>';
if (! $print_mode) {
- $r .= '<th colspan="2">' . __('Action') . '</th>';
+ $r .= '<th colspan="2" class="print_ignore">' . __('Action') . '</th>';
}
$r .= '<th>' . __('Keyname') . '</th>';
$r .= '<th>' . __('Type') . '</th>';
@@ -666,7 +714,7 @@ class PMA_Index
if (! $print_mode) {
$this_params = $GLOBALS['url_params'];
$this_params['index'] = $index->getName();
- $r .= '<td class="edit_index';
+ $r .= '<td class="edit_index print_ignore';
$r .= ' ajax';
$r .= '" ' . $row_span . '>'
. ' <a class="';
@@ -699,7 +747,7 @@ class PMA_Index
}
- $r .= '<td ' . $row_span . '>';
+ $r .= '<td ' . $row_span . ' class="print_ignore">';
$r .= '<input type="hidden" class="drop_primary_key_index_msg"'
. ' value="' . $js_msg . '" />';
$r .= ' <a class="drop_primary_key_index_anchor';
@@ -822,7 +870,10 @@ class PMA_Index
// so it makes no sense to have this two equal indexes
$message = PMA_Message::notice(
- __('The indexes %1$s and %2$s seem to be equal and one of them could possibly be removed.')
+ __(
+ 'The indexes %1$s and %2$s seem to be equal and one of them '
+ . 'could possibly be removed.'
+ )
);
$message->addParam($each_index->getName());
$message->addParam($while_index->getName());
@@ -1008,4 +1059,3 @@ class PMA_Index_Column
);
}
}
-?>
diff --git a/libraries/Linter.class.php b/libraries/Linter.class.php
new file mode 100644
index 0000000000..db5ae01c8c
--- /dev/null
+++ b/libraries/Linter.class.php
@@ -0,0 +1,177 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Analyzes a query and gives user feedback.
+ *
+ * @package PhpMyAdmin
+ */
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+/**
+ * The linter itself.
+ *
+ * @package PhpMyAdmin
+ */
+class PMA_Linter
+{
+
+ /**
+ * Gets the starting position of each line.
+ *
+ * @param string $str String to be analyzed.
+ *
+ * @return array
+ */
+ public static function getLines($str)
+ {
+ if ((!($str instanceof UtfString))
+ && (defined('USE_UTF_STRINGS')) && (USE_UTF_STRINGS)
+ ) {
+ // If the lexer uses UtfString for processing then the position will
+ // represent the position of the character and not the position of
+ // the byte.
+ $str = new SqlParser\UtfString($str);
+ }
+
+ // The reason for using the '8bit' parameter is that the length
+ // required is the length in bytes, not characters.
+ //
+ // Given the following string: `????+`, where `?` represents a
+ // multi-byte character (lets assume that every `?` is a 2-byte
+ // character) and `+` is a newline, the first value of `$i` is `0`
+ // and the last one is `4` (because there are 5 characters). Bytes
+ // `$str[0]` and `$str[1]` are the first character, `$str[2]` and
+ // `$str[3]` are the second one and `$str[4]` is going to be the
+ // first byte of the third character. The fourth and the last one
+ // (which is actually a new line) aren't going to be processed at
+ // all.
+ $len = ($str instanceof SqlParser\UtfString) ?
+ $str->length() : mb_strlen($len, '8bit');
+
+ $lines = array(0);
+ for ($i = 0; $i < $len; ++$i) {
+ if ($str[$i] === "\n") {
+ $lines[] = $i + 1;
+ }
+ }
+ return $lines;
+ }
+
+ /**
+ * Computes the number of the line and column given an absolute position.
+ *
+ * @param array $lines The starting position of each line.
+ * @param int $pos The absolute position
+ *
+ * @return array
+ */
+ public static function findLineNumberAndColumn($lines, $pos)
+ {
+ $line = 0;
+ foreach ($lines as $lineNo => $lineStart) {
+ if ($lineStart > $pos) {
+ break;
+ }
+ $line = $lineNo;
+ }
+ return array($line, $pos - $lines[$line]);
+ }
+
+ /**
+ * Runs the linting process.
+ *
+ * @param string $query The query to be checked.
+ *
+ * @return array
+ */
+ public static function lint($query)
+ {
+ // Disabling lint for huge queries to save some resources.
+ if (/*overload*/mb_strlen($query) > 10000) {
+ return array(
+ array(
+ 'message' => __(
+ 'Linting is disabled for this query because it exceeds the '
+ . 'maximum length.'
+ ),
+ 'fromLine' => 0,
+ 'fromColumn' => 0,
+ 'toLine' => 0,
+ 'toColumn' => 0,
+ 'severity' => 'warning',
+ )
+ );
+ }
+
+ /**
+ * Lexer used for tokenizing the query.
+ *
+ * @var SqlParser\Lexer
+ */
+ $lexer = new SqlParser\Lexer($query);
+
+ /**
+ * Parsed used for analysing the query.
+ *
+ * @var SqlParser\Parser
+ */
+ $parser = new SqlParser\Parser($lexer->list);
+
+ /**
+ * Array containing all errors.
+ *
+ * @var array
+ */
+ $errors = SqlParser\Utils\Error::get(array($lexer, $parser));
+
+ /**
+ * The response containing of all errors.
+ *
+ * @var array
+ */
+ $response = array();
+
+ /**
+ * The starting position for each line.
+ *
+ * CodeMirror requires relative position to line, but the parser stores
+ * only the absolute position of the character in string.
+ *
+ * @var array
+ */
+ $lines = static::getLines($query);
+
+ // Building the response.
+ foreach ($errors as $idx => $error) {
+
+ // Starting position of the string that caused the error.
+ list($fromLine, $fromColumn) = static::findLineNumberAndColumn(
+ $lines, $error[3]
+ );
+
+ // Ending position of the string that caused the error.
+ list($toLine, $toColumn) = static::findLineNumberAndColumn(
+ $lines, $error[3] + /*overload*/mb_strlen($error[2])
+ );
+
+ // Building the response.
+ $response[] = array(
+ 'message' => sprintf(
+ __('%1$s (near <code>%2$s</code>)'),
+ $error[0], $error[2]
+ ),
+ 'fromLine' => $fromLine,
+ 'fromColumn' => $fromColumn,
+ 'toLine' => $toLine,
+ 'toColumn' => $toColumn,
+ 'severity' => 'error',
+ );
+ }
+
+ // Sending back the answer.
+ return $response;
+ }
+
+}
diff --git a/libraries/List.class.php b/libraries/List.class.php
index d18e22fe0c..508b79f86e 100644
--- a/libraries/List.class.php
+++ b/libraries/List.class.php
@@ -119,4 +119,3 @@ abstract class PMA_List extends ArrayObject
*/
abstract public function build();
}
-?>
diff --git a/libraries/List_Database.class.php b/libraries/List_Database.class.php
index 3c9087c539..57da2c3854 100644
--- a/libraries/List_Database.class.php
+++ b/libraries/List_Database.class.php
@@ -190,4 +190,3 @@ class PMA_List_Database extends PMA_List
return $this->getEmpty();
}
}
-?>
diff --git a/libraries/Menu.class.php b/libraries/Menu.class.php
index 6a0f978713..08f7f93d0a 100644
--- a/libraries/Menu.class.php
+++ b/libraries/Menu.class.php
@@ -129,7 +129,7 @@ class PMA_Menu
{
$allowedTabs = PMA_Util::getMenuTabList($level);
$cfgRelation = PMA_getRelationsParam();
- if (isset($cfgRelation['menuswork']) && $cfgRelation['menuswork']) {
+ if ($cfgRelation['menuswork']) {
$groupTable = PMA_Util::backquote($cfgRelation['db'])
. "."
. PMA_Util::backquote($cfgRelation['usergroups']);
@@ -165,7 +165,8 @@ class PMA_Menu
private function _getBreadcrumbs()
{
$retval = '';
- $tbl_is_view = PMA_Table::isView($this->_db, $this->_table);
+ $tbl_is_view = $GLOBALS['dbi']->getTable($this->_db, $this->_table)
+ ->isView();
$server_info = ! empty($GLOBALS['cfg']['Server']['verbose'])
? $GLOBALS['cfg']['Server']['verbose']
: $GLOBALS['cfg']['Server']['host'];
@@ -191,7 +192,9 @@ class PMA_Menu
}
$retval .= sprintf(
$item,
- $GLOBALS['cfg']['DefaultTabServer'],
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabServer'], 'server'
+ ),
PMA_URL_getCommon(),
htmlspecialchars($server_info),
__('Server')
@@ -208,7 +211,9 @@ class PMA_Menu
}
$retval .= sprintf(
$item,
- $GLOBALS['cfg']['DefaultTabDatabase'],
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ ),
PMA_URL_getCommon(array('db' => $this->_db)),
htmlspecialchars($this->_db),
__('Database')
@@ -231,7 +236,9 @@ class PMA_Menu
}
$retval .= sprintf(
$item,
- $GLOBALS['cfg']['DefaultTabTable'],
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ ),
PMA_URL_getCommon(
array(
'db' => $this->_db, 'table' => $this->_table
@@ -264,7 +271,7 @@ class PMA_Menu
$cfgRelation = PMA_getRelationsParam();
// Get additional information about tables for tooltip is done
- // in libraries/db_info.inc.php only once
+ // in PMA_Util::getDbInfo() only once
if ($cfgRelation['commwork']) {
$comment = PMA_getDbComment($this->_db);
/**
@@ -292,7 +299,8 @@ class PMA_Menu
private function _getTableTabs()
{
$db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($this->_db);
- $tbl_is_view = PMA_Table::isView($this->_db, $this->_table);
+ $tbl_is_view = $GLOBALS['dbi']->getTable($this->_db, $this->_table)
+ ->isView();
$is_superuser = $GLOBALS['dbi']->isSuperuser();
$isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant')
|| $GLOBALS['dbi']->isUserType('create');
@@ -494,8 +502,7 @@ class PMA_Menu
}
if (! $db_is_system_schema
- && isset($cfgRelation['central_columnswork'])
- && $cfgRelation['central_columnswork']
+ && $cfgRelation['centralcolumnswork']
) {
$tabs['central_columns']['text'] = __('Central columns');
$tabs['central_columns']['icon'] = 'centralColumns.png';
@@ -558,7 +565,7 @@ class PMA_Menu
if (($is_superuser || $isCreateOrGrantUser) && ! PMA_DRIZZLE) {
$tabs['rights']['icon'] = 's_rights.png';
$tabs['rights']['link'] = 'server_privileges.php';
- $tabs['rights']['text'] = __('Users');
+ $tabs['rights']['text'] = __('User accounts');
$tabs['rights']['active'] = in_array(
basename($GLOBALS['PMA_PHP_SELF']),
array('server_privileges.php', 'server_user_groups.php')
@@ -606,6 +613,13 @@ class PMA_Menu
$tabs['plugins']['icon'] = 'b_engine.png';
$tabs['plugins']['link'] = 'server_plugins.php';
$tabs['plugins']['text'] = __('Plugins');
+ $tabs['plugins']['active'] = in_array(
+ basename($GLOBALS['PMA_PHP_SELF']),
+ array(
+ 'server_plugins.php',
+ 'server_modules.php',
+ )
+ );
} else {
$tabs['engine']['icon'] = 'b_engine.png';
$tabs['engine']['link'] = 'server_engines.php';
@@ -628,4 +642,3 @@ class PMA_Menu
}
}
-?>
diff --git a/libraries/Message.class.php b/libraries/Message.class.php
index 29cf41e6fc..ad9ec07c3c 100644
--- a/libraries/Message.class.php
+++ b/libraries/Message.class.php
@@ -756,4 +756,3 @@ class PMA_Message
}
}
-?>
diff --git a/libraries/OutputBuffering.class.php b/libraries/OutputBuffering.class.php
index aff498f58e..1d1d38f024 100644
--- a/libraries/OutputBuffering.class.php
+++ b/libraries/OutputBuffering.class.php
@@ -136,4 +136,3 @@ class PMA_OutputBuffering
}
}
-?>
diff --git a/libraries/PDF.class.php b/libraries/PDF.class.php
index fcf8e9423f..b6f00e6633 100644
--- a/libraries/PDF.class.php
+++ b/libraries/PDF.class.php
@@ -59,7 +59,7 @@ class PMA_PDF extends TCPDF
*
* @return void
*/
- function Footer()
+ public function Footer()
{
// Check if footer for this page already exists
if (!isset($this->footerset[$this->page])) {
@@ -87,7 +87,7 @@ class PMA_PDF extends TCPDF
*
* @return void
*/
- function SetAlias($name, $value)
+ public function SetAlias($name, $value)
{
$name = TCPDF_FONTS::UTF8ToUTF16BE(
$name, false, true, $this->CurrentFont
@@ -102,7 +102,7 @@ class PMA_PDF extends TCPDF
*
* @return void
*/
- function _putpages()
+ public function _putpages()
{
if (count($this->Alias) > 0) {
$nbPages = count($this->pages);
@@ -120,7 +120,7 @@ class PMA_PDF extends TCPDF
*
* @return void
*/
- function Error($error_message = '')
+ public function Error($error_message = '')
{
PMA_Message::error(
__('Error while creating PDF:') . ' ' . $error_message
@@ -135,7 +135,7 @@ class PMA_PDF extends TCPDF
*
* @return void
*/
- function Download($filename)
+ public function Download($filename)
{
$pdfData = $this->getPDFData();
PMA_Response::getInstance()->disable();
diff --git a/libraries/PMA.php b/libraries/PMA.php
index c0a7e1fd80..fb577caef9 100644
--- a/libraries/PMA.php
+++ b/libraries/PMA.php
@@ -106,4 +106,3 @@ class PMA
return $this->databases;
}
}
-?>
diff --git a/libraries/Partition.class.php b/libraries/Partition.class.php
index 92e597148e..12220232b4 100644
--- a/libraries/Partition.class.php
+++ b/libraries/Partition.class.php
@@ -10,13 +10,351 @@ if (! defined('PHPMYADMIN')) {
}
/**
+ * Represents a sub partition of a table
+ *
+ * @package PhpMyAdmin
+ */
+class PMA_SubPartition
+{
+ /**
+ * @var string the database
+ */
+ protected $db;
+ /**
+ * @var string the table
+ */
+ protected $table;
+ /**
+ * @var string partition name
+ */
+ protected $name;
+ /**
+ * @var integer ordinal
+ */
+ protected $ordinal;
+ /**
+ * @var string partition method
+ */
+ protected $method;
+ /**
+ * @var string partition expression
+ */
+ protected $expression;
+ /**
+ * @var integer no of table rows in the partition
+ */
+ protected $rows;
+ /**
+ * @var integer data length
+ */
+ protected $dataLength;
+ /**
+ * @var integer index length
+ */
+ protected $indexLength;
+ /**
+ * @var string partition comment
+ */
+ protected $comment;
+
+ /**
+ * Constructs a partition
+ *
+ * @param array $row fetched row from information_schema.PARTITIONS
+ */
+ public function __construct($row)
+ {
+ $this->db = $row['TABLE_SCHEMA'];
+ $this->table = $row['TABLE_NAME'];
+ $this->loadData($row);
+ }
+
+ /**
+ * Loads data from the fetched row from information_schema.PARTITIONS
+ *
+ * @param array $row fetched row
+ *
+ * @return void
+ */
+ protected function loadData($row)
+ {
+ $this->name = $row['SUBPARTITION_NAME'];
+ $this->ordinal = $row['SUBPARTITION_ORDINAL_POSITION'];
+ $this->method = $row['SUBPARTITION_METHOD'];
+ $this->expression = $row['SUBPARTITION_EXPRESSION'];
+ $this->loadCommonData($row);
+ }
+
+ /**
+ * Loads some data that is common to both partitions and sub partitions
+ *
+ * @param array $row fetched row
+ *
+ * @return void
+ */
+ protected function loadCommonData($row)
+ {
+ $this->rows = $row['TABLE_ROWS'];
+ $this->dataLength = $row['DATA_LENGTH'];
+ $this->indexLength = $row['INDEX_LENGTH'];
+ $this->comment = $row['PARTITION_COMMENT'];
+ }
+
+ /**
+ * Return the partition name
+ *
+ * @return string partition name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Return the ordinal of the partition
+ *
+ * @return number the ordinal
+ */
+ public function getOrdinal()
+ {
+ return $this->ordinal;
+ }
+
+ /**
+ * Returns the partition method
+ *
+ * @return string partition method
+ */
+ public function getMethod()
+ {
+ return $this->method;
+ }
+
+ /**
+ * Returns the partition expression
+ *
+ * @return string partition expression
+ */
+ public function getExpression()
+ {
+ return $this->expression;
+ }
+
+ /**
+ * Returns the number of data rows
+ *
+ * @return integer number of rows
+ */
+ public function getRows()
+ {
+ return $this->rows;
+ }
+
+ /**
+ * Returns the data length
+ *
+ * @return integer data length
+ */
+ public function getDataLength()
+ {
+ return $this->dataLength;
+ }
+
+ /**
+ * Returns the index length
+ *
+ * @return integer index length
+ */
+ public function getIndexLength()
+ {
+ return $this->indexLength;
+ }
+
+ /**
+ * Returns the partition comment
+ *
+ * @return string partition comment
+ */
+ public function getComment()
+ {
+ return $this->comment;
+ }
+}
+
+/**
* base Partition Class
*
* @package PhpMyAdmin
*/
-class PMA_Partition
+class PMA_Partition extends PMA_SubPartition
{
/**
+ * @var string partition description
+ */
+ protected $description;
+ /**
+ * @var PMA_SubPartition[] sub partitions
+ */
+ protected $subPartitions = array();
+
+ /**
+ * Loads data from the fetched row from information_schema.PARTITIONS
+ *
+ * @param array $row fetched row
+ *
+ * @return void
+ */
+ protected function loadData($row)
+ {
+ $this->name = $row['PARTITION_NAME'];
+ $this->ordinal = $row['PARTITION_ORDINAL_POSITION'];
+ $this->method = $row['PARTITION_METHOD'];
+ $this->expression = $row['PARTITION_EXPRESSION'];
+ $this->description = $row['PARTITION_DESCRIPTION'];
+ // no sub partitions, load all data to this object
+ if (empty($row['SUBPARTITION_NAME'])) {
+ $this->loadCommonData($row);
+ }
+ }
+
+ /**
+ * Returns the partiotion description
+ *
+ * @return string partition description
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Add a sub partition
+ *
+ * @param PMA_SubPartition $partition Sub partition
+ *
+ * @return void
+ */
+ public function addSubPartition(PMA_SubPartition $partition)
+ {
+ $this->subPartitions[] = $partition;
+ }
+
+ /**
+ * Whether there are sub partitions
+ *
+ * @return boolean
+ */
+ public function hasSubPartitions()
+ {
+ return ! empty($this->subPartitions);
+ }
+
+ /**
+ * Returns the number of data rows
+ *
+ * @return integer number of rows
+ */
+ public function getRows()
+ {
+ if (empty($this->subPartitions)) {
+ return $this->rows;
+ } else {
+ $rows = 0;
+ foreach ($this->subPartitions as $subPartition) {
+ $rows += $subPartition->rows;
+ }
+ return $rows;
+ }
+ }
+
+ /**
+ * Returns the total data length
+ *
+ * @return integer data length
+ */
+ public function getDataLength()
+ {
+ if (empty($this->subPartitions)) {
+ return $this->dataLength;
+ } else {
+ $dataLength = 0;
+ foreach ($this->subPartitions as $subPartition) {
+ $dataLength += $subPartition->dataLength;
+ }
+ return $dataLength;
+ }
+ }
+
+ /**
+ * Returns the tatal index length
+ *
+ * @return integer index length
+ */
+ public function getIndexLength()
+ {
+ if (empty($this->subPartitions)) {
+ return $this->indexLength;
+ } else {
+ $indexLength = 0;
+ foreach ($this->subPartitions as $subPartition) {
+ $indexLength += $subPartition->indexLength;
+ }
+ return $indexLength;
+ }
+ }
+
+ /**
+ * Returns the list of sub partitions
+ *
+ * @return PMA_SubPartition[]
+ */
+ public function getSubPartitions()
+ {
+ return $this->subPartitions;
+ }
+
+ /**
+ * Returns array of partitions for a specific db/table
+ *
+ * @param string $db database name
+ * @param string $table table name
+ *
+ * @access public
+ * @return PMA_Partition[]
+ */
+ static public function getPartitions($db, $table)
+ {
+ if (PMA_Partition::havePartitioning()) {
+ $result = $GLOBALS['dbi']->fetchResult(
+ "SELECT * FROM `information_schema`.`PARTITIONS`"
+ . " WHERE `TABLE_SCHEMA` = '" . PMA_Util::sqlAddSlashes($db)
+ . "' AND `TABLE_NAME` = '" . PMA_Util::sqlAddSlashes($table) . "'"
+ );
+ if ($result) {
+ $partitionMap = array();
+ foreach ($result as $row) {
+ if (isset($partitionMap[$row['PARTITION_NAME']])) {
+ $partition = $partitionMap[$row['PARTITION_NAME']];
+ } else {
+ $partition = new PMA_Partition($row);
+ $partitionMap[$row['PARTITION_NAME']] = $partition;
+ }
+
+ if (! empty($row['SUBPARTITION_NAME'])) {
+ $parentPartition = $partition;
+ $partition = new PMA_SubPartition($row);
+ $parentPartition->addSubPartition($partition);
+ }
+ }
+ return array_values($partitionMap);
+ }
+ return array();
+ } else {
+ return array();
+ }
+ }
+
+ /**
* returns array of partition names for a specific db/table
*
* @param string $db database name
@@ -39,6 +377,29 @@ class PMA_Partition
}
/**
+ * returns the partition method used by the table.
+ *
+ * @param string $db database name
+ * @param string $table table name
+ *
+ * @return string partition method
+ */
+ static public function getPartitionMethod($db, $table)
+ {
+ if (PMA_Partition::havePartitioning()) {
+ $partition_method = $GLOBALS['dbi']->fetchResult(
+ "SELECT `PARTITION_METHOD` FROM `information_schema`.`PARTITIONS`"
+ . " WHERE `TABLE_SCHEMA` = '" . PMA_Util::sqlAddSlashes($db) . "'"
+ . " AND `TABLE_NAME` = '" . PMA_Util::sqlAddSlashes($table) . "'"
+ );
+ if (! empty($partition_method)) {
+ return $partition_method[0];
+ }
+ }
+ return null;
+ }
+
+ /**
* checks if MySQL server supports partitioning
*
* @static
@@ -55,7 +416,7 @@ class PMA_Partition
if (! $already_checked) {
if (PMA_MYSQL_INT_VERSION < 50600) {
if ($GLOBALS['dbi']->fetchValue(
- "SHOW VARIABLES LIKE 'have_partitioning';"
+ "SELECT @@have_partitioning;"
)) {
$have_partitioning = true;
}
@@ -74,4 +435,3 @@ class PMA_Partition
return $have_partitioning;
}
}
-?>
diff --git a/libraries/RecentFavoriteTable.class.php b/libraries/RecentFavoriteTable.class.php
index 59f4c98c90..58778126d7 100644
--- a/libraries/RecentFavoriteTable.class.php
+++ b/libraries/RecentFavoriteTable.class.php
@@ -390,4 +390,3 @@ class PMA_RecentFavoriteTable
return null;
}
}
-?>
diff --git a/libraries/Response.class.php b/libraries/Response.class.php
index 5c4f9a6c7e..49d9087d53 100644
--- a/libraries/Response.class.php
+++ b/libraries/Response.class.php
@@ -312,7 +312,12 @@ class PMA_Response
$hashes = explode('-', $_REQUEST['menuHashes']);
}
if (! in_array($menuHash, $hashes)) {
- $this->addJSON('_menu', $this->getHeader()->getMenu()->getDisplay());
+ $this->addJSON(
+ '_menu',
+ $this->getHeader()
+ ->getMenu()
+ ->getDisplay()
+ );
}
}
@@ -321,7 +326,9 @@ class PMA_Response
$this->addJSON('_displayMessage', $this->getHeader()->getMessage());
$debug = $this->_footer->getDebugMessage();
- if (/*overload*/mb_strlen($debug)) {
+ if (empty($_REQUEST['no_debug'])
+ && /*overload*/mb_strlen($debug)
+ ) {
$this->addJSON('_debug', $debug);
}
@@ -394,4 +401,3 @@ class PMA_Response
}
}
-?>
diff --git a/libraries/Scripts.class.php b/libraries/Scripts.class.php
index 54c688a5f8..c1053fcac5 100644
--- a/libraries/Scripts.class.php
+++ b/libraries/Scripts.class.php
@@ -53,15 +53,19 @@ class PMA_Scripts
$first_dynamic_scripts = "";
$dynamic_scripts = "";
$scripts = array();
+ $separator = PMA_URL_getArgSeparator();
foreach ($files as $value) {
if (/*overload*/mb_strpos($value['filename'], "?") !== false) {
+ $file_name = $value['filename'] . $separator
+ . PMA_Header::getVersionParameter();
if ($value['before_statics'] === true) {
$first_dynamic_scripts
- .= "<script data-cfasync='false' type='text/javascript' src='js/"
- . $value['filename'] . "'></script>";
+ .= "<script data-cfasync='false' type='text/javascript' "
+ . "src='js/" . $file_name . "'></script>";
} else {
- $dynamic_scripts .= "<script data-cfasync='false' type='text/javascript' src='js/"
- . $value['filename'] . "'></script>";
+ $dynamic_scripts .= "<script data-cfasync='false' "
+ . "type='text/javascript' src='js/" . $file_name
+ . "'></script>";
}
continue;
}
@@ -86,7 +90,9 @@ class PMA_Scripts
// Using chunks of 20 files to avoid too long URLs
$script_chunks = array_chunk($scripts, 20);
foreach ($script_chunks as $script_chunk) {
- $url = 'js/get_scripts.js.php?' . implode($separator, $script_chunk);
+ $url = 'js/get_scripts.js.php?'
+ . implode($separator, $script_chunk)
+ . $separator . PMA_Header::getVersionParameter();
$static_scripts .= sprintf(
'<script data-cfasync="false" type="text/javascript" src="%s"></script>',
@@ -99,7 +105,6 @@ class PMA_Scripts
/**
* Generates new PMA_Scripts objects
*
- * @return PMA_Scripts object
*/
public function __construct()
{
@@ -165,7 +170,7 @@ class PMA_Scripts
*/
private function _eventBlacklist($filename)
{
- if ( strpos($filename, 'jquery') !== false
+ if (strpos($filename, 'jquery') !== false
|| strpos($filename, 'codemirror') !== false
|| strpos($filename, 'messages.php') !== false
|| strpos($filename, 'ajax.js') !== false
diff --git a/libraries/ServerStatusData.class.php b/libraries/ServerStatusData.class.php
index d0def03985..9cf958a08b 100644
--- a/libraries/ServerStatusData.class.php
+++ b/libraries/ServerStatusData.class.php
@@ -32,8 +32,9 @@ class PMA_ServerStatusData
public $links;
public $db_isLocal;
public $section;
- public $categoryUsed;
+ public $sectionUsed;
public $selfUrl;
+ public $dataLoaded;
/**
* An empty setter makes the above properties read-only
@@ -49,94 +50,13 @@ class PMA_ServerStatusData
}
/**
- * Constructor
+ * Gets the allocations for constructor
+ *
+ * @return array
*/
- public function __construct()
+ private function _getAllocations()
{
- $this->selfUrl = basename($GLOBALS['PMA_PHP_SELF']);
- /**
- * get status from server
- */
- $server_status = $GLOBALS['dbi']->fetchResult('SHOW GLOBAL STATUS', 0, 1);
- if (PMA_DRIZZLE) {
- // Drizzle doesn't put query statistics into variables, add it
- $sql = "SELECT concat('Com_', variable_name), variable_value "
- . "FROM data_dictionary.GLOBAL_STATEMENTS";
- $statements = $GLOBALS['dbi']->fetchResult($sql, 0, 1);
- $server_status = array_merge($server_status, $statements);
- }
-
- /**
- * for some calculations we require also some server settings
- */
- $server_variables = $GLOBALS['dbi']->fetchResult(
- 'SHOW GLOBAL VARIABLES', 0, 1
- );
-
- /**
- * cleanup of some deprecated values
- */
- $server_status = self::cleanDeprecated($server_status);
-
- /**
- * calculate some values
- */
- // Key_buffer_fraction
- if (isset($server_status['Key_blocks_unused'])
- && isset($server_variables['key_cache_block_size'])
- && isset($server_variables['key_buffer_size'])
- ) {
- $server_status['Key_buffer_fraction_%']
- = 100
- - $server_status['Key_blocks_unused']
- * $server_variables['key_cache_block_size']
- / $server_variables['key_buffer_size']
- * 100;
- } elseif (isset($server_status['Key_blocks_used'])
- && isset($server_variables['key_buffer_size'])
- ) {
- $server_status['Key_buffer_fraction_%']
- = $server_status['Key_blocks_used']
- * 1024
- / $server_variables['key_buffer_size'];
- }
-
- // Ratio for key read/write
- if (isset($server_status['Key_writes'])
- && isset($server_status['Key_write_requests'])
- && $server_status['Key_write_requests'] > 0
- ) {
- $key_writes = $server_status['Key_writes'];
- $key_write_requests = $server_status['Key_write_requests'];
- $server_status['Key_write_ratio_%']
- = 100 * $key_writes / $key_write_requests;
- }
-
- if (isset($server_status['Key_reads'])
- && isset($server_status['Key_read_requests'])
- && $server_status['Key_read_requests'] > 0
- ) {
- $key_reads = $server_status['Key_reads'];
- $key_read_requests = $server_status['Key_read_requests'];
- $server_status['Key_read_ratio_%']
- = 100 * $key_reads / $key_read_requests;
- }
-
- // Threads_cache_hitrate
- if (isset($server_status['Threads_created'])
- && isset($server_status['Connections'])
- && $server_status['Connections'] > 0
- ) {
-
- $server_status['Threads_cache_hitrate_%']
- = 100 - $server_status['Threads_created']
- / $server_status['Connections'] * 100;
- }
-
- /**
- * split variables in sections
- */
- $allocations = array(
+ return array(
// variable name => section
// variable names match when they begin with the given string
@@ -181,8 +101,16 @@ class PMA_ServerStatusData
'Open_streams' => 'files',
'Opened_files' => 'files',
);
+ }
- $sections = array(
+ /**
+ * Gets the sections for constructor
+ *
+ * @return array
+ */
+ private function _getSections()
+ {
+ return array(
// section => section name (description)
'com' => 'Com',
'query' => __('SQL query'),
@@ -204,12 +132,17 @@ class PMA_ServerStatusData
'ssl' => 'SSL',
'other' => __('Other')
);
+ }
- /**
- * define some needful links/commands
- */
- // variable or section name => (name => url)
+ /**
+ * Gets the links for constructor
+ *
+ * @return array
+ */
+ private function _getLinks()
+ {
$links = array();
+ // variable or section name => (name => url)
$links['table'][__('Flush (close) all tables')] = $this->selfUrl
. PMA_URL_getCommon(
@@ -271,23 +204,94 @@ class PMA_ServerStatusData
);
$links['innodb']['doc'] = 'innodb';
- // Variable to contain all com_ variables (query statistics)
- $used_queries = array();
+ return($links);
+ }
- // Variable to map variable names to their respective section name
- // (used for js category filtering)
- $allocationMap = array();
+ /**
+ * Calculate some values
+ *
+ * @param array $server_status contains results of SHOW GLOBAL STATUS
+ * @param array $server_variables contains results of SHOW GLOBAL VARIABLES
+ *
+ * @return array $server_status
+ */
+ private function _calculateValues($server_status, $server_variables)
+ {
+ // Key_buffer_fraction
+ if (isset($server_status['Key_blocks_unused'])
+ && isset($server_variables['key_cache_block_size'])
+ && isset($server_variables['key_buffer_size'])
+ ) {
+ $server_status['Key_buffer_fraction_%']
+ = 100
+ - $server_status['Key_blocks_unused']
+ * $server_variables['key_cache_block_size']
+ / $server_variables['key_buffer_size']
+ * 100;
+ } elseif (isset($server_status['Key_blocks_used'])
+ && isset($server_variables['key_buffer_size'])
+ ) {
+ $server_status['Key_buffer_fraction_%']
+ = $server_status['Key_blocks_used']
+ * 1024
+ / $server_variables['key_buffer_size'];
+ }
- // Variable to mark used sections
- $categoryUsed = array();
+ // Ratio for key read/write
+ if (isset($server_status['Key_writes'])
+ && isset($server_status['Key_write_requests'])
+ && $server_status['Key_write_requests'] > 0
+ ) {
+ $key_writes = $server_status['Key_writes'];
+ $key_write_requests = $server_status['Key_write_requests'];
+ $server_status['Key_write_ratio_%']
+ = 100 * $key_writes / $key_write_requests;
+ }
- // sort vars into arrays
+ if (isset($server_status['Key_reads'])
+ && isset($server_status['Key_read_requests'])
+ && $server_status['Key_read_requests'] > 0
+ ) {
+ $key_reads = $server_status['Key_reads'];
+ $key_read_requests = $server_status['Key_read_requests'];
+ $server_status['Key_read_ratio_%']
+ = 100 * $key_reads / $key_read_requests;
+ }
+
+ // Threads_cache_hitrate
+ if (isset($server_status['Threads_created'])
+ && isset($server_status['Connections'])
+ && $server_status['Connections'] > 0
+ ) {
+
+ $server_status['Threads_cache_hitrate_%']
+ = 100 - $server_status['Threads_created']
+ / $server_status['Connections'] * 100;
+ }
+ return $server_status;
+ }
+
+ /**
+ * Sort variables into arrays
+ *
+ * @param array $server_status contains results of SHOW GLOBAL STATUS
+ * @param array $allocations allocations for sections
+ * @param array $allocationMap map variables to their section
+ * @param array $sectionUsed is a section used?
+ * @param array $used_queries used queries
+ *
+ * @return array ($allocationMap, $sectionUsed, $used_queries)
+ */
+ private function _sortVariables(
+ $server_status, $allocations, $allocationMap, $sectionUsed,
+ $used_queries
+ ) {
foreach ($server_status as $name => $value) {
$section_found = false;
foreach ($allocations as $filter => $section) {
if (/*overload*/mb_strpos($name, $filter) !== false) {
$allocationMap[$name] = $section;
- $categoryUsed[$section] = true;
+ $sectionUsed[$section] = true;
$section_found = true;
if ($section == 'com' && $value > 0) {
$used_queries[$name] = $value;
@@ -295,11 +299,80 @@ class PMA_ServerStatusData
break; // Only exits inner loop
}
}
- if (!$section_found) {
+ if (! $section_found) {
$allocationMap[$name] = 'other';
- $categoryUsed['other'] = true;
+ $sectionUsed['other'] = true;
}
}
+ return array($allocationMap, $sectionUsed, $used_queries);
+ }
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->selfUrl = basename($GLOBALS['PMA_PHP_SELF']);
+
+ // get status from server
+ $server_status_result = $GLOBALS['dbi']->tryQuery('SHOW GLOBAL STATUS');
+ $server_status = array();
+ if ($server_status_result === false) {
+ $this->dataLoaded = false;
+ } else {
+ $this->dataLoaded = true;
+ while ($arr = $GLOBALS['dbi']->fetchRow($server_status_result)) {
+ $server_status[$arr[0]] = $arr[1];
+ }
+ $GLOBALS['dbi']->freeResult($server_status_result);
+ }
+
+ if (PMA_DRIZZLE) {
+ // Drizzle doesn't put query statistics into variables, add it
+ $sql = "SELECT concat('Com_', variable_name), variable_value "
+ . "FROM data_dictionary.GLOBAL_STATEMENTS";
+ $statements = $GLOBALS['dbi']->fetchResult($sql, 0, 1);
+ $server_status = array_merge($server_status, $statements);
+ }
+
+ // for some calculations we require also some server settings
+ $server_variables = $GLOBALS['dbi']->fetchResult(
+ 'SHOW GLOBAL VARIABLES', 0, 1
+ );
+
+ // cleanup of some deprecated values
+ $server_status = self::cleanDeprecated($server_status);
+
+ // calculate some values
+ $server_status = $this->_calculateValues(
+ $server_status, $server_variables
+ );
+
+ // split variables in sections
+ $allocations = $this->_getAllocations();
+
+ $sections = $this->_getSections();
+
+ // define some needful links/commands
+ $links = $this->_getLinks();
+
+ // Variable to contain all com_ variables (query statistics)
+ $used_queries = array();
+
+ // Variable to map variable names to their respective section name
+ // (used for js category filtering)
+ $allocationMap = array();
+
+ // Variable to mark used sections
+ $sectionUsed = array();
+
+ // sort vars into arrays
+ list(
+ $allocationMap, $sectionUsed, $used_queries
+ ) = $this->_sortVariables(
+ $server_status, $allocations, $allocationMap, $sectionUsed,
+ $used_queries
+ );
if (PMA_DRIZZLE) {
$used_queries = $GLOBALS['dbi']->fetchResult(
@@ -331,7 +404,7 @@ class PMA_ServerStatusData
$this->used_queries = $used_queries;
$this->allocationMap = $allocationMap;
$this->links = $links;
- $this->categoryUsed = $categoryUsed;
+ $this->sectionUsed = $sectionUsed;
}
/**
@@ -445,4 +518,3 @@ class PMA_ServerStatusData
}
}
-?>
diff --git a/libraries/StorageEngine.class.php b/libraries/StorageEngine.class.php
index 4895d6d085..5366e727de 100644
--- a/libraries/StorageEngine.class.php
+++ b/libraries/StorageEngine.class.php
@@ -268,10 +268,13 @@ class PMA_StorageEngine
if (! $ret) {
$ret = '<p>' . "\n"
- . ' '
- . __('There is no detailed status information available for this storage engine.')
- . "\n"
- . '</p>' . "\n";
+ . ' '
+ . __(
+ 'There is no detailed status information available for this '
+ . 'storage engine.'
+ )
+ . "\n"
+ . '</p>' . "\n";
} else {
$ret = '<table class="data">' . "\n" . $ret . '</table>' . "\n";
}
@@ -380,7 +383,9 @@ class PMA_StorageEngine
break;
case PMA_ENGINE_SUPPORT_NO:
default:
- $message = __('This MySQL server does not support the %s storage engine.');
+ $message = __(
+ 'This MySQL server does not support the %s storage engine.'
+ );
}
return sprintf($message, htmlspecialchars($this->title));
}
@@ -448,4 +453,3 @@ class PMA_StorageEngine
}
}
-?>
diff --git a/libraries/String.class.php b/libraries/String.class.php
index 970170a57e..3d1ed821fe 100644
--- a/libraries/String.class.php
+++ b/libraries/String.class.php
@@ -185,4 +185,3 @@ class PMA_String implements PMA_StringType
return $this->_type->numberInRangeInclusive($num, $lower, $upper);
}
}
-?>
diff --git a/libraries/StringAbstractType.class.php b/libraries/StringAbstractType.class.php
index 6424844a2c..025f171712 100644
--- a/libraries/StringAbstractType.class.php
+++ b/libraries/StringAbstractType.class.php
@@ -32,4 +32,3 @@ abstract class PMA_StringAbstractType implements PMA_StringType
return ($num >= $lower && $num <= $upper);
}
}
-?> \ No newline at end of file
diff --git a/libraries/StringByte.int.php b/libraries/StringByte.int.php
index e26013db17..7da1fd88f2 100644
--- a/libraries/StringByte.int.php
+++ b/libraries/StringByte.int.php
@@ -4,6 +4,12 @@
*
* @package PhpMyAdmin-String
*/
+
+/**
+ * Defines a set of specialized string functions.
+ *
+ * @package PhpMyAdmin-String
+ */
interface PMA_StringByte
{
/**
@@ -13,7 +19,6 @@ interface PMA_StringByte
*
* @return int|false string length
*/
-
public function strlen($string);
/**
@@ -170,4 +175,3 @@ interface PMA_StringByte
*/
public function chr($ascii);
}
-?>
diff --git a/libraries/StringCType.class.php b/libraries/StringCType.class.php
index 5972f12487..d7256fa7b8 100644
--- a/libraries/StringCType.class.php
+++ b/libraries/StringCType.class.php
@@ -107,4 +107,3 @@ class PMA_StringCType extends PMA_StringAbstractType
return ctype_xdigit($c);
} // end of the "isHexDigit()" function
}
-?>
diff --git a/libraries/StringNativeType.class.php b/libraries/StringNativeType.class.php
index f379cc26c7..e80e7efc28 100644
--- a/libraries/StringNativeType.class.php
+++ b/libraries/StringNativeType.class.php
@@ -135,4 +135,3 @@ class PMA_StringNativeType extends PMA_StringAbstractType
|| $this->numberInRangeInclusive($ord_c, $ord_Alower, $ord_Flower));
} // end of the "isHexDigit()" function
}
-?>
diff --git a/libraries/StringType.int.php b/libraries/StringType.int.php
index 38c17342da..7e09bde479 100644
--- a/libraries/StringType.int.php
+++ b/libraries/StringType.int.php
@@ -4,6 +4,12 @@
*
* @package PhpMyAdmin-String
*/
+
+/**
+ * Defines a set of specialized string functions.
+ *
+ * @package PhpMyAdmin-String
+ */
interface PMA_StringType
{
/**
@@ -81,4 +87,3 @@ interface PMA_StringType
*/
public function numberInRangeInclusive($num, $lower, $upper);
}
-?> \ No newline at end of file
diff --git a/libraries/SystemDatabase.class.php b/libraries/SystemDatabase.class.php
new file mode 100644
index 0000000000..93c2f74a4f
--- /dev/null
+++ b/libraries/SystemDatabase.class.php
@@ -0,0 +1,130 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * hold PMA\SystemDatabase class
+ *
+ * @package PMA
+ */
+
+namespace PMA;
+
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+require_once 'libraries/database_interface.inc.php';
+
+/**
+ * Class SystemDatabase
+ *
+ * @package PMA
+ */
+class SystemDatabase
+{
+ /**
+ * @var \PMA_DatabaseInterface
+ */
+ protected $dbi;
+
+ /**
+ * Get instance of SystemDatabase
+ *
+ * @param \PMA_DatabaseInterface $dbi Database interface for the system database
+ *
+ */
+ function __construct(\PMA_DatabaseInterface $dbi)
+ {
+ $this->dbi = $dbi;
+ }
+
+ /**
+ * Get existing data on transformations applied for
+ * columns in a particular table
+ *
+ * @param string $db Database name looking for
+ *
+ * @return \mysqli_result Result of executed SQL query
+ */
+ public function getExistingTransformationData($db)
+ {
+ $cfgRelation = \PMA_getRelationsParam();
+
+ // Get the existing transformation details of the same database
+ // from pma__column_info table
+ $pma_transformation_sql = sprintf(
+ "SELECT * FROM %s.%s WHERE `db_name` = '%s'",
+ \PMA_Util::backquote($cfgRelation['db']),
+ \PMA_Util::backquote($cfgRelation['column_info']),
+ \PMA_Util::sqlAddSlashes($db)
+ );
+
+ return $this->dbi->tryQuery($pma_transformation_sql);
+ }
+
+ /**
+ * Get SQL query for store new transformation details of a VIEW
+ *
+ * @param object $pma_transformation_data Result set of SQL execution
+ * @param array $column_map Details of VIEW columns
+ * @param string $view_name Name of the VIEW
+ * @param string $db Database name of the VIEW
+ *
+ * @return string $new_transformations_sql SQL query for new transformations
+ */
+ function getNewTransformationDataSql(
+ $pma_transformation_data, $column_map, $view_name, $db
+ ) {
+ $cfgRelation = \PMA_getRelationsParam();
+
+ // Need to store new transformation details for VIEW
+ $new_transformations_sql = sprintf(
+ "INSERT INTO %s.%s ("
+ . "`db_name`, `table_name`, `column_name`, "
+ . "`comment`, `mimetype`, `transformation`, "
+ . "`transformation_options`) VALUES",
+ \PMA_Util::backquote($cfgRelation['db']),
+ \PMA_Util::backquote($cfgRelation['column_info'])
+ );
+
+ $column_count = 0;
+ $add_comma = false;
+
+ while ($data_row = $this->dbi->fetchAssoc($pma_transformation_data)) {
+
+ foreach ($column_map as $column) {
+
+ if ($data_row['table_name'] != $column['table_name']
+ || $data_row['column_name'] != $column['refering_column']
+ ) {
+ continue;
+ }
+
+ $new_transformations_sql .= sprintf(
+ "%s ('%s', '%s', '%s', '%s', '%s', '%s', '%s')",
+ $add_comma ? ', ' : '',
+ $db,
+ $view_name,
+ isset($column['real_column'])
+ ? $column['real_column']
+ : $column['refering_column'],
+ $data_row['comment'],
+ $data_row['mimetype'],
+ $data_row['transformation'],
+ \PMA_Util::sqlAddSlashes(
+ $data_row['transformation_options']
+ )
+ );
+
+ $add_comma = true;
+ $column_count++;
+ break;
+ }
+
+ if ($column_count == count($column_map)) {
+ break;
+ }
+ }
+
+ return ($column_count > 0) ? $new_transformations_sql : '';
+ }
+}
diff --git a/libraries/Table.class.php b/libraries/Table.class.php
index 6ed9afb344..af9a028339 100644
--- a/libraries/Table.class.php
+++ b/libraries/Table.class.php
@@ -24,18 +24,6 @@ class PMA_Table
const PROP_COLUMN_ORDER = 'col_order';
const PROP_COLUMN_VISIB = 'col_visib';
- static public $cache = array();
-
- /**
- * @var string table name
- */
- var $name = '';
-
- /**
- * @var string database name
- */
- var $db_name = '';
-
/**
* @var string engine (innodb, myisam, bdb, ...)
*/
@@ -47,11 +35,6 @@ class PMA_Table
var $type = '';
/**
- * @var array settings
- */
- var $settings = array();
-
- /**
* @var array UI preferences
*/
var $uiprefs;
@@ -67,15 +50,35 @@ class PMA_Table
var $messages = array();
/**
+ * @var string table name
+ */
+ protected $_name = '';
+
+ /**
+ * @var string database name
+ */
+ protected $_db_name = '';
+
+ /**
+ * @var PMA_DatabaseInterface
+ */
+ protected $_dbi;
+
+ /**
* Constructor
*
- * @param string $table_name table name
- * @param string $db_name database name
+ * @param string $table_name table name
+ * @param string $db_name database name
+ * @param PMA_DatabaseInterface $dbi database interface for the table
*/
- function __construct($table_name, $db_name)
+ function __construct($table_name, $db_name, PMA_DatabaseInterface $dbi = null)
{
- $this->setName($table_name);
- $this->setDbName($db_name);
+ if (empty($dbi)) {
+ $dbi = $GLOBALS['dbi'];
+ }
+ $this->_dbi = $dbi;
+ $this->_name = $table_name;
+ $this->_db_name = $db_name;
}
/**
@@ -110,18 +113,6 @@ class PMA_Table
}
/**
- * sets table name
- *
- * @param string $table_name new table name
- *
- * @return void
- */
- function setName($table_name)
- {
- $this->name = $table_name;
- }
-
- /**
* returns table name
*
* @param boolean $backquoted whether to quote name with backticks ``
@@ -131,21 +122,9 @@ class PMA_Table
function getName($backquoted = false)
{
if ($backquoted) {
- return PMA_Util::backquote($this->name);
+ return PMA_Util::backquote($this->_name);
}
- return $this->name;
- }
-
- /**
- * sets database name for this table
- *
- * @param string $db_name database name
- *
- * @return void
- */
- function setDbName($db_name)
- {
- $this->db_name = $db_name;
+ return $this->_name;
}
/**
@@ -158,9 +137,9 @@ class PMA_Table
function getDbName($backquoted = false)
{
if ($backquoted) {
- return PMA_Util::backquote($this->db_name);
+ return PMA_Util::backquote($this->_db_name);
}
- return $this->db_name;
+ return $this->_db_name;
}
/**
@@ -173,28 +152,27 @@ class PMA_Table
function getFullName($backquoted = false)
{
return $this->getDbName($backquoted) . '.'
- . $this->getName($backquoted);
+ . $this->getName($backquoted);
}
/**
* returns whether the table is actually a view
*
- * @param string $db database
- * @param string $table table
- *
* @return boolean whether the given is a view
*/
- static public function isView($db = null, $table = null)
+ public function isView()
{
+ $db = $this->_db_name;
+ $table = $this->_name;
if (empty($db) || empty($table)) {
return false;
}
// use cached data or load information with SHOW command
- if (isset(PMA_Table::$cache[$db][$table])
+ if ($this->_dbi->getCachedTableContent("${db}.${table}") != null
|| $GLOBALS['cfg']['Server']['DisableIS']
) {
- $type = PMA_Table::sGetStatusInfo($db, $table, 'TABLE_TYPE');
+ $type = $this->getStatusInfo('TABLE_TYPE');
return $type == 'VIEW' || $type == 'SYSTEM VIEW';
}
@@ -204,7 +182,7 @@ class PMA_Table
}
// query information_schema
- $result = $GLOBALS['dbi']->fetchResult(
+ $result = $this->_dbi->fetchResult(
"SELECT TABLE_NAME
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = '" . PMA_Util::sqlAddSlashes($db) . "'
@@ -216,22 +194,19 @@ class PMA_Table
/**
* Returns whether the table is actually an updatable view
*
- * @param string $db database
- * @param string $table table
- *
* @return boolean whether the given is an updatable view
*/
- static public function isUpdatableView($db = null, $table = null)
+ public function isUpdatableView()
{
- if (empty($db) || empty($table)) {
+ if (empty($this->_db_name) || empty($this->_name)) {
return false;
}
- $result = $GLOBALS['dbi']->fetchResult(
+ $result = $this->_dbi->fetchResult(
"SELECT TABLE_NAME
FROM information_schema.VIEWS
- WHERE TABLE_SCHEMA = '" . PMA_Util::sqlAddSlashes($db) . "'
- AND TABLE_NAME = '" . PMA_Util::sqlAddSlashes($table) . "'
+ WHERE TABLE_SCHEMA = '" . PMA_Util::sqlAddSlashes($this->_db_name) . "'
+ AND TABLE_NAME = '" . PMA_Util::sqlAddSlashes($this->_name) . "'
AND IS_UPDATABLE = 'YES'"
);
return $result ? true : false;
@@ -241,30 +216,27 @@ class PMA_Table
* Returns the analysis of 'SHOW CREATE TABLE' query for the table.
* In case of a view, the values are taken from the information_schema.
*
- * @param string $db database
- * @param string $table table
- *
* @return array analysis of 'SHOW CREATE TABLE' query for the table
*/
- static public function analyzeStructure($db = null, $table = null)
+ public function analyzeStructure()
{
- if (empty($db) || empty($table)) {
+ if (empty($this->_db_name) || empty($this->_name)) {
return false;
}
$analyzed_sql = array();
- if (self::isView($db, $table)) {
+ if ($this->isView()) {
// For a view, 'SHOW CREATE TABLE' returns the definition,
// but the structure of the view. So, we try to mock
// the result of analyzing 'SHOW CREATE TABLE' query.
$analyzed_sql[0] = array();
$analyzed_sql[0]['create_table_fields'] = array();
- $results = $GLOBALS['dbi']->fetchResult(
+ $results = $this->_dbi->fetchResult(
"SELECT COLUMN_NAME, DATA_TYPE
FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = '" . PMA_Util::sqlAddSlashes($db) . "'
- AND TABLE_NAME = '" . PMA_Util::sqlAddSlashes($table) . "'"
+ WHERE TABLE_SCHEMA = '" . PMA_Util::sqlAddSlashes($this->_db_name)
+ . " AND TABLE_NAME = '" . PMA_Util::sqlAddSlashes($this->_name) . "'"
);
foreach ($results as $result) {
@@ -274,10 +246,10 @@ class PMA_Table
);
}
} else {
- $show_create_table = $GLOBALS['dbi']->fetchValue(
+ $show_create_table = $this->_dbi->fetchValue(
'SHOW CREATE TABLE '
- . PMA_Util::backquote($db)
- . '.' . PMA_Util::backquote($table),
+ . PMA_Util::backquote($this->_db_name)
+ . '.' . PMA_Util::backquote($this->_name),
0,
1
);
@@ -287,53 +259,20 @@ class PMA_Table
}
/**
- * sets given $value for given $param
- *
- * @param string $param name
- * @param mixed $value value
- *
- * @return void
- */
- function set($param, $value)
- {
- $this->settings[$param] = $value;
- }
-
- /**
- * returns value for given setting/param
- *
- * @param string $param name for value to return
- *
- * @return mixed value for $param
- */
- function get($param)
- {
- if (isset($this->settings[$param])) {
- return $this->settings[$param];
- }
-
- return null;
- }
-
- /**
* Checks if this is a merge table
*
* If the ENGINE of the table is MERGE or MRG_MYISAM (alias),
* this is a merge table.
*
- * @param string $db the database name
- * @param string $table the table name
*
* @return boolean true if it is a merge table
*/
- static public function isMerge($db = null, $table = null)
+ public function isMerge()
{
$engine = null;
// if called static, with parameters
- if (! empty($db) && ! empty($table)) {
- $engine = PMA_Table::sGetStatusInfo(
- $db, $table, 'ENGINE', null, true
- );
+ if (! empty($this->_db_name) && ! empty($this->_name)) {
+ $engine = $this->getStatusInfo('ENGINE', null, true);
}
// did we get engine?
@@ -352,8 +291,6 @@ class PMA_Table
* Returns full table status info, or specific if $info provided
* this info is collected from information_schema
*
- * @param string $db database name
- * @param string $table table name
* @param string $info specific information to be fetched
* @param boolean $force_read read new rather than serving from cache
* @param boolean $disable_error if true, disables error message
@@ -363,23 +300,28 @@ class PMA_Table
*
* @return mixed
*/
- static public function sGetStatusInfo($db, $table, $info = null,
- $force_read = false, $disable_error = false
+ public function getStatusInfo(
+ $info = null,
+ $force_read = false,
+ $disable_error = false
) {
+ $db = $this->_db_name;
+ $table = $this->_name;
+
if (! empty($_SESSION['is_multi_query'])) {
$disable_error = true;
}
// sometimes there is only one entry (ExactRows) so
// we have to get the table's details
- if (! isset(PMA_Table::$cache[$db][$table])
+ if ($this->_dbi->getCachedTableContent("${db}.${table}") == null
|| $force_read
- || count(PMA_Table::$cache[$db][$table]) == 1
+ || count($this->_dbi->getCachedTableContent("${db}.${table}")) == 1
) {
- $GLOBALS['dbi']->getTablesFull($db, $table);
+ $this->_dbi->getTablesFull($db, $table);
}
- if (! isset(PMA_Table::$cache[$db][$table])) {
+ if ($this->_dbi->getCachedTableContent("${db}.${table}") == null) {
// happens when we enter the table creation dialog
// or when we really did not get any status info, for example
// when $table == 'TABLE_NAMES' after the user tried SHOW TABLES
@@ -387,11 +329,14 @@ class PMA_Table
}
if (null === $info) {
- return PMA_Table::$cache[$db][$table];
+ return $this->_dbi->getCachedTableContent("${db}.${table}");
}
// array_key_exists allows for null values
- if (!array_key_exists($info, PMA_Table::$cache[$db][$table])) {
+ if (!array_key_exists(
+ $info, $this->_dbi->getCachedTableContent("${db}.${table}")
+ )
+ ) {
if (! $disable_error) {
trigger_error(
__('Unknown table status:') . ' ' . $info,
@@ -401,7 +346,7 @@ class PMA_Table
return false;
}
- return PMA_Table::$cache[$db][$table][$info];
+ return $this->_dbi->getCachedTableContent("${db}.${table}.${info}");
}
/**
@@ -419,6 +364,8 @@ class PMA_Table
* default type
* @param string $extra 'AUTO_INCREMENT'
* @param string $comment field comment
+ * @param string $virtuality virtuality of the column
+ * @param string $expression expression for the virtual column
* @param string $move_to new position for column
*
* @todo move into class PMA_Column
@@ -430,7 +377,7 @@ class PMA_Table
static function generateFieldSpec($name, $type, $length = '',
$attribute = '', $collation = '', $null = false,
$default_type = 'USER_DEFINED', $default_value = '', $extra = '',
- $comment = '', $move_to = ''
+ $comment = '', $virtuality = '', $expression = '', $move_to = ''
) {
$is_timestamp = /*overload*/mb_strpos(
/*overload*/mb_strtoupper($type),
@@ -451,70 +398,75 @@ class PMA_Table
$query .= '(' . $length . ')';
}
- if ($attribute != '') {
- $query .= ' ' . $attribute;
- }
+ if ($virtuality) {
+ $query .= ' AS (' . $expression . ') ' . $virtuality;
+ } else {
+ if ($attribute != '') {
+ $query .= ' ' . $attribute;
+ }
- $matches = preg_match(
- '@^(TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT|VARCHAR|CHAR|ENUM|SET)$@i',
- $type
- );
- if (! empty($collation) && $collation != 'NULL' && $matches) {
- $query .= PMA_generateCharsetQueryPart($collation);
- }
+ $matches = preg_match(
+ '@^(TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT|VARCHAR|CHAR|ENUM|SET)$@i',
+ $type
+ );
+ if (! empty($collation) && $collation != 'NULL' && $matches) {
+ $query .= PMA_generateCharsetQueryPart($collation);
+ }
- if ($null !== false) {
- if ($null == 'NULL') {
- $query .= ' NULL';
- } else {
- $query .= ' NOT NULL';
+ if ($null !== false) {
+ if ($null == 'NULL') {
+ $query .= ' NULL';
+ } else {
+ $query .= ' NOT NULL';
+ }
}
- }
- switch ($default_type) {
- case 'USER_DEFINED' :
- if ($is_timestamp && $default_value === '0') {
- // a TIMESTAMP does not accept DEFAULT '0'
- // but DEFAULT 0 works
- $query .= ' DEFAULT 0';
- } elseif ($type == 'BIT') {
- $query .= ' DEFAULT b\''
+ switch ($default_type) {
+ case 'USER_DEFINED' :
+ if ($is_timestamp && $default_value === '0') {
+ // a TIMESTAMP does not accept DEFAULT '0'
+ // but DEFAULT 0 works
+ $query .= ' DEFAULT 0';
+ } elseif ($type == 'BIT') {
+ $query .= ' DEFAULT b\''
. preg_replace('/[^01]/', '0', $default_value)
. '\'';
- } elseif ($type == 'BOOLEAN') {
- if (preg_match('/^1|T|TRUE|YES$/i', $default_value)) {
- $query .= ' DEFAULT TRUE';
- } elseif (preg_match('/^0|F|FALSE|NO$/i', $default_value)) {
- $query .= ' DEFAULT FALSE';
+ } elseif ($type == 'BOOLEAN') {
+ if (preg_match('/^1|T|TRUE|YES$/i', $default_value)) {
+ $query .= ' DEFAULT TRUE';
+ } elseif (preg_match('/^0|F|FALSE|NO$/i', $default_value)) {
+ $query .= ' DEFAULT FALSE';
+ } else {
+ // Invalid BOOLEAN value
+ $query .= ' DEFAULT \''
+ . PMA_Util::sqlAddSlashes($default_value) . '\'';
+ }
+ } elseif ($type == 'BINARY' || $type == 'VARBINARY') {
+ $query .= ' DEFAULT 0x' . $default_value;
} else {
- // Invalid BOOLEAN value
$query .= ' DEFAULT \''
. PMA_Util::sqlAddSlashes($default_value) . '\'';
}
- } elseif ($type == 'BINARY' || $type == 'VARBINARY') {
- $query .= ' DEFAULT 0x' . $default_value;
- } else {
- $query .= ' DEFAULT \''
- . PMA_Util::sqlAddSlashes($default_value) . '\'';
- }
- break;
- case 'NULL' :
- // If user uncheck null checkbox and not change default value null,
- // default value will be ignored.
- if ($null !== false && $null !== 'NULL') {
+ break;
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 'NULL' :
+ // If user uncheck null checkbox and not change default value null,
+ // default value will be ignored.
+ if ($null !== false && $null !== 'NULL') {
+ break;
+ }
+ // else fall-through intended, no break here
+ case 'CURRENT_TIMESTAMP' :
+ $query .= ' DEFAULT ' . $default_type;
+ break;
+ case 'NONE' :
+ default :
break;
}
- // else fall-through intended, no break here
- case 'CURRENT_TIMESTAMP' :
- $query .= ' DEFAULT ' . $default_type;
- break;
- case 'NONE' :
- default :
- break;
- }
- if (!empty($extra)) {
- $query .= ' ' . $extra;
+ if (!empty($extra)) {
+ $query .= ' ' . $extra;
+ }
}
if (!empty($comment)) {
$query .= " COMMENT '" . PMA_Util::sqlAddSlashes($comment) . "'";
@@ -532,85 +484,91 @@ class PMA_Table
/**
* Counts and returns (or displays) the number of records in a table
*
- * @param string $db the current database name
- * @param string $table the current table name
- * @param bool $force_exact whether to force an exact count
- * @param bool $is_view whether the table is a view
+ * @param bool $force_exact whether to force an exact count
*
* @return mixed the number of records if "retain" param is true,
* otherwise true
*/
- static public function countRecords($db, $table, $force_exact = false,
- $is_view = null
- ) {
- if (isset(PMA_Table::$cache[$db][$table]['ExactRows'])) {
- $row_count = PMA_Table::$cache[$db][$table]['ExactRows'];
- } else {
- $row_count = false;
+ public function countRecords($force_exact = false)
+ {
+ $is_view = $this->isView();
+ $db = $this->_db_name;
+ $table = $this->_name;
- if (null === $is_view) {
- $is_view = PMA_Table::isView($db, $table);
- }
+ if ($this->_dbi->getCachedTableContent("${db}.${table}.ExactRows") != null) {
+ $row_count = $this->_dbi->getCachedTableContent(
+ "${db}.${table}.ExactRows"
+ );
+ return $row_count;
+ }
+ $row_count = false;
- if (! $force_exact) {
- if (! isset(PMA_Table::$cache[$db][$table]['Rows']) && ! $is_view) {
- $tmp_tables = $GLOBALS['dbi']->getTablesFull($db, $table);
- if (isset($tmp_tables[$table])) {
- PMA_Table::$cache[$db][$table] = $tmp_tables[$table];
- }
- }
- if (isset(PMA_Table::$cache[$db][$table]['Rows'])) {
- $row_count = PMA_Table::$cache[$db][$table]['Rows'];
- } else {
- $row_count = false;
+ if (! $force_exact) {
+ if (($this->_dbi->getCachedTableContent("${db}.${table}.Rows") == null)
+ && !$is_view
+ ) {
+ $tmp_tables = $this->_dbi->getTablesFull($db, $table);
+ if (isset($tmp_tables[$table])) {
+ $this->_dbi->cacheTableContent(
+ "${db}.${table}",
+ $tmp_tables[$table]
+ );
}
}
+ if ($this->_dbi->getCachedTableContent("${db}.${table}.Rows") != null) {
+ $row_count = $this->_dbi->getCachedTableContent(
+ "${db}.${table}.Rows"
+ );
+ } else {
+ $row_count = false;
+ }
+ }
+ // for a VIEW, $row_count is always false at this point
+ if (false !== $row_count
+ && $row_count >= $GLOBALS['cfg']['MaxExactCount']
+ ) {
+ return $row_count;
+ }
- // for a VIEW, $row_count is always false at this point
- if (false === $row_count
- || $row_count < $GLOBALS['cfg']['MaxExactCount']
- ) {
- // Make an exception for views in I_S and D_D schema in
- // Drizzle, as these map to in-memory data and should execute
- // fast enough
- if (! $is_view
- || (PMA_DRIZZLE && $GLOBALS['dbi']->isSystemSchema($db))
- ) {
- $row_count = $GLOBALS['dbi']->fetchValue(
- 'SELECT COUNT(*) FROM ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($table)
- );
- } else {
- // For complex views, even trying to get a partial record
- // count could bring down a server, so we offer an
- // alternative: setting MaxExactCountViews to 0 will bypass
- // completely the record counting for views
+ // Make an exception for views in I_S and D_D schema in
+ // Drizzle, as these map to in-memory data and should execute
+ // fast enough
+ if (! $is_view
+ || (PMA_DRIZZLE && $this->_dbi->isSystemSchema($db))
+ ) {
+ $row_count = $this->_dbi->fetchValue(
+ 'SELECT COUNT(*) FROM ' . PMA_Util::backquote($db) . '.'
+ . PMA_Util::backquote($table)
+ );
+ } else {
+ // For complex views, even trying to get a partial record
+ // count could bring down a server, so we offer an
+ // alternative: setting MaxExactCountViews to 0 will bypass
+ // completely the record counting for views
- if ($GLOBALS['cfg']['MaxExactCountViews'] == 0) {
- $row_count = 0;
- } else {
- // Counting all rows of a VIEW could be too long,
- // so use a LIMIT clause.
- // Use try_query because it can fail (when a VIEW is
- // based on a table that no longer exists)
- $result = $GLOBALS['dbi']->tryQuery(
- 'SELECT 1 FROM ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($table) . ' LIMIT '
- . $GLOBALS['cfg']['MaxExactCountViews'],
- null,
- PMA_DatabaseInterface::QUERY_STORE
- );
- if (!$GLOBALS['dbi']->getError()) {
- $row_count = $GLOBALS['dbi']->numRows($result);
- $GLOBALS['dbi']->freeResult($result);
- }
- }
- }
- if ($row_count) {
- PMA_Table::$cache[$db][$table]['ExactRows'] = $row_count;
+ if ($GLOBALS['cfg']['MaxExactCountViews'] == 0) {
+ $row_count = 0;
+ } else {
+ // Counting all rows of a VIEW could be too long,
+ // so use a LIMIT clause.
+ // Use try_query because it can fail (when a VIEW is
+ // based on a table that no longer exists)
+ $result = $this->_dbi->tryQuery(
+ 'SELECT 1 FROM ' . PMA_Util::backquote($db) . '.'
+ . PMA_Util::backquote($table) . ' LIMIT '
+ . $GLOBALS['cfg']['MaxExactCountViews'],
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+ if (!$this->_dbi->getError()) {
+ $row_count = $this->_dbi->numRows($result);
+ $this->_dbi->freeResult($result);
}
}
}
+ if ($row_count) {
+ $this->_dbi->cacheTableContent("${db}.${table}.ExactRows", $row_count);
+ }
return $row_count;
} // end of the 'PMA_Table::countRecords()' function
@@ -631,6 +589,8 @@ class PMA_Table
* type
* @param string $extra 'AUTO_INCREMENT'
* @param string $comment field comment
+ * @param string $virtuality virtuality of the column
+ * @param string $expression expression for the virtual column
* @param string $move_to new position for column
*
* @see PMA_Table::generateFieldSpec()
@@ -639,14 +599,14 @@ class PMA_Table
*/
static public function generateAlter($oldcol, $newcol, $type, $length,
$attribute, $collation, $null, $default_type, $default_value,
- $extra, $comment, $move_to
+ $extra, $comment, $virtuality, $expression, $move_to
) {
return PMA_Util::backquote($oldcol) . ' '
- . PMA_Table::generateFieldSpec(
- $newcol, $type, $length, $attribute,
- $collation, $null, $default_type, $default_value, $extra,
- $comment, $move_to
- );
+ . PMA_Table::generateFieldSpec(
+ $newcol, $type, $length, $attribute,
+ $collation, $null, $default_type, $default_value, $extra,
+ $comment, $virtuality, $expression, $move_to
+ );
} // end function
/**
@@ -674,67 +634,65 @@ class PMA_Table
) {
$last_id = -1;
- if (isset($GLOBALS['cfgRelation']) && $GLOBALS['cfgRelation'][$work]) {
- $select_parts = array();
- $row_fields = array();
- foreach ($get_fields as $get_field) {
- $select_parts[] = PMA_Util::backquote($get_field);
- $row_fields[$get_field] = 'cc';
- }
+ if (!isset($GLOBALS['cfgRelation']) || !$GLOBALS['cfgRelation'][$work]) {
+ return true;
+ }
- $where_parts = array();
- foreach ($where_fields as $_where => $_value) {
- $where_parts[] = PMA_Util::backquote($_where) . ' = \''
- . PMA_Util::sqlAddSlashes($_value) . '\'';
- }
+ $select_parts = array();
+ $row_fields = array();
+ foreach ($get_fields as $get_field) {
+ $select_parts[] = PMA_Util::backquote($get_field);
+ $row_fields[$get_field] = 'cc';
+ }
- $new_parts = array();
- $new_value_parts = array();
- foreach ($new_fields as $_where => $_value) {
- $new_parts[] = PMA_Util::backquote($_where);
- $new_value_parts[] = PMA_Util::sqlAddSlashes($_value);
- }
+ $where_parts = array();
+ foreach ($where_fields as $_where => $_value) {
+ $where_parts[] = PMA_Util::backquote($_where) . ' = \''
+ . PMA_Util::sqlAddSlashes($_value) . '\'';
+ }
- $table_copy_query = '
- SELECT ' . implode(', ', $select_parts) . '
- FROM ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.'
- . PMA_Util::backquote($GLOBALS['cfgRelation'][$pma_table]) . '
- WHERE ' . implode(' AND ', $where_parts);
+ $new_parts = array();
+ $new_value_parts = array();
+ foreach ($new_fields as $_where => $_value) {
+ $new_parts[] = PMA_Util::backquote($_where);
+ $new_value_parts[] = PMA_Util::sqlAddSlashes($_value);
+ }
- // must use PMA_DatabaseInterface::QUERY_STORE here, since we execute
- // another query inside the loop
- $table_copy_rs = PMA_queryAsControlUser(
- $table_copy_query, true, PMA_DatabaseInterface::QUERY_STORE
- );
+ $table_copy_query = '
+ SELECT ' . implode(', ', $select_parts) . '
+ FROM ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.'
+ . PMA_Util::backquote($GLOBALS['cfgRelation'][$pma_table]) . '
+ WHERE ' . implode(' AND ', $where_parts);
- while ($table_copy_row = @$GLOBALS['dbi']->fetchAssoc($table_copy_rs)) {
- $value_parts = array();
- foreach ($table_copy_row as $_key => $_val) {
- if (isset($row_fields[$_key]) && $row_fields[$_key] == 'cc') {
- $value_parts[] = PMA_Util::sqlAddSlashes($_val);
- }
+ // must use PMA_DatabaseInterface::QUERY_STORE here, since we execute
+ // another query inside the loop
+ $table_copy_rs = PMA_queryAsControlUser(
+ $table_copy_query, true, PMA_DatabaseInterface::QUERY_STORE
+ );
+
+ while ($table_copy_row = @$GLOBALS['dbi']->fetchAssoc($table_copy_rs)) {
+ $value_parts = array();
+ foreach ($table_copy_row as $_key => $_val) {
+ if (isset($row_fields[$_key]) && $row_fields[$_key] == 'cc') {
+ $value_parts[] = PMA_Util::sqlAddSlashes($_val);
}
+ }
- $new_table_query = 'INSERT IGNORE INTO '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.'
- . PMA_Util::backquote($GLOBALS['cfgRelation'][$pma_table])
- . ' (' . implode(', ', $select_parts)
- . ', ' . implode(', ', $new_parts)
- . ') VALUES (\''
- . implode('\', \'', $value_parts) . '\', \''
- . implode('\', \'', $new_value_parts) . '\')';
-
- PMA_queryAsControlUser($new_table_query);
- $last_id = $GLOBALS['dbi']->insertId();
- } // end while
+ $new_table_query = 'INSERT IGNORE INTO '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($GLOBALS['cfgRelation'][$pma_table])
+ . ' (' . implode(', ', $select_parts) . ', '
+ . implode(', ', $new_parts) . ') VALUES (\''
+ . implode('\', \'', $value_parts) . '\', \''
+ . implode('\', \'', $new_value_parts) . '\')';
- $GLOBALS['dbi']->freeResult($table_copy_rs);
+ PMA_queryAsControlUser($new_table_query);
+ $last_id = $GLOBALS['dbi']->insertId();
+ } // end while
- return $last_id;
- }
+ $GLOBALS['dbi']->freeResult($table_copy_rs);
- return true;
+ return $last_id;
} // end of 'PMA_Table::duplicateInfo()' function
/**
@@ -753,23 +711,23 @@ class PMA_Table
static public function moveCopy($source_db, $source_table, $target_db,
$target_table, $what, $move, $mode
) {
+
global $err_url;
- /* Try moving table directly */
+ // Try moving the tables directly, using native `RENAME` statement.
if ($move && $what == 'data') {
$tbl = new PMA_Table($source_table, $source_db);
- $result = $tbl->rename($target_table, $target_db);
- if ($result) {
+ if ($tbl->rename($target_table, $target_db)) {
$GLOBALS['message'] = $tbl->getLastMessage();
return true;
}
}
- // set export settings we need
+ // Setting required export settings.
$GLOBALS['sql_backquotes'] = 1;
$GLOBALS['asfile'] = 1;
- // Ensure the target is valid
+ // Ensuring the target database is valid.
if (! $GLOBALS['pma']->databases->exists($source_db, $target_db)) {
if (! $GLOBALS['pma']->databases->exists($source_db)) {
$GLOBALS['message'] = PMA_Message::rawError(
@@ -790,23 +748,40 @@ class PMA_Table
return false;
}
+ /**
+ * The full name of source table, quoted.
+ * @var string $source
+ */
$source = PMA_Util::backquote($source_db)
. '.' . PMA_Util::backquote($source_table);
+
+ // If the target database is not specified, the operation is taking
+ // place in the same database.
if (! isset($target_db) || ! /*overload*/mb_strlen($target_db)) {
$target_db = $source_db;
}
- // Doing a select_db could avoid some problems with replicated databases,
- // when moving table from replicated one to not replicated one
+ // Selecting the database could avoid some problems with replicated
+ // databases, when moving table from replicated one to not replicated one.
$GLOBALS['dbi']->selectDb($target_db);
+ /**
+ * The full name of target table, quoted.
+ * @var string $target
+ */
$target = PMA_Util::backquote($target_db)
. '.' . PMA_Util::backquote($target_table);
- // do not create the table if dataonly
+ // No table is created when this is a data-only operation.
if ($what != 'dataonly') {
+
include_once "libraries/plugin_interface.lib.php";
- // get Export SQL instance
+
+ /**
+ * Instance used for exporting the current structure of the table.
+ *
+ * @var ExportSql
+ */
$export_sql_plugin = PMA_getPlugin(
"export",
"sql",
@@ -824,141 +799,133 @@ class PMA_Table
$GLOBALS['sql_auto_increment'] = $_POST['sql_auto_increment'];
}
+ /**
+ * The old structure of the table..
+ * @var string $sql_structure
+ */
$sql_structure = $export_sql_plugin->getTableDef(
$source_db, $source_table, "\n", $err_url, false, false
);
+
unset($no_constraints_comments);
- $parsed_sql = PMA_SQP_parse($sql_structure);
- $analyzed_sql = PMA_SQP_analyze($parsed_sql);
- $i = 0;
- if (empty($analyzed_sql[0]['create_table_fields'])) {
- // this is not a CREATE TABLE, so find the first VIEW
- $target_for_view = PMA_Util::backquote($target_db);
- while (true) {
- if ($parsed_sql[$i]['type'] == 'alpha_reservedWord'
- && $parsed_sql[$i]['data'] == 'VIEW'
- ) {
- break;
- }
- $i++;
- }
- }
- unset($analyzed_sql);
- if (PMA_DRIZZLE) {
- $table_delimiter = 'quote_backtick';
- } else {
- $server_sql_mode = $GLOBALS['dbi']->fetchValue(
- "SHOW VARIABLES LIKE 'sql_mode'",
- 0,
- 1
- );
- // ANSI_QUOTES might be a subset of sql_mode, for example
- // REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
- if (false !== /*overload*/mb_strpos($server_sql_mode, 'ANSI_QUOTES')
- ) {
- $table_delimiter = 'quote_double';
- } else {
- $table_delimiter = 'quote_backtick';
- }
- unset($server_sql_mode);
- }
- /* Find table name in query and replace it */
- while ($parsed_sql[$i]['type'] != $table_delimiter) {
- $i++;
- }
+ // -----------------------------------------------------------------
+ // Phase 0: Preparing structures used.
- /* no need to backquote() */
- if (isset($target_for_view)) {
- // this a view definition; we just found the first db name
- // that follows DEFINER VIEW
- // so change it for the new db name
- $parsed_sql[$i]['data'] = $target_for_view;
- // then we have to find all references to the source db
- // and change them to the target db, ensuring we stay into
- // the $parsed_sql limits
- $last = $parsed_sql['len'] - 1;
- $backquoted_source_db = PMA_Util::backquote($source_db);
- for (++$i; $i <= $last; $i++) {
- if ($parsed_sql[$i]['type'] == $table_delimiter
- && $parsed_sql[$i]['data'] == $backquoted_source_db
- && $parsed_sql[$i - 1]['type'] != 'punct_qualifier'
- ) {
- $parsed_sql[$i]['data'] = $target_for_view;
- }
- }
- unset($last,$backquoted_source_db);
- } else {
- $parsed_sql[$i]['data'] = $target;
+ /**
+ * The destination where the table is moved or copied to.
+ * @var SqlParser\Components\Expression
+ */
+ $destination = new SqlParser\Components\Expression(
+ $target_db, $target_table, ''
+ );
+
+ // Find server's SQL mode so the builder can generate correct
+ // queries.
+ // One of the options that alters the behaviour is `ANSI_QUOTES`.
+ // This is not availabile for Drizzle.
+ if (!PMA_DRIZZLE) {
+ SqlParser\Context::setMode(
+ $GLOBALS['dbi']->fetchValue("SELECT @@sql_mode")
+ );
}
- /* Generate query back */
- $sql_structure = PMA_SQP_format($parsed_sql, 'query_only');
- // If table exists, and 'add drop table' is selected: Drop it!
+ // -----------------------------------------------------------------
+ // Phase 1: Dropping existent element of the same name (if exists
+ // and required).
+
if (isset($_REQUEST['drop_if_exists'])
&& $_REQUEST['drop_if_exists'] == 'true'
) {
- if (PMA_Table::isView($target_db, $target_table)) {
- $drop_query = 'DROP VIEW';
- } else {
- $drop_query = 'DROP TABLE';
- }
- $drop_query .= ' IF EXISTS '
- . PMA_Util::backquote($target_db) . '.'
- . PMA_Util::backquote($target_table);
- $GLOBALS['dbi']->query($drop_query);
- $GLOBALS['sql_query'] .= "\n" . $drop_query . ';';
+ /**
+ * Drop statement used for building the query.
+ * @var SqlParser\Statements\DropStatement $statement
+ */
+ $statement = new SqlParser\Statements\DropStatement();
+
+ $tbl = new PMA_Table($target_db, $target_table);
+
+ $statement->options = new SqlParser\Components\OptionsArray(
+ array(
+ $tbl->isView() ? 'VIEW' : 'TABLE',
+ 'IF EXISTS',
+ )
+ );
+
+ $statement->fields = array($destination);
+
+ // Building the query.
+ $drop_query = $statement->build() . ';';
- // If an existing table gets deleted, maintain any
- // entries for the PMA_* tables
+ // Executing it.
+ $GLOBALS['dbi']->query($drop_query);
+ $GLOBALS['sql_query'] .= "\n" . $drop_query;
+
+ // If an existing table gets deleted, maintain any entries for
+ // the PMA_* tables.
$maintain_relations = true;
}
- @$GLOBALS['dbi']->query($sql_structure);
- $GLOBALS['sql_query'] .= "\n" . $sql_structure . ';';
+ // -----------------------------------------------------------------
+ // Phase 2: Generating the new query of this structure.
+
+ /**
+ * The parser responsible for parsing the old queries.
+ * @var SqlParser\Parser $parser
+ */
+ $parser = new SqlParser\Parser($sql_structure);
+
+ if (!empty($parser->statements[0])) {
+
+ /**
+ * The CREATE statement of this structure.
+ * @var SqlParser\Statements\CreateStatement $statement
+ */
+ $statement = $parser->statements[0];
+
+ // Changing the destination.
+ $statement->name = $destination;
+
+ // Building back the query.
+ $sql_structure = $statement->build() . ';';
+
+ // Executing it.
+ $GLOBALS['dbi']->query($sql_structure);
+ $GLOBALS['sql_query'] .= "\n" . $sql_structure;
+ }
+
+ // -----------------------------------------------------------------
+ // Phase 3: Adding constraints.
+ // All constraint names are removed because they must be unique.
if (($move || isset($GLOBALS['add_constraints']))
&& !empty($GLOBALS['sql_constraints_query'])
) {
- $parsed_sql = PMA_SQP_parse($GLOBALS['sql_constraints_query']);
- $i = 0;
-
- // find the first $table_delimiter, it must be the source
- // table name
- while ($parsed_sql[$i]['type'] != $table_delimiter) {
- $i++;
- // maybe someday we should guard against going over limit
- //if ($i == $parsed_sql['len']) {
- // break;
- //}
- }
- // replace it by the target table name, no need
- // to backquote()
- $parsed_sql[$i]['data'] = $target;
+ $parser = new SqlParser\Parser($GLOBALS['sql_constraints_query']);
- // now we must remove all $table_delimiter that follow a
- // CONSTRAINT keyword, because a constraint name must be
- // unique in a db
+ /**
+ * The ALTER statement that generates the constraints.
+ * @var SqlParser\Statements\AlterStatement $statement
+ */
+ $statement = $parser->statements[0];
- $cnt = $parsed_sql['len'] - 1;
+ // Changing the altered table to the destination.
+ $statement->table = $destination;
- for ($j = $i; $j < $cnt; $j++) {
- $dataUpper = /*overload*/mb_strtoupper($parsed_sql[$j]['data']);
- if ($parsed_sql[$j]['type'] == 'alpha_reservedWord'
- && $dataUpper == 'CONSTRAINT'
- ) {
- if ($parsed_sql[$j+1]['type'] == $table_delimiter) {
- $parsed_sql[$j+1]['data'] = '';
- }
+ // Removing the name of the constraints.
+ foreach ($statement->altered as $idx => $altered) {
+ // All constraint names are removed because they must be unique.
+ if ($altered->options->has('CONSTRAINT')) {
+ $altered->field = null;
}
}
- // Generate query back
- $GLOBALS['sql_constraints_query'] = PMA_SQP_format(
- $parsed_sql, 'query_only'
- );
+ // Building back the query.
+ $GLOBALS['sql_constraints_query'] = $statement->build() . ';';
+
+ // Executing it.
if ($mode == 'one_table') {
$GLOBALS['dbi']->query($GLOBALS['sql_constraints_query']);
}
@@ -968,102 +935,78 @@ class PMA_Table
}
}
- // add indexes to the table
- if (!empty($GLOBALS['sql_indexes'])) {
-
- $index_queries = array();
- $sql_indexes = $GLOBALS['sql_indexes'];
- $GLOBALS['sql_indexes'] = '';
-
- $parsed_sql = PMA_SQP_parse($sql_indexes);
- $cnt = $parsed_sql['len'] - 1;
- $k = 0;
-
- for ($j = 0; $j < $cnt; $j++) {
- if ($parsed_sql[$j]['type'] == 'punct_queryend') {
- $index_queries[] = substr(
- $sql_indexes, $k, $parsed_sql[$j]['pos'] - $k
- );
- $k = $parsed_sql[$j]['pos'];
- }
- }
-
- foreach ($index_queries as $index_query) {
+ // -----------------------------------------------------------------
+ // Phase 4: Adding indexes.
+ // View phase 3.
- $parsed_sql = PMA_SQP_parse($index_query);
- $i = 0;
+ if (!empty($GLOBALS['sql_indexes'])) {
- while ($parsed_sql[$i]['type'] != $table_delimiter) {
- $i++;
- }
+ $parser = new SqlParser\Parser($GLOBALS['sql_indexes']);
- $parsed_sql[$i]['data'] = $target;
+ /**
+ * The ALTER statement that generates the indexes.
+ * @var SqlParser\Statements\AlterStatement $statement
+ */
+ $statement = $parser->statements[0];
- $cnt = $parsed_sql['len'] - 1;
+ // Changing the altered table to the destination.
+ $statement->table = $destination;
- for ($j = $i; $j < $cnt; $j++) {
- $dataUpper = /*overload*/mb_strtoupper($parsed_sql[$j]['data']);
- if ($parsed_sql[$j]['type'] == 'alpha_reservedWord'
- && $dataUpper == 'CONSTRAINT'
- ) {
- if ($parsed_sql[$j+1]['type'] == $table_delimiter) {
- $parsed_sql[$j+1]['data'] = '';
- }
- }
+ // Removing the name of the constraints.
+ foreach ($statement->altered as $idx => $altered) {
+ // All constraint names are removed because they must be unique.
+ if ($altered->options->has('CONSTRAINT')) {
+ $altered->field = null;
}
+ }
- $sql_index = PMA_SQP_format($parsed_sql, 'query_only');
- if ($mode == 'one_table' || $mode == 'db_copy') {
- $GLOBALS['dbi']->query($sql_index);
- }
+ // Building back the query.
+ $GLOBALS['sql_indexes'] = $statement->build() . ';';
- $GLOBALS['sql_indexes'] .= $sql_index;
+ // Executing it.
+ if ($mode == 'one_table' || $mode == 'db_copy') {
+ $GLOBALS['dbi']->query($GLOBALS['sql_indexes']);
}
-
$GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_indexes'];
if ($mode == 'one_table' || $mode == 'db_copy') {
unset($GLOBALS['sql_indexes']);
-
}
}
- /*
- * add AUTO_INCREMENT to the table
- *
- * @todo refactor with similar code above
- */
+ // -----------------------------------------------------------------
+ // Phase 5: Adding AUTO_INCREMENT.
+
if (! empty($GLOBALS['sql_auto_increments'])) {
if ($mode == 'one_table' || $mode == 'db_copy') {
- $parsed_sql = PMA_SQP_parse($GLOBALS['sql_auto_increments']);
- $i = 0;
- // find the first $table_delimiter, it must be the source
- // table name
- while ($parsed_sql[$i]['type'] != $table_delimiter) {
- $i++;
- }
+ $parser = new SqlParser\Parser($GLOBALS['sql_auto_increments']);
- // replace it by the target table name, no need
- // to backquote()
- $parsed_sql[$i]['data'] = $target;
+ /**
+ * The ALTER statement that alters the AUTO_INCREMENT value.
+ * @var SqlParser\Statements\AlterStatement $statement
+ */
+ $statement = $parser->statements[0];
- // Generate query back
- $GLOBALS['sql_auto_increments'] = PMA_SQP_format(
- $parsed_sql, 'query_only'
- );
+ // Changing the altered table to the destination.
+ $statement->table = $destination;
+
+ // Building back the query.
+ $GLOBALS['sql_auto_increments'] = $statement->build() . ';';
+
+ // Executing it.
$GLOBALS['dbi']->query($GLOBALS['sql_auto_increments']);
$GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_auto_increments'];
unset($GLOBALS['sql_auto_increments']);
}
}
-
} else {
$GLOBALS['sql_query'] = '';
}
+ $_table = new PMA_Table($target_table, $target_db);
// Copy the data unless this is a VIEW
if (($what == 'data' || $what == 'dataonly')
- && ! PMA_Table::isView($target_db, $target_table)
+ && ! $_table->isView()
) {
if (! PMA_DRIZZLE) {
$sql_set_mode = "SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'";
@@ -1074,10 +1017,10 @@ class PMA_Table
$sql_insert_data = 'INSERT INTO ' . $target
. ' SELECT * FROM ' . $source;
$GLOBALS['dbi']->query($sql_insert_data);
- $GLOBALS['sql_query'] .= "\n\n" . $sql_insert_data . ';';
+ $GLOBALS['sql_query'] .= "\n\n" . $sql_insert_data . ';';
}
- $GLOBALS['cfgRelation'] = PMA_getRelationsParam();
+ PMA_getRelationsParam();
// Drops old table if the user has requested to move it
if ($move) {
@@ -1086,7 +1029,8 @@ class PMA_Table
// moving table from replicated one to not replicated one
$GLOBALS['dbi']->selectDb($source_db);
- if (PMA_Table::isView($source_db, $source_table)) {
+ $_source_table = new PMA_Table($source_table, $source_db);
+ if ($_source_table->isView()) {
$sql_drop_query = 'DROP VIEW';
} else {
$sql_drop_query = 'DROP TABLE';
@@ -1100,184 +1044,180 @@ class PMA_Table
$source_table, $target_table
);
- $GLOBALS['sql_query'] .= "\n\n" . $sql_drop_query . ';';
+ $GLOBALS['sql_query'] .= "\n\n" . $sql_drop_query . ';';
// end if ($move)
- } else {
- // we are copying
- // Create new entries as duplicates from old PMA DBs
- if ($what != 'dataonly' && ! isset($maintain_relations)) {
- if ($GLOBALS['cfgRelation']['commwork']) {
- // Get all comments and MIME-Types for current table
- $comments_copy_rs = PMA_queryAsControlUser(
- 'SELECT column_name, comment'
- . ($GLOBALS['cfgRelation']['mimework']
+ return true;
+ }
+
+ // we are copying
+ // Create new entries as duplicates from old PMA DBs
+ if ($what == 'dataonly' || isset($maintain_relations)) {
+ return true;
+ }
+
+ if ($GLOBALS['cfgRelation']['commwork']) {
+ // Get all comments and MIME-Types for current table
+ $comments_copy_rs = PMA_queryAsControlUser(
+ 'SELECT column_name, comment'
+ . ($GLOBALS['cfgRelation']['mimework']
+ ? ', mimetype, transformation, transformation_options'
+ : '')
+ . ' FROM '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.'
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['column_info'])
+ . ' WHERE '
+ . ' db_name = \''
+ . PMA_Util::sqlAddSlashes($source_db) . '\''
+ . ' AND '
+ . ' table_name = \''
+ . PMA_Util::sqlAddSlashes($source_table) . '\''
+ );
+
+ // Write every comment as new copied entry. [MIME]
+ while ($comments_copy_row
+ = $GLOBALS['dbi']->fetchAssoc($comments_copy_rs)) {
+ $new_comment_query = 'REPLACE INTO '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote(
+ $GLOBALS['cfgRelation']['column_info']
+ )
+ . ' (db_name, table_name, column_name, comment'
+ . ($GLOBALS['cfgRelation']['mimework']
? ', mimetype, transformation, transformation_options'
: '')
- . ' FROM '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.'
- . PMA_Util::backquote($GLOBALS['cfgRelation']['column_info'])
- . ' WHERE '
- . ' db_name = \''
- . PMA_Util::sqlAddSlashes($source_db) . '\''
- . ' AND '
- . ' table_name = \''
- . PMA_Util::sqlAddSlashes($source_table) . '\''
- );
-
- // Write every comment as new copied entry. [MIME]
- while ($comments_copy_row
- = $GLOBALS['dbi']->fetchAssoc($comments_copy_rs)) {
- $new_comment_query = 'REPLACE INTO '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.'
- . PMA_Util::backquote(
- $GLOBALS['cfgRelation']['column_info']
- )
- . ' (db_name, table_name, column_name, comment'
- . ($GLOBALS['cfgRelation']['mimework']
- ? ', mimetype, transformation, transformation_options'
- : '')
- . ') '
- . ' VALUES('
- . '\'' . PMA_Util::sqlAddSlashes($target_db)
- . '\','
- . '\'' . PMA_Util::sqlAddSlashes($target_table)
- . '\','
- . '\''
- . PMA_Util::sqlAddSlashes(
- $comments_copy_row['column_name']
- )
- . '\''
- . ($GLOBALS['cfgRelation']['mimework']
- ? ',\''
- . PMA_Util::sqlAddSlashes(
- $comments_copy_row['comment']
- ) . '\','
- . '\'' . PMA_Util::sqlAddSlashes(
- $comments_copy_row['mimetype']
- ) . '\','
- . '\'' . PMA_Util::sqlAddSlashes(
- $comments_copy_row['transformation']
- ) . '\','
- . '\'' . PMA_Util::sqlAddSlashes(
- $comments_copy_row['transformation_options']
- ) . '\''
- : '')
- . ')';
- PMA_queryAsControlUser($new_comment_query);
- } // end while
- $GLOBALS['dbi']->freeResult($comments_copy_rs);
- unset($comments_copy_rs);
- }
+ . ') ' . ' VALUES(' . '\'' . PMA_Util::sqlAddSlashes($target_db)
+ . '\',\'' . PMA_Util::sqlAddSlashes($target_table) . '\',\''
+ . PMA_Util::sqlAddSlashes($comments_copy_row['column_name'])
+ . '\''
+ . ($GLOBALS['cfgRelation']['mimework']
+ ? ',\'' . PMA_Util::sqlAddSlashes(
+ $comments_copy_row['comment']
+ )
+ . '\',' . '\'' . PMA_Util::sqlAddSlashes(
+ $comments_copy_row['mimetype']
+ )
+ . '\',' . '\'' . PMA_Util::sqlAddSlashes(
+ $comments_copy_row['transformation']
+ )
+ . '\',' . '\'' . PMA_Util::sqlAddSlashes(
+ $comments_copy_row['transformation_options']
+ )
+ . '\''
+ : '')
+ . ')';
+ PMA_queryAsControlUser($new_comment_query);
+ } // end while
+ $GLOBALS['dbi']->freeResult($comments_copy_rs);
+ unset($comments_copy_rs);
+ }
- // duplicating the bookmarks must not be done here, but
- // just once per db
+ // duplicating the bookmarks must not be done here, but
+ // just once per db
- $get_fields = array('display_field');
- $where_fields = array(
- 'db_name' => $source_db,
- 'table_name' => $source_table
- );
- $new_fields = array(
- 'db_name' => $target_db,
- 'table_name' => $target_table
- );
- PMA_Table::duplicateInfo(
- 'displaywork',
- 'table_info',
- $get_fields,
- $where_fields,
- $new_fields
- );
+ $get_fields = array('display_field');
+ $where_fields = array(
+ 'db_name' => $source_db,
+ 'table_name' => $source_table
+ );
+ $new_fields = array(
+ 'db_name' => $target_db,
+ 'table_name' => $target_table
+ );
+ PMA_Table::duplicateInfo(
+ 'displaywork',
+ 'table_info',
+ $get_fields,
+ $where_fields,
+ $new_fields
+ );
- /**
- * @todo revise this code when we support cross-db relations
- */
- $get_fields = array(
- 'master_field',
- 'foreign_table',
- 'foreign_field'
- );
- $where_fields = array(
- 'master_db' => $source_db,
- 'master_table' => $source_table
- );
- $new_fields = array(
- 'master_db' => $target_db,
- 'foreign_db' => $target_db,
- 'master_table' => $target_table
- );
- PMA_Table::duplicateInfo(
- 'relwork',
- 'relation',
- $get_fields,
- $where_fields,
- $new_fields
- );
+ /**
+ * @todo revise this code when we support cross-db relations
+ */
+ $get_fields = array(
+ 'master_field',
+ 'foreign_table',
+ 'foreign_field'
+ );
+ $where_fields = array(
+ 'master_db' => $source_db,
+ 'master_table' => $source_table
+ );
+ $new_fields = array(
+ 'master_db' => $target_db,
+ 'foreign_db' => $target_db,
+ 'master_table' => $target_table
+ );
+ PMA_Table::duplicateInfo(
+ 'relwork',
+ 'relation',
+ $get_fields,
+ $where_fields,
+ $new_fields
+ );
- $get_fields = array(
- 'foreign_field',
- 'master_table',
- 'master_field'
- );
- $where_fields = array(
- 'foreign_db' => $source_db,
- 'foreign_table' => $source_table
- );
- $new_fields = array(
- 'master_db' => $target_db,
- 'foreign_db' => $target_db,
- 'foreign_table' => $target_table
- );
- PMA_Table::duplicateInfo(
- 'relwork',
- 'relation',
- $get_fields,
- $where_fields,
- $new_fields
- );
+ $get_fields = array(
+ 'foreign_field',
+ 'master_table',
+ 'master_field'
+ );
+ $where_fields = array(
+ 'foreign_db' => $source_db,
+ 'foreign_table' => $source_table
+ );
+ $new_fields = array(
+ 'master_db' => $target_db,
+ 'foreign_db' => $target_db,
+ 'foreign_table' => $target_table
+ );
+ PMA_Table::duplicateInfo(
+ 'relwork',
+ 'relation',
+ $get_fields,
+ $where_fields,
+ $new_fields
+ );
- /**
- * @todo Can't get duplicating PDFs the right way. The
- * page numbers always get screwed up independently from
- * duplication because the numbers do not seem to be stored on a
- * per-database basis. Would the author of pdf support please
- * have a look at it?
- *
- $get_fields = array('page_descr');
- $where_fields = array('db_name' => $source_db);
- $new_fields = array('db_name' => $target_db);
- $last_id = PMA_Table::duplicateInfo(
- 'pdfwork',
- 'pdf_pages',
- $get_fields,
- $where_fields,
- $new_fields
- );
+ /**
+ * @todo Can't get duplicating PDFs the right way. The
+ * page numbers always get screwed up independently from
+ * duplication because the numbers do not seem to be stored on a
+ * per-database basis. Would the author of pdf support please
+ * have a look at it?
+ *
+ $get_fields = array('page_descr');
+ $where_fields = array('db_name' => $source_db);
+ $new_fields = array('db_name' => $target_db);
+ $last_id = PMA_Table::duplicateInfo(
+ 'pdfwork',
+ 'pdf_pages',
+ $get_fields,
+ $where_fields,
+ $new_fields
+ );
- if (isset($last_id) && $last_id >= 0) {
- $get_fields = array('x', 'y');
- $where_fields = array(
- 'db_name' => $source_db,
- 'table_name' => $source_table
- );
- $new_fields = array(
- 'db_name' => $target_db,
- 'table_name' => $target_table,
- 'pdf_page_number' => $last_id
- );
- PMA_Table::duplicateInfo(
- 'pdfwork',
- 'table_coords',
- $get_fields,
- $where_fields,
- $new_fields
- );
- }
- */
- }
+ if (isset($last_id) && $last_id >= 0) {
+ $get_fields = array('x', 'y');
+ $where_fields = array(
+ 'db_name' => $source_db,
+ 'table_name' => $source_table
+ );
+ $new_fields = array(
+ 'db_name' => $target_db,
+ 'table_name' => $target_table,
+ 'pdf_page_number' => $last_id
+ );
+ PMA_Table::duplicateInfo(
+ 'pdfwork',
+ 'table_coords',
+ $get_fields,
+ $where_fields,
+ $new_fields
+ );
}
+ */
+
return true;
}
@@ -1345,7 +1285,7 @@ class PMA_Table
}
// If the table is moved to a different database drop its triggers first
- $triggers = $GLOBALS['dbi']->getTriggers(
+ $triggers = $this->_dbi->getTriggers(
$this->getDbName(), $this->getName(), ''
);
$handle_triggers = $this->getDbName() != $new_db && $triggers;
@@ -1354,7 +1294,7 @@ class PMA_Table
$sql = 'DROP TRIGGER IF EXISTS '
. PMA_Util::backquote($this->getDbName())
. '.' . PMA_Util::backquote($trigger['name']) . ';';
- $GLOBALS['dbi']->query($sql);
+ $this->_dbi->query($sql);
}
}
@@ -1365,12 +1305,12 @@ class PMA_Table
RENAME TABLE ' . $this->getFullName(true) . '
TO ' . $new_table->getFullName(true) . ';';
// I don't think a specific error message for views is necessary
- if (! $GLOBALS['dbi']->query($GLOBALS['sql_query'])) {
+ if (! $this->_dbi->query($GLOBALS['sql_query'])) {
// Restore triggers in the old database
if ($handle_triggers) {
- $GLOBALS['dbi']->selectDb($this->getDbName());
+ $this->_dbi->selectDb($this->getDbName());
foreach ($triggers as $trigger) {
- $GLOBALS['dbi']->query($trigger['create']);
+ $this->_dbi->query($trigger['create']);
}
}
$this->errors[] = sprintf(
@@ -1383,8 +1323,8 @@ class PMA_Table
$old_name = $this->getName();
$old_db = $this->getDbName();
- $this->setName($new_name);
- $this->setDbName($new_db);
+ $this->_name = $new_name;
+ $this->_db_name = $new_db;
// Renable table in configuration storage
PMA_REL_renameTable(
@@ -1419,12 +1359,12 @@ class PMA_Table
*/
public function getUniqueColumns($backquoted = true, $fullName = true)
{
- $sql = $GLOBALS['dbi']->getTableIndexesSql(
+ $sql = $this->_dbi->getTableIndexesSql(
$this->getDbName(),
$this->getName(),
'Non_unique = 0'
);
- $uniques = $GLOBALS['dbi']->fetchResult(
+ $uniques = $this->_dbi->fetchResult(
$sql,
array('Key_name', null),
'Column_name'
@@ -1468,12 +1408,12 @@ class PMA_Table
*/
public function getIndexedColumns($backquoted = true, $fullName = true)
{
- $sql = $GLOBALS['dbi']->getTableIndexesSql(
+ $sql = $this->_dbi->getTableIndexesSql(
$this->getDbName(),
$this->getName(),
''
);
- $indexed = $GLOBALS['dbi']->fetchResult($sql, 'Column_name', 'Column_name');
+ $indexed = $this->_dbi->fetchResult($sql, 'Column_name', 'Column_name');
$return = array();
foreach ($indexed as $column) {
@@ -1497,7 +1437,7 @@ class PMA_Table
public function getColumns($backquoted = true, $fullName = true)
{
$sql = 'SHOW COLUMNS FROM ' . $this->getFullName(true);
- $indexed = $GLOBALS['dbi']->fetchResult($sql, 'Field', 'Field');
+ $indexed = $this->_dbi->fetchResult($sql, 'Field', 'Field');
$return = array();
foreach ($indexed as $column) {
@@ -1509,6 +1449,22 @@ class PMA_Table
}
/**
+ * Get meta info for fields in table
+ *
+ * @return mixed
+ */
+ public function getColumnsMeta()
+ {
+ $move_columns_sql_query = sprintf(
+ 'SELECT * FROM %s.%s LIMIT 1',
+ PMA_Util::backquote($this->_db_name),
+ PMA_Util::backquote($this->_name)
+ );
+ $move_columns_sql_result = $this->_dbi->tryQuery($move_columns_sql_query);
+ return $this->_dbi->getFieldsMeta($move_columns_sql_result);
+ }
+
+ /**
* Return UI preferences for this table from phpMyAdmin database.
*
* @return array
@@ -1522,10 +1478,10 @@ class PMA_Table
// Read from phpMyAdmin database
$sql_query = " SELECT `prefs` FROM " . $pma_table
. " WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'"
- . " AND `db_name` = '" . PMA_Util::sqlAddSlashes($this->db_name) . "'"
- . " AND `table_name` = '" . PMA_Util::sqlAddSlashes($this->name) . "'";
+ . " AND `db_name` = '" . PMA_Util::sqlAddSlashes($this->_db_name) . "'"
+ . " AND `table_name` = '" . PMA_Util::sqlAddSlashes($this->_name) . "'";
- $row = $GLOBALS['dbi']->fetchArray(PMA_queryAsControlUser($sql_query));
+ $row = $this->_dbi->fetchArray(PMA_queryAsControlUser($sql_query));
if (isset($row[0])) {
return json_decode($row[0], true);
} else {
@@ -1544,16 +1500,16 @@ class PMA_Table
$pma_table = PMA_Util::backquote($cfgRelation['db']) . "."
. PMA_Util::backquote($cfgRelation['table_uiprefs']);
- $secureDbName = PMA_Util::sqlAddSlashes($this->db_name);
+ $secureDbName = PMA_Util::sqlAddSlashes($this->_db_name);
$username = $GLOBALS['cfg']['Server']['user'];
$sql_query = " REPLACE INTO " . $pma_table
. " (username, db_name, table_name, prefs) VALUES ('"
. $username . "', '" . $secureDbName
- . "', '" . PMA_Util::sqlAddSlashes($this->name) . "', '"
+ . "', '" . PMA_Util::sqlAddSlashes($this->_name) . "', '"
. PMA_Util::sqlAddSlashes(json_encode($this->uiprefs)) . "')";
- $success = $GLOBALS['dbi']->tryQuery($sql_query, $GLOBALS['controllink']);
+ $success = $this->_dbi->tryQuery($sql_query, $GLOBALS['controllink']);
if (!$success) {
$message = PMA_Message::error(
@@ -1562,7 +1518,7 @@ class PMA_Table
$message->addMessage('<br /><br />');
$message->addMessage(
PMA_Message::rawError(
- $GLOBALS['dbi']->getError($GLOBALS['controllink'])
+ $this->_dbi->getError($GLOBALS['controllink'])
)
);
return $message;
@@ -1571,7 +1527,7 @@ class PMA_Table
// Remove some old rows in table_uiprefs if it exceeds the configured
// maximum rows
$sql_query = 'SELECT COUNT(*) FROM ' . $pma_table;
- $rows_count = $GLOBALS['dbi']->fetchValue($sql_query);
+ $rows_count = $this->_dbi->fetchValue($sql_query);
$max_rows = $GLOBALS['cfg']['Server']['MaxTableUiprefs'];
if ($rows_count > $max_rows) {
$num_rows_to_delete = $rows_count - $max_rows;
@@ -1579,21 +1535,24 @@ class PMA_Table
= ' DELETE FROM ' . $pma_table .
' ORDER BY last_update ASC' .
' LIMIT ' . $num_rows_to_delete;
- $success = $GLOBALS['dbi']->tryQuery(
+ $success = $this->_dbi->tryQuery(
$sql_query, $GLOBALS['controllink']
);
if (!$success) {
$message = PMA_Message::error(
sprintf(
- __('Failed to cleanup table UI preferences (see $cfg[\'Servers\'][$i][\'MaxTableUiprefs\'] %s)'),
+ __(
+ 'Failed to cleanup table UI preferences (see ' .
+ '$cfg[\'Servers\'][$i][\'MaxTableUiprefs\'] %s)'
+ ),
PMA_Util::showDocu('config', 'cfg_Servers_MaxTableUiprefs')
)
);
$message->addMessage('<br /><br />');
$message->addMessage(
PMA_Message::rawError(
- $GLOBALS['dbi']->getError($GLOBALS['controllink'])
+ $this->_dbi->getError($GLOBALS['controllink'])
)
);
print_r($message);
@@ -1617,15 +1576,15 @@ class PMA_Table
$server_id = $GLOBALS['server'];
// set session variable if it's still undefined
- if (! isset($_SESSION['tmpval']['table_uiprefs'][$server_id][$this->db_name][$this->name])) {
+ if (!isset($_SESSION['tmpval']['table_uiprefs'][$server_id][$this->_db_name][$this->_name])) {
// check whether we can get from pmadb
- $_SESSION['tmpval']['table_uiprefs'][$server_id][$this->db_name]
- [$this->name] = $cfgRelation['uiprefswork']
+ $_SESSION['tmpval']['table_uiprefs'][$server_id][$this->_db_name]
+ [$this->_name] = $cfgRelation['uiprefswork']
? $this->getUiPrefsFromDb()
: array();
}
$this->uiprefs =& $_SESSION['tmpval']['table_uiprefs'][$server_id]
- [$this->db_name][$this->name];
+ [$this->_db_name][$this->_name];
}
/**
@@ -1645,58 +1604,58 @@ class PMA_Table
if (! isset($this->uiprefs)) {
$this->loadUiPrefs();
}
+
// do checking based on property
if ($property == self::PROP_SORTED_COLUMN) {
- if (isset($this->uiprefs[$property])) {
- if (! isset($_REQUEST['discard_remembered_sort'])) {
- // check if the column name exists in this table
- $tmp = explode(' ', $this->uiprefs[$property]);
- $colname = $tmp[0];
- //remove backquoting from colname
- $colname = str_replace('`', '', $colname);
- //get the available column name without backquoting
- $avail_columns = $this->getColumns(false);
-
- foreach ($avail_columns as $each_col) {
- // check if $each_col ends with $colname
- if (substr_compare(
- $each_col,
- $colname,
- /*overload*/mb_strlen($each_col)
- - /*overload*/mb_strlen($colname)
- ) === 0
- ) {
- return $this->uiprefs[$property];
- }
+ if (!isset($this->uiprefs[$property])) {
+ return false;
+ }
+
+ if (!isset($_REQUEST['discard_remembered_sort'])) {
+ // check if the column name exists in this table
+ $tmp = explode(' ', $this->uiprefs[$property]);
+ $colname = $tmp[0];
+ //remove backquoting from colname
+ $colname = str_replace('`', '', $colname);
+ //get the available column name without backquoting
+ $avail_columns = $this->getColumns(false);
+
+ foreach ($avail_columns as $each_col) {
+ // check if $each_col ends with $colname
+ if (substr_compare(
+ $each_col,
+ $colname,
+ /*overload*/mb_strlen($each_col)
+ - /*overload*/mb_strlen($colname)
+ ) === 0
+ ) {
+ return $this->uiprefs[$property];
}
}
- // remove the property, since it no longer exists in database
- $this->removeUiProp(self::PROP_SORTED_COLUMN);
- return false;
- } else {
- return false;
}
- } elseif ($property == self::PROP_COLUMN_ORDER
+ // remove the property, since it no longer exists in database
+ $this->removeUiProp(self::PROP_SORTED_COLUMN);
+ return false;
+ }
+
+ if ($property == self::PROP_COLUMN_ORDER
|| $property == self::PROP_COLUMN_VISIB
) {
- if (! PMA_Table::isView($this->db_name, $this->name)
- && isset($this->uiprefs[$property])
- ) {
- // check if the table has not been modified
- if (self::sGetStatusInfo(
- $this->db_name,
- $this->name, 'Create_time'
- ) == $this->uiprefs['CREATE_TIME']) {
- return $this->uiprefs[$property];
- } else {
- // remove the property, since the table has been modified
- $this->removeUiProp(self::PROP_COLUMN_ORDER);
- return false;
- }
- } else {
+ if ($this->isView() || !isset($this->uiprefs[$property])) {
return false;
}
+
+ // check if the table has not been modified
+ if ($this->getStatusInfo('Create_time') == $this->uiprefs['CREATE_TIME']
+ ) {
+ return $this->uiprefs[$property];
+ }
+
+ // remove the property, since the table has been modified
+ $this->removeUiProp(self::PROP_COLUMN_ORDER);
+ return false;
}
+
// default behaviour for other property:
return isset($this->uiprefs[$property]) ? $this->uiprefs[$property] : false;
}
@@ -1723,15 +1682,11 @@ class PMA_Table
$this->loadUiPrefs();
}
// we want to save the create time if the property is PROP_COLUMN_ORDER
- if (! PMA_Table::isView($this->db_name, $this->name)
+ if (! $this->isView()
&& ($property == self::PROP_COLUMN_ORDER
|| $property == self::PROP_COLUMN_VISIB)
) {
- $curr_create_time = self::sGetStatusInfo(
- $this->db_name,
- $this->name,
- 'CREATE_TIME'
- );
+ $curr_create_time = $this->getStatusInfo('CREATE_TIME');
if (isset($table_create_time)
&& $table_create_time == $curr_create_time
) {
@@ -1742,7 +1697,11 @@ class PMA_Table
// so don't save
return PMA_Message::error(
sprintf(
- __('Cannot save UI property "%s". The changes made will not be persistent after you refresh this page. Please check if the table structure has been changed.'),
+ __(
+ 'Cannot save UI property "%s". The changes made will ' .
+ 'not be persistent after you refresh this page. ' .
+ 'Please check if the table structure has been changed.'
+ ),
$property
)
);
@@ -1774,11 +1733,9 @@ class PMA_Table
if (isset($this->uiprefs[$property])) {
unset($this->uiprefs[$property]);
- $cfgRelation = PMA_getRelationsParam();
// check if pmadb is set
- if (/*overload*/mb_strlen($cfgRelation['db'])
- && /*overload*/mb_strlen($cfgRelation['table_uiprefs'])
- ) {
+ $cfgRelation = PMA_getRelationsParam();
+ if ($cfgRelation['uiprefswork']) {
return $this->saveUiprefsToDb();
}
}
@@ -1798,11 +1755,651 @@ class PMA_Table
foreach ($columns as $column) {
$temp = explode('.', $column);
$column_name = $temp[2];
- if (PMA_SQP_isKeyWord($column_name)) {
+ if (SqlParser\Context::isKeyword($column_name, true)) {
$return[] = $column_name;
}
}
return $return;
}
+
+ /**
+ * Function to get the name and type of the columns of a table
+ *
+ * @return array
+ */
+ public function getNameAndTypeOfTheColumns()
+ {
+ $columns = array();
+ foreach ($this->_dbi->getColumnsFull(
+ $this->_db_name, $this->_name
+ ) as $row) {
+ if (preg_match('@^(set|enum)\((.+)\)$@i', $row['Type'], $tmp)) {
+ $tmp[2] = /*overload*/
+ mb_substr(
+ preg_replace('@([^,])\'\'@', '\\1\\\'', ',' . $tmp[2]), 1
+ );
+ $columns[$row['Field']] = $tmp[1] . '('
+ . str_replace(',', ', ', $tmp[2]) . ')';
+ } else {
+ $columns[$row['Field']] = $row['Type'];
+ }
+ }
+ return $columns;
+ }
+
+ /**
+ * Get index with index name
+ *
+ * @param string $index Index name
+ *
+ * @return PMA_Index
+ */
+ public function getIndex($index)
+ {
+ return PMA_Index::singleton($this->_db_name, $this->_name, $index);
+ }
+
+ /**
+ * Function to get the sql query for index creation or edit
+ *
+ * @param PMA_Index $index current index
+ * @param bool &$error whether error occurred or not
+ *
+ * @return string
+ */
+ public function getSqlQueryForIndexCreateOrEdit($index, &$error)
+ {
+ // $sql_query is the one displayed in the query box
+ $sql_query = sprintf(
+ 'ALTER TABLE %s.%s',
+ PMA_Util::backquote($this->_db_name),
+ PMA_Util::backquote($this->_name)
+ );
+
+ // Drops the old index
+ if (! empty($_REQUEST['old_index'])) {
+ if ($_REQUEST['old_index'] == 'PRIMARY') {
+ $sql_query .= ' DROP PRIMARY KEY,';
+ } else {
+ $sql_query .= sprintf(
+ ' DROP INDEX %s,',
+ PMA_Util::backquote($_REQUEST['old_index'])
+ );
+ }
+ } // end if
+
+ // Builds the new one
+ switch ($index->getChoice()) {
+ case 'PRIMARY':
+ if ($index->getName() == '') {
+ $index->setName('PRIMARY');
+ } elseif ($index->getName() != 'PRIMARY') {
+ $error = PMA_Message::error(
+ __('The name of the primary key must be "PRIMARY"!')
+ );
+ }
+ $sql_query .= ' ADD PRIMARY KEY';
+ break;
+ case 'FULLTEXT':
+ case 'UNIQUE':
+ case 'INDEX':
+ case 'SPATIAL':
+ if ($index->getName() == 'PRIMARY') {
+ $error = PMA_Message::error(
+ __('Can\'t rename index to PRIMARY!')
+ );
+ }
+ $sql_query .= sprintf(
+ ' ADD %s ',
+ $index->getChoice()
+ );
+ if ($index->getName()) {
+ $sql_query .= PMA_Util::backquote($index->getName());
+ }
+ break;
+ } // end switch
+
+ $index_fields = array();
+ foreach ($index->getColumns() as $key => $column) {
+ $index_fields[$key] = PMA_Util::backquote($column->getName());
+ if ($column->getSubPart()) {
+ $index_fields[$key] .= '(' . $column->getSubPart() . ')';
+ }
+ } // end while
+
+ if (empty($index_fields)) {
+ $error = PMA_Message::error(__('No index parts defined!'));
+ } else {
+ $sql_query .= ' (' . implode(', ', $index_fields) . ')';
+ }
+
+ $keyBlockSizes = $index->getKeyBlockSize();
+ if (! empty($keyBlockSizes)) {
+ $sql_query .= sprintf(
+ ' KEY_BLOCK_SIZE = ',
+ PMA_Util::sqlAddSlashes($keyBlockSizes)
+ );
+ }
+
+ // specifying index type is allowed only for primary, unique and index only
+ $type = $index->getType();
+ if ($index->getChoice() != 'SPATIAL'
+ && $index->getChoice() != 'FULLTEXT'
+ && in_array($type, PMA_Index::getIndexTypes())
+ ) {
+ $sql_query .= ' USING ' . $type;
+ }
+
+ $parser = $index->getParser();
+ if ($index->getChoice() == 'FULLTEXT' && ! empty($parser)) {
+ $sql_query .= ' WITH PARSER ' . PMA_Util::sqlAddSlashes($parser);
+ }
+
+ $comment = $index->getComment();
+ if (! empty($comment)) {
+ $sql_query .= sprintf(
+ " COMMENT '%s'",
+ PMA_Util::sqlAddSlashes($comment)
+ );
+ }
+
+ $sql_query .= ';';
+
+ return $sql_query;
+ }
+
+ /**
+ * Function to handle update for display field
+ *
+ * @param string $disp current display field
+ * @param string $display_field display field
+ * @param array $cfgRelation configuration relation
+ *
+ * @return boolean True on update succeed or False on failure
+ */
+ public function updateDisplayField($disp, $display_field, $cfgRelation)
+ {
+ $upd_query = false;
+ if ($disp) {
+ if ($display_field == '') {
+ $upd_query = 'DELETE FROM '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($cfgRelation['table_info'])
+ . ' WHERE db_name = \''
+ . PMA_Util::sqlAddSlashes($this->db_name) . '\''
+ . ' AND table_name = \''
+ . PMA_Util::sqlAddSlashes($this->name) . '\'';
+ } elseif ($disp != $display_field) {
+ $upd_query = 'UPDATE '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($cfgRelation['table_info'])
+ . ' SET display_field = \''
+ . PMA_Util::sqlAddSlashes($display_field) . '\''
+ . ' WHERE db_name = \''
+ . PMA_Util::sqlAddSlashes($this->db_name) . '\''
+ . ' AND table_name = \''
+ . PMA_Util::sqlAddSlashes($this->name) . '\'';
+ }
+ } elseif ($display_field != '') {
+ $upd_query = 'INSERT INTO '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($cfgRelation['table_info'])
+ . '(db_name, table_name, display_field) VALUES('
+ . '\'' . PMA_Util::sqlAddSlashes($this->_db_name) . '\','
+ . '\'' . PMA_Util::sqlAddSlashes($this->_name) . '\','
+ . '\'' . PMA_Util::sqlAddSlashes($display_field) . '\')';
+ }
+
+ if ($upd_query) {
+ $this->_dbi->query(
+ $upd_query,
+ $GLOBALS['controllink'],
+ 0,
+ false
+ );
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Function to get update query for updating internal relations
+ *
+ * @param array $multi_edit_columns_name multi edit column names
+ * @param array $destination_db destination tables
+ * @param array $destination_table destination tables
+ * @param array $destination_column destination columns
+ * @param array $cfgRelation configuration relation
+ * @param array|null $existrel db, table, column
+ *
+ * @return boolean
+ */
+ public function updateInternalRelations($multi_edit_columns_name,
+ $destination_db, $destination_table, $destination_column,
+ $cfgRelation, $existrel
+ ) {
+ $updated = false;
+ foreach ($destination_db as $master_field_md5 => $foreign_db) {
+ $upd_query = null;
+ // Map the fieldname's md5 back to its real name
+ $master_field = $multi_edit_columns_name[$master_field_md5];
+ $foreign_table = $destination_table[$master_field_md5];
+ $foreign_field = $destination_column[$master_field_md5];
+ if (! empty($foreign_db)
+ && ! empty($foreign_table)
+ && ! empty($foreign_field)
+ ) {
+ if (! isset($existrel[$master_field])) {
+ $upd_query = 'INSERT INTO '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($cfgRelation['relation'])
+ . '(master_db, master_table, master_field, foreign_db,'
+ . ' foreign_table, foreign_field)'
+ . ' values('
+ . '\'' . PMA_Util::sqlAddSlashes($this->_db_name) . '\', '
+ . '\'' . PMA_Util::sqlAddSlashes($this->_name) . '\', '
+ . '\'' . PMA_Util::sqlAddSlashes($master_field) . '\', '
+ . '\'' . PMA_Util::sqlAddSlashes($foreign_db) . '\', '
+ . '\'' . PMA_Util::sqlAddSlashes($foreign_table) . '\','
+ . '\'' . PMA_Util::sqlAddSlashes($foreign_field) . '\')';
+
+ } elseif ($existrel[$master_field]['foreign_db'] != $foreign_db
+ || $existrel[$master_field]['foreign_table'] != $foreign_table
+ || $existrel[$master_field]['foreign_field'] != $foreign_field
+ ) {
+ $upd_query = 'UPDATE '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($cfgRelation['relation'])
+ . ' SET foreign_db = \''
+ . PMA_Util::sqlAddSlashes($foreign_db) . '\', '
+ . ' foreign_table = \''
+ . PMA_Util::sqlAddSlashes($foreign_table) . '\', '
+ . ' foreign_field = \''
+ . PMA_Util::sqlAddSlashes($foreign_field) . '\' '
+ . ' WHERE master_db = \''
+ . PMA_Util::sqlAddSlashes($this->_db_name) . '\''
+ . ' AND master_table = \''
+ . PMA_Util::sqlAddSlashes($this->_name) . '\''
+ . ' AND master_field = \''
+ . PMA_Util::sqlAddSlashes($master_field) . '\'';
+ } // end if... else....
+ } elseif (isset($existrel[$master_field])) {
+ $upd_query = 'DELETE FROM '
+ . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ . '.' . PMA_Util::backquote($cfgRelation['relation'])
+ . ' WHERE master_db = \''
+ . PMA_Util::sqlAddSlashes($this->db_name) . '\''
+ . ' AND master_table = \''
+ . PMA_Util::sqlAddSlashes($this->name) . '\''
+ . ' AND master_field = \''
+ . PMA_Util::sqlAddSlashes($master_field) . '\'';
+ } // end if... else....
+
+ if (isset($upd_query)) {
+ $this->_dbi->query(
+ $upd_query,
+ $GLOBALS['controllink'],
+ 0,
+ false
+ );
+ $updated = true;
+ }
+ }
+ return $updated;
+ }
+
+ /**
+ * Function to handle foreign key updates
+ *
+ * @param array $destination_foreign_db destination foreign database
+ * @param array $multi_edit_columns_name multi edit column names
+ * @param array $destination_foreign_table destination foreign table
+ * @param array $destination_foreign_column destination foreign column
+ * @param array $options_array options array
+ * @param string $table current table
+ * @param array $existrel_foreign db, table, column
+ *
+ * @return array
+ */
+ public function updateForeignKeys($destination_foreign_db,
+ $multi_edit_columns_name, $destination_foreign_table,
+ $destination_foreign_column, $options_array, $table, $existrel_foreign
+ ) {
+ $html_output = '';
+ $preview_sql_data = '';
+ $display_query = '';
+ $seen_error = false;
+
+ foreach ($destination_foreign_db as $master_field_md5 => $foreign_db) {
+ $create = false;
+ $drop = false;
+
+ // Map the fieldname's md5 back to its real name
+ $master_field = $multi_edit_columns_name[$master_field_md5];
+
+ $foreign_table = $destination_foreign_table[$master_field_md5];
+ $foreign_field = $destination_foreign_column[$master_field_md5];
+
+ if (isset($existrel_foreign[$master_field_md5]['ref_db_name'])) {
+ $ref_db_name = $existrel_foreign[$master_field_md5]['ref_db_name'];
+ } else {
+ $ref_db_name = $GLOBALS['db'];
+ }
+
+ $empty_fields = false;
+ foreach ($master_field as $key => $one_field) {
+ if ((! empty($one_field) && empty($foreign_field[$key]))
+ || (empty($one_field) && ! empty($foreign_field[$key]))
+ ) {
+ $empty_fields = true;
+ }
+
+ if (empty($one_field) && empty($foreign_field[$key])) {
+ unset($master_field[$key]);
+ unset($foreign_field[$key]);
+ }
+ }
+
+ if (! empty($foreign_db)
+ && ! empty($foreign_table)
+ && ! $empty_fields
+ ) {
+ if (isset($existrel_foreign[$master_field_md5])) {
+ $constraint_name
+ = $existrel_foreign[$master_field_md5]['constraint'];
+ $on_delete = !empty(
+ $existrel_foreign[$master_field_md5]['on_delete']
+ )
+ ? $existrel_foreign[$master_field_md5]['on_delete']
+ : 'RESTRICT';
+ $on_update = ! empty(
+ $existrel_foreign[$master_field_md5]['on_update']
+ )
+ ? $existrel_foreign[$master_field_md5]['on_update']
+ : 'RESTRICT';
+
+ if ($ref_db_name != $foreign_db
+ || $existrel_foreign[$master_field_md5]['ref_table_name'] != $foreign_table
+ || $existrel_foreign[$master_field_md5]['ref_index_list'] != $foreign_field
+ || $existrel_foreign[$master_field_md5]['index_list'] != $master_field
+ || $_REQUEST['constraint_name'][$master_field_md5] != $constraint_name
+ || ($_REQUEST['on_delete'][$master_field_md5] != $on_delete)
+ || ($_REQUEST['on_update'][$master_field_md5] != $on_update)
+ ) {
+ // another foreign key is already defined for this field
+ // or an option has been changed for ON DELETE or ON UPDATE
+ $drop = true;
+ $create = true;
+ } // end if... else....
+ } else {
+ // no key defined for this field(s)
+ $create = true;
+ }
+ } elseif (isset($existrel_foreign[$master_field_md5])) {
+ $drop = true;
+ } // end if... else....
+
+ $tmp_error_drop = false;
+ if ($drop) {
+ $drop_query = 'ALTER TABLE ' . PMA_Util::backquote($table)
+ . ' DROP FOREIGN KEY ' . PMA_Util::backquote($existrel_foreign[$master_field_md5]['constraint']) . ';';
+
+ if (! isset($_REQUEST['preview_sql'])) {
+ $display_query .= $drop_query . "\n";
+ $this->_dbi->tryQuery($drop_query);
+ $tmp_error_drop = $this->_dbi->getError();
+
+ if (! empty($tmp_error_drop)) {
+ $seen_error = true;
+ $html_output .= PMA_Util::mysqlDie(
+ $tmp_error_drop, $drop_query, false, '', false
+ );
+ continue;
+ }
+ } else {
+ $preview_sql_data .= $drop_query . "\n";
+ }
+ }
+ $tmp_error_create = false;
+ if (!$create) {
+ continue;
+ }
+
+ $create_query = $this->_getSQLToCreateForeignKey(
+ $table, $master_field, $foreign_db, $foreign_table, $foreign_field,
+ $_REQUEST['constraint_name'][$master_field_md5],
+ $options_array[$_REQUEST['on_delete'][$master_field_md5]],
+ $options_array[$_REQUEST['on_update'][$master_field_md5]]
+ );
+
+ if (! isset($_REQUEST['preview_sql'])) {
+ $display_query .= $create_query . "\n";
+ $this->_dbi->tryQuery($create_query);
+ $tmp_error_create = $this->_dbi->getError();
+ if (! empty($tmp_error_create)) {
+ $seen_error = true;
+
+ if (substr($tmp_error_create, 1, 4) == '1005') {
+ $message = PMA_Message::error(
+ __(
+ 'Error creating foreign key on %1$s (check data ' .
+ 'types)'
+ )
+ );
+ $message->addParam(implode(', ', $master_field));
+ $html_output .= $message->getDisplay();
+ } else {
+ $html_output .= PMA_Util::mysqlDie(
+ $tmp_error_create, $create_query, false, '', false
+ );
+ }
+ $html_output .= PMA_Util::showMySQLDocu(
+ 'InnoDB_foreign_key_constraints'
+ ) . "\n";
+ }
+ } else {
+ $preview_sql_data .= $create_query . "\n";
+ }
+
+ // this is an alteration and the old constraint has been dropped
+ // without creation of a new one
+ if ($drop && $create && empty($tmp_error_drop)
+ && ! empty($tmp_error_create)
+ ) {
+ // a rollback may be better here
+ $sql_query_recreate = '# Restoring the dropped constraint...' . "\n";
+ $sql_query_recreate .= $this->_getSQLToCreateForeignKey(
+ $table,
+ $master_field,
+ $existrel_foreign[$master_field_md5]['ref_db_name'],
+ $existrel_foreign[$master_field_md5]['ref_table_name'],
+ $existrel_foreign[$master_field_md5]['ref_index_list'],
+ $existrel_foreign[$master_field_md5]['constraint'],
+ $options_array[$existrel_foreign[$master_field_md5]['on_delete']],
+ $options_array[$existrel_foreign[$master_field_md5]['on_update']]
+ );
+ if (! isset($_REQUEST['preview_sql'])) {
+ $display_query .= $sql_query_recreate . "\n";
+ $this->_dbi->tryQuery($sql_query_recreate);
+ } else {
+ $preview_sql_data .= $sql_query_recreate;
+ }
+ }
+ } // end foreach
+
+ return array(
+ $html_output,
+ $preview_sql_data,
+ $display_query,
+ $seen_error
+ );
+ }
+
+ /**
+ * Returns the SQL query for foreign key constraint creation
+ *
+ * @param string $table table name
+ * @param array $field field names
+ * @param string $foreignDb foreign database name
+ * @param string $foreignTable foreign table name
+ * @param array $foreignField foreign field names
+ * @param string $name name of the constraint
+ * @param string $onDelete on delete action
+ * @param string $onUpdate on update action
+ *
+ * @return string SQL query for foreign key constraint creation
+ */
+ private function _getSQLToCreateForeignKey(
+ $table,
+ $field,
+ $foreignDb,
+ $foreignTable,
+ $foreignField,
+ $name = null,
+ $onDelete = null,
+ $onUpdate = null
+ ) {
+ $sql_query = 'ALTER TABLE ' . PMA_Util::backquote($table) . ' ADD ';
+ // if user entered a constraint name
+ if (! empty($name)) {
+ $sql_query .= ' CONSTRAINT ' . PMA_Util::backquote($name);
+ }
+
+ foreach ($field as $key => $one_field) {
+ $field[$key] = PMA_Util::backquote($one_field);
+ }
+ foreach ($foreignField as $key => $one_field) {
+ $foreignField[$key] = PMA_Util::backquote($one_field);
+ }
+ $sql_query .= ' FOREIGN KEY (' . implode(', ', $field) . ')'
+ . ' REFERENCES ' . PMA_Util::backquote($foreignDb)
+ . '.' . PMA_Util::backquote($foreignTable)
+ . '(' . implode(', ', $foreignField) . ')';
+
+ if (! empty($onDelete)) {
+ $sql_query .= ' ON DELETE ' . $onDelete;
+ }
+ if (! empty($onUpdate)) {
+ $sql_query .= ' ON UPDATE ' . $onUpdate;
+ }
+ $sql_query .= ';';
+
+ return $sql_query;
+ }
+
+ /**
+ * Returns the generation expression for virtual columns
+ *
+ * @param string $column name of the column
+ *
+ * @return array|boolean associative array of column name and their expressions
+ * or false on failure
+ */
+ public function getColumnGenerationExpression($column = null)
+ {
+ $serverType = PMA_Util::getServerType();
+ if ($serverType == 'MySQL'
+ && PMA_MYSQL_INT_VERSION > 50705
+ && ! $GLOBALS['cfg']['Server']['DisableIS']
+ ) {
+ $sql
+ = "SELECT
+ `COLUMN_NAME` AS `Field`,
+ `GENERATION_EXPRESSION` AS `Expression`
+ FROM
+ `information_schema`.`COLUMNS`
+ WHERE
+ `TABLE_SCHEMA` = '" . PMA_Util::sqlAddSlashes($this->_db_name) . "'
+ AND `TABLE_NAME` = '" . PMA_Util::sqlAddSlashes($this->_name) . "'";
+ if ($column != null) {
+ $sql .= " AND `COLUMN_NAME` = '" . PMA_Util::sqlAddSlashes($column)
+ . "'";
+ }
+ $columns = $this->_dbi->fetchResult($sql, 'Field', 'Expression');
+ return $columns;
+ }
+
+ $createTable = $this->showCreate();
+ if (!$createTable) {
+ return false;
+ }
+
+ $parser = new SqlParser\Parser($createTable);
+ /**
+ * @var SqlParser\Statements\CreateStatement $stmt
+ */
+ $stmt = $parser->statements[0];
+ $fields = SqlParser\Utils\Table::getFields($stmt);
+ if ($column != null) {
+ $expression = isset($fields[$column]['expr']) ?
+ substr($fields[$column]['expr'], 1, -1) : '';
+ return array($column => $expression);
+ }
+
+ $ret = array();
+ foreach ($fields as $field => $options) {
+ if (isset($options['expr'])) {
+ $ret[$field] = substr($options['expr'], 1, -1);
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Returns the CREATE statement for this table
+ *
+ * @return mixed
+ */
+ public function showCreate()
+ {
+ return $this->_dbi->fetchValue(
+ 'SHOW CREATE TABLE ' . PMA_Util::backquote($this->_db_name) . '.'
+ . PMA_Util::backquote($this->_name),
+ 0, 1
+ );
+ }
+
+ /**
+ * Returns the real row count for a table
+ *
+ * @return number
+ */
+ function getRealRowCountTable()
+ {
+ // SQL query to get row count for a table.
+ $result = $this->_dbi->fetchSingleRow(
+ sprintf(
+ 'SELECT COUNT(*) AS %s FROM %s.%s',
+ PMA_Util::backquote('row_count'),
+ PMA_Util::backquote($this->_db_name),
+ PMA_Util::backquote($this->_name)
+ )
+ );
+ return $result['row_count'];
+ }
+
+ /**
+ * Get columns with indexes
+ *
+ * @param int $types types bitmask
+ *
+ * @return array an array of columns
+ */
+ function getColumnsWithIndex($types)
+ {
+ $columns_with_index = array();
+ foreach (
+ PMA_Index::getFromTableByChoice(
+ $this->_name,
+ $this->_db_name,
+ $types
+ ) as $index
+ ) {
+ $columns = $index->getColumns();
+ foreach ($columns as $column_name => $dummy) {
+ $columns_with_index[] = $column_name;
+ }
+ }
+ return $columns_with_index;
+ }
}
-?>
diff --git a/libraries/TableSearch.class.php b/libraries/TableSearch.class.php
deleted file mode 100644
index bda58fbc59..0000000000
--- a/libraries/TableSearch.class.php
+++ /dev/null
@@ -1,1587 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Handles Table search and Zoom search
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Class to handle normal-search
- * and zoom-search in a table
- *
- * @package PhpMyAdmin
- */
-class PMA_TableSearch
-{
- /**
- * Database name
- *
- * @access private
- * @var string
- */
- private $_db;
- /**
- * Table name
- *
- * @access private
- * @var string
- */
- private $_table;
- /**
- * Normal search or Zoom search
- *
- * @access private
- * @var string
- */
- private $_searchType;
- /**
- * Names of columns
- *
- * @access private
- * @var array
- */
- private $_columnNames;
- /**
- * Types of columns
- *
- * @access private
- * @var array
- */
- private $_columnTypes;
- /**
- * Collations of columns
- *
- * @access private
- * @var array
- */
- private $_columnCollations;
- /**
- * Null Flags of columns
- *
- * @access private
- * @var array
- */
- private $_columnNullFlags;
- /**
- * Whether a geometry column is present
- *
- * @access private
- * @var boolean
- */
- private $_geomColumnFlag;
- /**
- * Foreign Keys
- *
- * @access private
- * @var array
- */
- private $_foreigners;
-
-
- /**
- * Public Constructor
- *
- * @param string $db Database name
- * @param string $table Table name
- * @param string $searchType Whether normal or zoom search
- */
- public function __construct($db, $table, $searchType)
- {
- $this->_db = $db;
- $this->_table = $table;
- $this->_searchType = $searchType;
- $this->_columnNames = array();
- $this->_columnNullFlags = array();
- $this->_columnTypes = array();
- $this->_columnCollations = array();
- $this->_geomColumnFlag = false;
- $this->_foreigners = array();
- // Loads table's information
- $this->_loadTableInfo();
- }
-
- /**
- * Returns Column names array
- *
- * @return array column names
- */
- public function getColumnNames()
- {
- return $this->_columnNames;
- }
-
- /**
- * Gets all the columns of a table along with their types, collations
- * and whether null or not.
- *
- * @return void
- */
- private function _loadTableInfo()
- {
- // Gets the list and number of columns
- $columns = $GLOBALS['dbi']->getColumns(
- $this->_db, $this->_table, null, true
- );
- // Get details about the geometry functions
- $geom_types = PMA_Util::getGISDatatypes();
-
- foreach ($columns as $row) {
- // set column name
- $this->_columnNames[] = $row['Field'];
-
- $type = $row['Type'];
- // check whether table contains geometric columns
- if (in_array($type, $geom_types)) {
- $this->_geomColumnFlag = true;
- }
- // reformat mysql query output
- if (strncasecmp($type, 'set', 3) == 0
- || strncasecmp($type, 'enum', 4) == 0
- ) {
- $type = str_replace(',', ', ', $type);
- } else {
- // strip the "BINARY" attribute, except if we find "BINARY(" because
- // this would be a BINARY or VARBINARY column type
- if (! preg_match('@BINARY[\(]@i', $type)) {
- $type = preg_replace('@BINARY@i', '', $type);
- }
- $type = preg_replace('@ZEROFILL@i', '', $type);
- $type = preg_replace('@UNSIGNED@i', '', $type);
- $type = /*overload*/mb_strtolower($type);
- }
- if (empty($type)) {
- $type = '&nbsp;';
- }
- $this->_columnTypes[] = $type;
- $this->_columnNullFlags[] = $row['Null'];
- $this->_columnCollations[]
- = ! empty($row['Collation']) && $row['Collation'] != 'NULL'
- ? $row['Collation']
- : '';
- } // end for
-
- // Retrieve foreign keys
- $this->_foreigners = PMA_getForeigners($this->_db, $this->_table);
- }
-
- /**
- * Sets the table header for displaying a table in query-by-example format.
- *
- * @return string HTML content, the tags and content for table header
- */
- private function _getTableHeader()
- {
- // Display the Function column only if there is at least one geometry column
- $func = '';
- if ($this->_geomColumnFlag) {
- $func = '<th>' . __('Function') . '</th>';
- }
-
- return '<thead>
- <tr>' . $func . '<th>' . __('Column') . '</th>
- <th>' . __('Type') . '</th>
- <th>' . __('Collation') . '</th>
- <th>' . __('Operator') . '</th>
- <th>' . __('Value') . '</th>
- </tr>
- </thead>';
- }
-
- /**
- * Returns an array with necessary configurations to create
- * sub-tabs in the table_select page.
- *
- * @return array Array containing configuration (icon, text, link, id, args)
- * of sub-tabs
- */
- private function _getSubTabs()
- {
- $subtabs = array();
- $subtabs['search']['icon'] = 'b_search.png';
- $subtabs['search']['text'] = __('Table search');
- $subtabs['search']['link'] = 'tbl_select.php';
- $subtabs['search']['id'] = 'tbl_search_id';
- $subtabs['search']['args']['pos'] = 0;
-
- $subtabs['zoom']['icon'] = 'b_props.png';
- $subtabs['zoom']['link'] = 'tbl_zoom_select.php';
- $subtabs['zoom']['text'] = __('Zoom search');
- $subtabs['zoom']['id'] = 'zoom_search_id';
-
- $subtabs['replace']['icon'] = 'b_find_replace.png';
- $subtabs['replace']['link'] = 'tbl_find_replace.php';
- $subtabs['replace']['text'] = __('Find and replace');
- $subtabs['replace']['id'] = 'find_replace_id';
-
- return $subtabs;
- }
-
- /**
- * Provides html elements for search criteria inputbox
- * in case the column's type is geometrical
- *
- * @param int $column_index Column's index
- * @param bool $in_fbs Whether we are in 'function based search'
- *
- * @return string HTML elements.
- */
- private function _getGeometricalInputBox($column_index, $in_fbs)
- {
- $html_output = '<input type="text" name="criteriaValues['
- . $column_index . ']"'
- . ' size="40" class="textfield" id="field_' . $column_index . '" />';
-
- if ($in_fbs) {
- $edit_url = 'gis_data_editor.php' . PMA_URL_getCommon();
- $edit_str = PMA_Util::getIcon('b_edit.png', __('Edit/Insert'));
- $html_output .= '<span class="open_search_gis_editor">';
- $html_output .= PMA_Util::linkOrButton(
- $edit_url, $edit_str, array(), false, false, '_blank'
- );
- $html_output .= '</span>';
- }
- return $html_output;
- }
-
- /**
- * Provides html elements for search criteria inputbox
- * in case the column is a Foreign Key
- *
- * @param array $foreignData Foreign keys data
- * @param string $column_name Column name
- * @param int $column_index Column index
- * @param array $titles Selected title
- * @param int $foreignMaxLimit Max limit of displaying foreign elements
- * @param array $criteriaValues Array of search criteria inputs
- * @param string $column_id Column's inputbox's id
- *
- * @return string HTML elements.
- */
- private function _getForeignKeyInputBox($foreignData, $column_name,
- $column_index, $titles, $foreignMaxLimit, $criteriaValues, $column_id
- ) {
- $html_output = '';
- if (is_array($foreignData['disp_row'])) {
- $html_output .= '<select name="criteriaValues[' . $column_index . ']"'
- . ' id="' . $column_id . $column_index . '">';
- $html_output .= PMA_foreignDropdown(
- $foreignData['disp_row'], $foreignData['foreign_field'],
- $foreignData['foreign_display'], '', $foreignMaxLimit
- );
- $html_output .= '</select>';
-
- } elseif ($foreignData['foreign_link'] == true) {
- $html_output .= '<input type="text" id="' . $column_id
- . $column_index . '"'
- . ' name="criteriaValues[' . $column_index . ']" id="field_'
- . md5($column_name) . '[' . $column_index . ']" class="textfield"'
- . (isset($criteriaValues[$column_index])
- && is_string($criteriaValues[$column_index])
- ? (' value="' . $criteriaValues[$column_index] . '"')
- : '')
- . ' />';
-
- $html_output .= '<a class="ajax browse_foreign" href="'
- . 'browse_foreigners.php'
- . PMA_URL_getCommon(
- array('db' => $this->_db, 'table' => $this->_table)
- )
- . '&amp;field=' . urlencode($column_name) . '&amp;fieldkey='
- . $column_index . '&amp;fromsearch=1"';
- $html_output .= '>' . str_replace("'", "\'", $titles['Browse']) . '</a>';
- }
- return $html_output;
- }
-
- /**
- * Provides html elements for search criteria inputbox
- * in case the column is of ENUM or SET type
- *
- * @param int $column_index Column index
- * @param array $criteriaValues Array of search criteria inputs
- * @param string $column_type Column type
- * @param string $column_id Column's inputbox's id
- * @param bool $in_zoom_search_edit Whether we are in zoom search edit
- *
- * @return string HTML elements.
- */
- private function _getEnumSetInputBox($column_index, $criteriaValues,
- $column_type, $column_id, $in_zoom_search_edit = false
- ) {
- $column_type = htmlspecialchars($column_type);
- $html_output = '';
- $value = explode(
- ', ',
- str_replace("'", '', /*overload*/mb_substr($column_type, 5, -1))
- );
- $cnt_value = count($value);
-
- /*
- * Enum in edit mode --> dropdown
- * Enum in search mode --> multiselect
- * Set in edit mode --> multiselect
- * Set in search mode --> input (skipped here, so the 'else'
- * section would handle it)
- */
- if ((strncasecmp($column_type, 'enum', 4) && ! $in_zoom_search_edit)
- || (strncasecmp($column_type, 'set', 3) && $in_zoom_search_edit)
- ) {
- $html_output .= '<select name="criteriaValues[' . ($column_index)
- . ']" id="' . $column_id . $column_index . '">';
- } else {
- $html_output .= '<select name="criteriaValues[' . $column_index . ']"'
- . ' id="' . $column_id . $column_index . '" multiple="multiple"'
- . ' size="' . min(3, $cnt_value) . '">';
- }
-
- //Add select options
- for ($j = 0; $j < $cnt_value; $j++) {
- if (isset($criteriaValues[$column_index])
- && is_array($criteriaValues[$column_index])
- && in_array($value[$j], $criteriaValues[$column_index])
- ) {
- $html_output .= '<option value="' . $value[$j] . '" Selected>'
- . $value[$j] . '</option>';
- } else {
- $html_output .= '<option value="' . $value[$j] . '">'
- . $value[$j] . '</option>';
- }
- } // end for
- $html_output .= '</select>';
- return $html_output;
- }
-
- /**
- * Creates the HTML content for:
- * 1) Browsing foreign data for a column.
- * 2) Creating elements for search criteria input on columns.
- *
- * @param array $foreignData Foreign keys data
- * @param string $column_name Column name
- * @param string $column_type Column type
- * @param int $column_index Column index
- * @param array $titles Selected title
- * @param int $foreignMaxLimit Max limit of displaying foreign elements
- * @param array $criteriaValues Array of search criteria inputs
- * @param bool $in_fbs Whether we are in 'function based search'
- * @param bool $in_zoom_search_edit Whether we are in zoom search edit
- *
- * @return string HTML content for viewing foreign data and elements
- * for search criteria input.
- */
- private function _getInputbox($foreignData, $column_name, $column_type,
- $column_index, $titles, $foreignMaxLimit, $criteriaValues, $in_fbs = false,
- $in_zoom_search_edit = false
- ) {
- $str = '';
- $column_type = (string)$column_type;
- $column_id = ($in_zoom_search_edit) ? 'edit_fieldID_' : 'fieldID_';
-
- // Get inputbox based on different column types
- // (Foreign key, geometrical, enum)
- if ($this->_foreigners
- && PMA_searchColumnInForeigners($this->_foreigners, $column_name)
- ) {
- $str .= $this->_getForeignKeyInputBox(
- $foreignData, $column_name, $column_index, $titles,
- $foreignMaxLimit, $criteriaValues, $column_id
- );
-
- } elseif (in_array($column_type, PMA_Util::getGISDatatypes())) {
- $str .= $this->_getGeometricalInputBox($column_index, $in_fbs);
-
- } elseif (strncasecmp($column_type, 'enum', 4) == 0
- || (strncasecmp($column_type, 'set', 3) == 0 && $in_zoom_search_edit)
- ) {
- $str .= $this->_getEnumSetInputBox(
- $column_index, $criteriaValues, $column_type, $column_id,
- $in_zoom_search_edit = false
- );
-
- } else {
- // other cases
- $the_class = 'textfield';
-
- if ($column_type == 'date') {
- $the_class .= ' datefield';
- } elseif ($column_type == 'datetime'
- || substr($column_type, 0, 9) == 'timestamp'
- ) {
- $the_class .= ' datetimefield';
- } elseif (substr($column_type, 0, 3) == 'bit') {
- $the_class .= ' bit';
- }
-
- $str .= '<input type="text" name="criteriaValues[' . $column_index . ']"'
- . ' size="40" class="' . $the_class . '" id="'
- . $column_id . $column_index . '"'
- . (isset($criteriaValues[$column_index])
- && is_string($criteriaValues[$column_index])
- ? (' value="' . $criteriaValues[$column_index] . '"')
- : '')
- . ' />';
- }
- return $str;
- }
-
- /**
- * Return the where clause in case column's type is ENUM.
- *
- * @param mixed $criteriaValues Search criteria input
- * @param string $func_type Search function/operator
- *
- * @return string part of where clause.
- */
- private function _getEnumWhereClause($criteriaValues, $func_type)
- {
- if (! is_array($criteriaValues)) {
- $criteriaValues = explode(',', $criteriaValues);
- }
- $enum_selected_count = count($criteriaValues);
- if ($func_type == '=' && $enum_selected_count > 1) {
- $func_type = 'IN';
- $parens_open = '(';
- $parens_close = ')';
-
- } elseif ($func_type == '!=' && $enum_selected_count > 1) {
- $func_type = 'NOT IN';
- $parens_open = '(';
- $parens_close = ')';
-
- } else {
- $parens_open = '';
- $parens_close = '';
- }
- $enum_where = '\''
- . PMA_Util::sqlAddSlashes($criteriaValues[0]) . '\'';
- for ($e = 1; $e < $enum_selected_count; $e++) {
- $enum_where .= ', \''
- . PMA_Util::sqlAddSlashes($criteriaValues[$e]) . '\'';
- }
-
- return ' ' . $func_type . ' ' . $parens_open
- . $enum_where . $parens_close;
- }
-
- /**
- * Return the where clause for a geometrical column.
- *
- * @param mixed $criteriaValues Search criteria input
- * @param string $names Name of the column on which search is submitted
- * @param string $func_type Search function/operator
- * @param string $types Type of the field
- * @param bool $geom_func Whether geometry functions should be applied
- *
- * @return string part of where clause.
- */
- private function _getGeomWhereClause($criteriaValues, $names,
- $func_type, $types, $geom_func = null
- ) {
- $geom_unary_functions = array(
- 'IsEmpty' => 1,
- 'IsSimple' => 1,
- 'IsRing' => 1,
- 'IsClosed' => 1,
- );
- $where = '';
-
- // Get details about the geometry functions
- $geom_funcs = PMA_Util::getGISFunctions($types, true, false);
- // New output type is the output type of the function being applied
- $types = $geom_funcs[$geom_func]['type'];
-
- // If the function takes a single parameter
- if ($geom_funcs[$geom_func]['params'] == 1) {
- $backquoted_name = $geom_func . '(' . PMA_Util::backquote($names) . ')';
- } else {
- // If the function takes two parameters
- // create gis data from the criteria input
- $gis_data = PMA_Util::createGISData($criteriaValues);
- $where = $geom_func . '(' . PMA_Util::backquote($names)
- . ',' . $gis_data . ')';
- return $where;
- }
-
- // If the where clause is something like 'IsEmpty(`spatial_col_name`)'
- if (isset($geom_unary_functions[$geom_func])
- && trim($criteriaValues) == ''
- ) {
- $where = $backquoted_name;
-
- } elseif (in_array($types, PMA_Util::getGISDatatypes())
- && ! empty($criteriaValues)
- ) {
- // create gis data from the criteria input
- $gis_data = PMA_Util::createGISData($criteriaValues);
- $where = $backquoted_name . ' ' . $func_type . ' ' . $gis_data;
- }
- return $where;
- }
-
- /**
- * Return the where clause for query generation based on the inputs provided.
- *
- * @param mixed $criteriaValues Search criteria input
- * @param string $names Name of the column on which search is submitted
- * @param string $types Type of the field
- * @param string $func_type Search function/operator
- * @param bool $unaryFlag Whether operator unary or not
- * @param bool $geom_func Whether geometry functions should be applied
- *
- * @return string generated where clause.
- */
- private function _getWhereClause($criteriaValues, $names, $types,
- $func_type, $unaryFlag, $geom_func = null
- ) {
- // If geometry function is set
- if ($geom_func != null && trim($geom_func) != '') {
- return $this->_getGeomWhereClause(
- $criteriaValues, $names, $func_type, $types, $geom_func
- );
- }
-
- $backquoted_name = PMA_Util::backquote($names);
- $where = '';
- if ($unaryFlag) {
- $where = $backquoted_name . ' ' . $func_type;
-
- } elseif (strncasecmp($types, 'enum', 4) == 0 && ! empty($criteriaValues)) {
- $where = $backquoted_name;
- $where .= $this->_getEnumWhereClause($criteriaValues, $func_type);
-
- } elseif ($criteriaValues != '') {
- // For these types we quote the value. Even if it's another type
- // (like INT), for a LIKE we always quote the value. MySQL converts
- // strings to numbers and numbers to strings as necessary
- // during the comparison
- if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types)
- || /*overload*/mb_strpos(' ' . $func_type, 'LIKE')
- ) {
- $quot = '\'';
- } else {
- $quot = '';
- }
-
- // LIKE %...%
- if ($func_type == 'LIKE %...%') {
- $func_type = 'LIKE';
- $criteriaValues = '%' . $criteriaValues . '%';
- }
- if ($func_type == 'REGEXP ^...$') {
- $func_type = 'REGEXP';
- $criteriaValues = '^' . $criteriaValues . '$';
- }
-
- if ('IN (...)' != $func_type
- && 'NOT IN (...)' != $func_type
- && 'BETWEEN' != $func_type
- && 'NOT BETWEEN' != $func_type
- ) {
- if ($func_type == 'LIKE %...%' || $func_type == 'LIKE') {
- $where = $backquoted_name . ' ' . $func_type . ' ' . $quot
- . PMA_Util::sqlAddSlashes($criteriaValues, true) . $quot;
- } else {
- $where = $backquoted_name . ' ' . $func_type . ' ' . $quot
- . PMA_Util::sqlAddSlashes($criteriaValues) . $quot;
- }
- return $where;
- }
- $func_type = str_replace(' (...)', '', $func_type);
-
- //Don't explode if this is already an array
- //(Case for (NOT) IN/BETWEEN.)
- if (is_array($criteriaValues)) {
- $values = $criteriaValues;
- } else {
- $values = explode(',', $criteriaValues);
- }
- // quote values one by one
- $emptyKey = false;
- foreach ($values as $key => &$value) {
- if ('' === $value) {
- $emptyKey = $key;
- $value = 'NULL';
- continue;
- }
- $value = $quot . PMA_Util::sqlAddSlashes(trim($value))
- . $quot;
- }
-
- if ('BETWEEN' == $func_type || 'NOT BETWEEN' == $func_type) {
- $where = $backquoted_name . ' ' . $func_type . ' '
- . (isset($values[0]) ? $values[0] : '')
- . ' AND ' . (isset($values[1]) ? $values[1] : '');
- } else { //[NOT] IN
- if (false !== $emptyKey) {
- unset($values[$emptyKey]);
- }
- $wheres = array();
- if (!empty($values)) {
- $wheres[] = $backquoted_name . ' ' . $func_type
- . ' (' . implode(',', $values) . ')';
- }
- if (false !== $emptyKey) {
- $wheres[] = $backquoted_name . ' IS NULL';
- }
- $where = implode(' OR ', $wheres);
- if (1 < count($wheres)) {
- $where = '(' . $where . ')';
- }
- }
- } // end if
-
- return $where;
- }
-
- /**
- * Builds the sql search query from the post parameters
- *
- * @return string the generated SQL query
- */
- public function buildSqlQuery()
- {
- $sql_query = 'SELECT ';
-
- // If only distinct values are needed
- $is_distinct = (isset($_POST['distinct'])) ? 'true' : 'false';
- if ($is_distinct == 'true') {
- $sql_query .= 'DISTINCT ';
- }
-
- // if all column names were selected to display, we do a 'SELECT *'
- // (more efficient and this helps prevent a problem in IE
- // if one of the rows is edited and we come back to the Select results)
- if (isset($_POST['zoom_submit']) || ! empty($_POST['displayAllColumns'])) {
- $sql_query .= '* ';
- } else {
- $sql_query .= implode(
- ', ',
- PMA_Util::backquote($_POST['columnsToDisplay'])
- );
- } // end if
-
- $sql_query .= ' FROM '
- . PMA_Util::backquote($_POST['table']);
- $whereClause = $this->_generateWhereClause();
- $sql_query .= $whereClause;
-
- // if the search results are to be ordered
- if (isset($_POST['orderByColumn']) && $_POST['orderByColumn'] != '--nil--') {
- $sql_query .= ' ORDER BY '
- . PMA_Util::backquote($_POST['orderByColumn'])
- . ' ' . $_POST['order'];
- } // end if
- return $sql_query;
- }
-
- /**
- * Generates the where clause for the SQL search query to be executed
- *
- * @return string the generated where clause
- */
- private function _generateWhereClause()
- {
- if (isset($_POST['customWhereClause'])
- && trim($_POST['customWhereClause']) != ''
- ) {
- return ' WHERE ' . $_POST['customWhereClause'];
- }
-
- // If there are no search criteria set or no unary criteria operators,
- // return
- if (! isset($_POST['criteriaValues'])
- && ! isset($_POST['criteriaColumnOperators'])
- ) {
- return '';
- }
-
- // else continue to form the where clause from column criteria values
- $fullWhereClause = array();
- reset($_POST['criteriaColumnOperators']);
- while (list($column_index, $operator) = each(
- $_POST['criteriaColumnOperators']
- )) {
-
- $unaryFlag = $GLOBALS['PMA_Types']->isUnaryOperator($operator);
- $tmp_geom_func = isset($geom_func[$column_index])
- ? $geom_func[$column_index] : null;
-
- $whereClause = $this->_getWhereClause(
- $_POST['criteriaValues'][$column_index],
- $_POST['criteriaColumnNames'][$column_index],
- $_POST['criteriaColumnTypes'][$column_index],
- $operator,
- $unaryFlag,
- $tmp_geom_func
- );
-
- if ($whereClause) {
- $fullWhereClause[] = $whereClause;
- }
- } // end while
-
- if ($fullWhereClause) {
- return ' WHERE ' . implode(' AND ', $fullWhereClause);
- }
- return '';
- }
-
- /**
- * Generates HTML for a geometrical function column to be displayed in table
- * search selection form
- *
- * @param integer $column_index index of current column in $columnTypes array
- *
- * @return string the generated HTML
- */
- private function _getGeomFuncHtml($column_index)
- {
- $html_output = '';
- // return if geometrical column is not present
- if (! $this->_geomColumnFlag) {
- return $html_output;
- }
-
- /**
- * Displays 'Function' column if it is present
- */
- $html_output .= '<td>';
- $geom_types = PMA_Util::getGISDatatypes();
- // if a geometry column is present
- if (in_array($this->_columnTypes[$column_index], $geom_types)) {
- $html_output .= '<select class="geom_func" name="geom_func['
- . $column_index . ']">';
- // get the relevant list of GIS functions
- $funcs = PMA_Util::getGISFunctions(
- $this->_columnTypes[$column_index], true, true
- );
- /**
- * For each function in the list of functions,
- * add an option to select list
- */
- foreach ($funcs as $func_name => $func) {
- $name = isset($func['display']) ? $func['display'] : $func_name;
- $html_output .= '<option value="' . htmlspecialchars($name) . '">'
- . htmlspecialchars($name) . '</option>';
- }
- $html_output .= '</select>';
- } else {
- $html_output .= '&nbsp;';
- }
- $html_output .= '</td>';
- return $html_output;
- }
-
- /**
- * Generates formatted HTML for extra search options in table search form
- *
- * @return string the generated HTML
- */
- private function _getOptions()
- {
- $html_output = '';
- $html_output .= PMA_Util::getDivForSliderEffect(
- 'searchoptions', __('Options')
- );
-
- /**
- * Displays columns select list for selecting distinct columns in the search
- */
- $html_output .= '<fieldset id="fieldset_select_fields">'
- . '<legend>' . __('Select columns (at least one):') . '</legend>'
- . '<select name="columnsToDisplay[]"'
- . ' size="' . min(count($this->_columnNames), 10) . '"'
- . ' multiple="multiple">';
- // Displays the list of the fields
- foreach ($this->_columnNames as $each_field) {
- $html_output .= ' '
- . '<option value="' . htmlspecialchars($each_field) . '"'
- . ' selected="selected">' . htmlspecialchars($each_field)
- . '</option>' . "\n";
- } // end for
- $html_output .= '</select>'
- . '<input type="checkbox" name="distinct" value="DISTINCT"'
- . ' id="oDistinct" />'
- . '<label for="oDistinct">DISTINCT</label></fieldset>';
-
- /**
- * Displays input box for custom 'Where' clause to be used in the search
- */
- $html_output .= '<fieldset id="fieldset_search_conditions">'
- . '<legend>' . '<em>' . __('Or') . '</em> '
- . __('Add search conditions (body of the "where" clause):')
- . '</legend>';
- $html_output .= PMA_Util::showMySQLDocu('Functions');
- $html_output .= '<input type="text" name="customWhereClause"'
- . ' class="textfield" size="64" />';
- $html_output .= '</fieldset>';
-
- /**
- * Displays option of changing default number of rows displayed per page
- */
- $html_output .= '<fieldset id="fieldset_limit_rows">'
- . '<legend>' . __('Number of rows per page') . '</legend>'
- . '<input type="number" name="session_max_rows" required="required" '
- . 'min="1" '
- . 'value="' . $GLOBALS['cfg']['MaxRows'] . '" class="textfield" />'
- . '</fieldset>';
-
- /**
- * Displays option for ordering search results
- * by a column value (Asc or Desc)
- */
- $html_output .= '<fieldset id="fieldset_display_order">'
- . '<legend>' . __('Display order:') . '</legend>'
- . '<select name="orderByColumn"><option value="--nil--"></option>';
- foreach ($this->_columnNames as $each_field) {
- $html_output .= ' '
- . '<option value="' . htmlspecialchars($each_field) . '">'
- . htmlspecialchars($each_field) . '</option>' . "\n";
- } // end for
- $html_output .= '</select>';
- $choices = array(
- 'ASC' => __('Ascending'),
- 'DESC' => __('Descending')
- );
- $html_output .= PMA_Util::getRadioFields(
- 'order', $choices, 'ASC', false, true, "formelement"
- );
- unset($choices);
-
- $html_output .= '</fieldset><br style="clear: both;"/></div>';
- return $html_output;
- }
-
- /**
- * Other search criteria like data label
- * (for tbl_zoom_select.php)
- *
- * @param string|null $dataLabel Label for points in zoom plot
- *
- * @return string the generated html
- */
- private function _getOptionsZoom($dataLabel)
- {
- $html_output = '';
- $html_output .= '<table class="data">';
- //Select options for datalabel
- $html_output .= '<tr>';
- $html_output .= '<td><label for="dataLabel">'
- . __("Use this column to label each point") . '</label></td>';
- $html_output .= '<td><select name="dataLabel" id="dataLabel" >'
- . '<option value = "">' . __('None') . '</option>';
- for ($j = 0, $nb = count($this->_columnNames); $j < $nb; $j++) {
- if (isset($dataLabel)
- && $dataLabel == htmlspecialchars($this->_columnNames[$j])
- ) {
- $html_output .= '<option value="'
- . htmlspecialchars($this->_columnNames[$j])
- . '" selected="selected">'
- . htmlspecialchars($this->_columnNames[$j])
- . '</option>';
- } else {
- $html_output .= '<option value="'
- . htmlspecialchars($this->_columnNames[$j]) . '" >'
- . htmlspecialchars($this->_columnNames[$j]) . '</option>';
- }
- }
- $html_output .= '</select></td>';
- $html_output .= '</tr>';
- //Inputbox for changing default maximum rows to plot
- $html_output .= '<tr>';
- $html_output .= '<td><label for="maxRowPlotLimit">'
- . __("Maximum rows to plot") . '</label></td>';
- $html_output .= '<td>';
- $html_output .= '<input type="number" name="maxPlotLimit"'
- . ' id="maxRowPlotLimit" required="required"'
- . ' value="' . ((! empty($_POST['maxPlotLimit']))
- ? htmlspecialchars($_POST['maxPlotLimit'])
- : $GLOBALS['cfg']['maxRowPlotLimit'])
- . '" />';
- $html_output .= '</td></tr>';
- $html_output .= '</table>';
- return $html_output;
- }
-
- /**
- * Provides a column's type, collation, operators list, and criteria value
- * to display in table search form
- *
- * @param integer $search_index Row number in table search form
- * @param integer $column_index Column index in ColumnNames array
- *
- * @return array Array containing column's properties
- */
- public function getColumnProperties($search_index, $column_index)
- {
- $selected_operator = (isset($_POST['criteriaColumnOperators'])
- ? $_POST['criteriaColumnOperators'][$search_index] : '');
- $entered_value = (isset($_POST['criteriaValues'])
- ? $_POST['criteriaValues'] : '');
- $titles = array(
- 'Browse' => PMA_Util::getIcon(
- 'b_browse.png', __('Browse foreign values')
- )
- );
- //Gets column's type and collation
- $type = $this->_columnTypes[$column_index];
- $collation = $this->_columnCollations[$column_index];
- //Gets column's comparison operators depending on column type
- $func = '<select name="criteriaColumnOperators['
- . $search_index . ']" onchange="changeValueFieldType(this, '
- . $search_index . ')">';
- $func .= $GLOBALS['PMA_Types']->getTypeOperatorsHtml(
- preg_replace('@\(.*@s', '', $this->_columnTypes[$column_index]),
- $this->_columnNullFlags[$column_index], $selected_operator
- );
- $func .= '</select>';
- //Gets link to browse foreign data(if any) and criteria inputbox
- $foreignData = PMA_getForeignData(
- $this->_foreigners, $this->_columnNames[$column_index], false, '', ''
- );
- $value = $this->_getInputbox(
- $foreignData, $this->_columnNames[$column_index], $type, $search_index,
- $titles, $GLOBALS['cfg']['ForeignKeyMaxLimit'], $entered_value
- );
- return array(
- 'type' => $type,
- 'collation' => $collation,
- 'func' => $func,
- 'value' => $value
- );
- }
-
- /**
- * Provides the search form's table row in case of Normal Search
- * (for tbl_select.php)
- *
- * @return string the generated table row
- */
- private function _getRowsNormal()
- {
- $odd_row = true;
- $html_output = '';
- // for every column present in table
- for (
- $column_index = 0, $nb = count($this->_columnNames);
- $column_index < $nb;
- $column_index++
- ) {
- $html_output .= '<tr class="noclick '
- . ($odd_row ? 'odd' : 'even')
- . '">';
- $odd_row = !$odd_row;
- //If 'Function' column is present
- $html_output .= $this->_getGeomFuncHtml($column_index);
- //Displays column's name, type, collation and value
- $html_output .= '<th>'
- . htmlspecialchars($this->_columnNames[$column_index]) . '</th>';
- $properties = $this->getColumnProperties($column_index, $column_index);
- $html_output .= '<td>'
- . htmlspecialchars($properties['type'])
- . '</td>';
- $html_output .= '<td>' . $properties['collation'] . '</td>';
- $html_output .= '<td>' . $properties['func'] . '</td>';
- // here, the data-type attribute is needed for a date/time picker
- $html_output .= '<td data-type="'
- . htmlspecialchars($properties['type']) . '"'
- . '>' . $properties['value'] . '</td>';
- $html_output .= '</tr>';
- //Displays hidden fields
- $html_output .= '<tr><td>';
- $html_output .= '<input type="hidden"'
- . ' name="criteriaColumnNames[' . $column_index . ']"'
- . ' value="'
- . htmlspecialchars($this->_columnNames[$column_index])
- . '" />';
- $html_output .= '<input type="hidden"'
- . ' name="criteriaColumnTypes[' . $column_index . ']"'
- . ' value="'
- . htmlspecialchars($this->_columnTypes[$column_index]) . '" />';
- $html_output .= '<input type="hidden"'
- . ' name="criteriaColumnCollations[' . $column_index . ']"'
- . ' value="' . $this->_columnCollations[$column_index] . '" />';
- $html_output .= '</td></tr>';
- } // end for
-
- return $html_output;
- }
-
- /**
- * Provides the search form's table row in case of Zoom search
- * (for tbl_zoom_select.php)
- *
- * @return string the generated table row
- */
- private function _getRowsZoom()
- {
- $odd_row = true;
- $html_output = '';
- $type = $collation = $func = $value = array();
- /**
- * Get already set search criteria (if any)
- */
-
- //Displays column rows for search criteria input
- for ($i = 0; $i < 4; $i++) {
- //After X-Axis and Y-Axis column rows, display additional criteria
- // option
- if ($i == 2) {
- $html_output .= '<tr><td>';
- $html_output .= __("Additional search criteria");
- $html_output .= '</td></tr>';
- }
- $html_output .= '<tr class="noclick '
- . ($odd_row ? 'odd' : 'even')
- . '">';
- $odd_row = ! $odd_row;
- //Select options for column names
- $html_output .= '<th><select name="criteriaColumnNames[]" id="'
- . 'tableid_' . $i . '" >';
- $html_output .= '<option value="' . 'pma_null' . '">' . __('None')
- . '</option>';
- for ($j = 0, $nb = count($this->_columnNames); $j < $nb; $j++) {
- if (isset($_POST['criteriaColumnNames'][$i])
- && $_POST['criteriaColumnNames'][$i] == htmlspecialchars($this->_columnNames[$j])
- ) {
- $html_output .= '<option value="'
- . htmlspecialchars($this->_columnNames[$j])
- . '" selected="selected">'
- . htmlspecialchars($this->_columnNames[$j])
- . '</option>';
- } else {
- $html_output .= '<option value="'
- . htmlspecialchars($this->_columnNames[$j]) . '">'
- . htmlspecialchars($this->_columnNames[$j]) . '</option>';
- }
- }
- $html_output .= '</select></th>';
- if (isset($_POST['criteriaColumnNames'])
- && $_POST['criteriaColumnNames'][$i] != 'pma_null'
- ) {
- $key = array_search(
- $_POST['criteriaColumnNames'][$i],
- $this->_columnNames
- );
- $properties = $this->getColumnProperties($i, $key);
- $type[$i] = $properties['type'];
- $collation[$i] = $properties['collation'];
- $func[$i] = $properties['func'];
- $value[$i] = $properties['value'];
- }
- //Column type
- $html_output .= '<td>' . (isset($type[$i]) ? $type[$i] : '') . '</td>';
- //Column Collation
- $html_output .= '<td>' . (isset($collation[$i]) ? $collation[$i] : '')
- . '</td>';
- //Select options for column operators
- $html_output .= '<td>' . (isset($func[$i]) ? $func[$i] : '') . '</td>';
- //Inputbox for search criteria value
- $html_output .= '<td>' . (isset($value[$i]) ? $value[$i] : '') . '</td>';
- $html_output .= '</tr>';
- //Displays hidden fields
- $html_output .= '<tr><td>';
- $html_output
- .= '<input type="hidden" name="criteriaColumnTypes[' . $i . ']"'
- . ' id="types_' . $i . '" ';
- if (isset($_POST['criteriaColumnTypes'][$i])) {
- $html_output .= 'value="' . $_POST['criteriaColumnTypes'][$i] . '" ';
- }
- $html_output .= '/>';
- $html_output .= '<input type="hidden" name="criteriaColumnCollations['
- . $i . ']" id="collations_' . $i . '" />';
- $html_output .= '</td></tr>';
- }//end for
- return $html_output;
- }
-
- /**
- * Generates HTML for displaying fields table in search form
- *
- * @return string the generated HTML
- */
- private function _getFieldsTableHtml()
- {
- $html_output = '';
- $html_output .= '<table class="data"'
- . ($this->_searchType == 'zoom' ? ' id="tableFieldsId"' : '') . '>';
- $html_output .= $this->_getTableHeader();
- $html_output .= '<tbody>';
-
- if ($this->_searchType == 'zoom') {
- $html_output .= $this->_getRowsZoom();
- } else {
- $html_output .= $this->_getRowsNormal();
- }
-
- $html_output .= '</tbody></table>';
- return $html_output;
- }
-
- /**
- * Provides the form tag for table search form
- * (normal search or zoom search)
- *
- * @param string $goto Goto URL
- *
- * @return string the HTML for form tag
- */
- private function _getFormTag($goto)
- {
- $html_output = '';
- $scriptName = '';
- $formId = '';
- switch ($this->_searchType) {
- case 'normal' :
- $scriptName = 'tbl_select.php';
- $formId = 'tbl_search_form';
- break;
- case 'zoom' :
- $scriptName = 'tbl_zoom_select.php';
- $formId = 'zoom_search_form';
- break;
- case 'replace' :
- $scriptName = 'tbl_find_replace.php';
- $formId = 'find_replace_form';
- break;
- }
-
- $html_output .= '<form method="post" action="' . $scriptName . '" '
- . 'name="insertForm" id="' . $formId . '" '
- . 'class="ajax"' . '>';
-
- $html_output .= PMA_URL_getHiddenInputs($this->_db, $this->_table);
- $html_output .= '<input type="hidden" name="goto" value="' . $goto . '" />';
- $html_output .= '<input type="hidden" name="back" value="' . $scriptName
- . '" />';
-
- return $html_output;
- }
-
- /**
- * Returns the HTML for secondary levels tabs of the table search page
- *
- * @return string HTML for secondary levels tabs
- */
- public function getSecondaryTabs()
- {
- $url_params = array();
- $url_params['db'] = $this->_db;
- $url_params['table'] = $this->_table;
-
- $html_output = '<ul id="topmenu2">';
- foreach ($this->_getSubTabs() as $tab) {
- $html_output .= PMA_Util::getHtmlTab($tab, $url_params);
- }
- $html_output .= '</ul>';
- $html_output .= '<div class="clearfloat"></div>';
- return $html_output;
- }
-
- /**
- * Generates the table search form under table search tab
- *
- * @param string $goto Goto URL
- * @param string|null $dataLabel Label for points in zoom plot
- *
- * @return string the generated HTML for table search form
- */
- public function getSelectionForm($goto, $dataLabel = null)
- {
- $html_output = $this->_getFormTag($goto);
-
- if ($this->_searchType == 'zoom') {
- $html_output .= '<fieldset id="fieldset_zoom_search">';
- $html_output .= '<fieldset id="inputSection">';
- $html_output .= '<legend>'
- . __(
- 'Do a "query by example" (wildcard: "%") for two'
- . ' different columns'
- )
- . '</legend>';
- $html_output .= $this->_getFieldsTableHtml();
- $html_output .= $this->_getOptionsZoom($dataLabel);
- $html_output .= '</fieldset>';
- $html_output .= '</fieldset>';
- } else if ($this->_searchType == 'normal') {
- $html_output .= '<fieldset id="fieldset_table_search">';
- $html_output .= '<fieldset id="fieldset_table_qbe">';
- $html_output .= '<legend>'
- . __('Do a "query by example" (wildcard: "%")')
- . '</legend>';
- $html_output .= $this->_getFieldsTableHtml();
- $html_output .= '<div id="gis_editor"></div>';
- $html_output .= '<div id="popup_background"></div>';
- $html_output .= '</fieldset>';
- $html_output .= $this->_getOptions();
- $html_output .= '</fieldset>';
- } else if ($this->_searchType == 'replace') {
- $html_output .= '<fieldset id="fieldset_find_replace">';
- $html_output .= '<fieldset id="fieldset_find">';
- $html_output .= '<legend>' . __('Find and replace') . '</legend>';
- $html_output .= $this->_getSearchAndReplaceHTML();
- $html_output .= '</fieldset>';
- $html_output .= '</fieldset>';
- }
-
- /**
- * Displays selection form's footer elements
- */
- $html_output .= '<fieldset class="tblFooters">';
- $html_output .= '<input type="submit" name="'
- . ($this->_searchType == 'zoom' ? 'zoom_submit' : 'submit')
- . ($this->_searchType == 'zoom' ? '" id="inputFormSubmitId"' : '" ')
- . 'value="' . __('Go') . '" />';
- $html_output .= '</fieldset></form>';
- $html_output .= '<div id="sqlqueryresultsouter"></div>';
- return $html_output;
- }
-
- /**
- * Provides form for displaying point data and also the scatter plot
- * (for tbl_zoom_select.php)
- *
- * @param string $goto Goto URL
- * @param array $data Array containing SQL query data
- *
- * @return string form's html
- */
- public function getZoomResultsForm($goto, $data)
- {
- $html_output = '';
- $titles = array(
- 'Browse' => PMA_Util::getIcon(
- 'b_browse.png',
- __('Browse foreign values')
- )
- );
- $html_output .= '<form method="post" action="tbl_zoom_select.php"'
- . ' name="displayResultForm" id="zoom_display_form"'
- . ' class="ajax"' . '>';
- $html_output .= PMA_URL_getHiddenInputs($this->_db, $this->_table);
- $html_output .= '<input type="hidden" name="goto" value="' . $goto . '" />';
- $html_output
- .= '<input type="hidden" name="back" value="tbl_zoom_select.php" />';
-
- $html_output .= '<fieldset id="displaySection">';
- $html_output .= '<legend>' . __('Browse/Edit the points') . '</legend>';
-
- //JSON encode the data(query result)
- $html_output .= '<center>';
- if (isset($_POST['zoom_submit']) && ! empty($data)) {
- $html_output .= '<div id="resizer">';
- $html_output .= '<center><a href="#" onclick="displayHelp();">'
- . __('How to use') . '</a></center>';
- $html_output .= '<div id="querydata" style="display:none">'
- . json_encode($data) . '</div>';
- $html_output .= '<div id="querychart"></div>';
- $html_output .= '<button class="button-reset">'
- . __('Reset zoom') . '</button>';
- $html_output .= '</div>';
- }
- $html_output .= '</center>';
-
- //Displays rows in point edit form
- $html_output .= '<div id="dataDisplay" style="display:none">';
- $html_output .= '<table><thead>';
- $html_output .= '<tr>';
- $html_output .= '<th>' . __('Column') . '</th>'
- . '<th>' . __('Null') . '</th>'
- . '<th>' . __('Value') . '</th>';
- $html_output .= '</tr>';
- $html_output .= '</thead>';
-
- $html_output .= '<tbody>';
- $odd_row = true;
- for (
- $column_index = 0, $nb = count($this->_columnNames);
- $column_index < $nb;
- $column_index++
- ) {
- $fieldpopup = $this->_columnNames[$column_index];
- $foreignData = PMA_getForeignData(
- $this->_foreigners,
- $fieldpopup,
- false,
- '',
- ''
- );
- $html_output
- .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">';
- $odd_row = ! $odd_row;
- //Display column Names
- $html_output
- .= '<th>' . htmlspecialchars($this->_columnNames[$column_index])
- . '</th>';
- //Null checkbox if column can be null
- $html_output .= '<th>'
- . (($this->_columnNullFlags[$column_index] == 'YES')
- ? '<input type="checkbox" class="checkbox_null"'
- . ' name="criteriaColumnNullFlags[' . $column_index . ']"'
- . ' id="edit_fields_null_id_' . $column_index . '" />'
- : '');
- $html_output .= '</th>';
- //Column's Input box
- $html_output .= '<th>';
- $html_output .= $this->_getInputbox(
- $foreignData, $fieldpopup, $this->_columnTypes[$column_index],
- $column_index, $titles, $GLOBALS['cfg']['ForeignKeyMaxLimit'],
- '', false, true
- );
- $html_output .= '</th></tr>';
- }
- $html_output .= '</tbody></table>';
- $html_output .= '</div>';
- $html_output .= '<input type="hidden" id="queryID" name="sql_query" />';
- $html_output .= '</form>';
- return $html_output;
- }
-
- /**
- * Displays the 'Find and replace' form
- *
- * @return string HTML for 'Find and replace' form
- */
- function _getSearchAndReplaceHTML()
- {
- $htmlOutput = __('Find:')
- . '<input type="text" value="" name="find" required />';
- $htmlOutput .= __('Replace with:')
- . '<input type="text" value="" name="replaceWith" required />';
-
- $htmlOutput .= __('Column:') . '<select name="columnIndex">';
- for ($i = 0, $nb = count($this->_columnNames); $i < $nb; $i++) {
- $type = preg_replace('@\(.*@s', '', $this->_columnTypes[$i]);
- if ($GLOBALS['PMA_Types']->getTypeClass($type) == 'CHAR') {
- $column = $this->_columnNames[$i];
- $htmlOutput .= '<option value="' . $i . '">'
- . htmlspecialchars($column) . '</option>';
- }
- }
- $htmlOutput .= '</select>';
-
- $htmlOutput .= '<br>'
- . PMA_Util::getCheckbox(
- 'useRegex',
- __('Use regular expression'),
- false,
- false,
- 'useRegex'
- );
- return $htmlOutput;
- }
-
- /**
- * Finds and returns Regex pattern and their replacements
- *
- * @param int $columnIndex index of the column
- * @param string $find string to find in the column
- * @param string $replaceWith string to replace with
- * @param string $charSet character set of the connection
- *
- * @return array Array containing original values, replaced values and count
- */
- function _getRegexReplaceRows($columnIndex, $find, $replaceWith, $charSet)
- {
- $column = $this->_columnNames[$columnIndex];
- $sql_query = "SELECT "
- . PMA_Util::backquote($column) . ","
- . " 1," // to add an extra column that will have replaced value
- . " COUNT(*)"
- . " FROM " . PMA_Util::backquote($this->_db)
- . "." . PMA_Util::backquote($this->_table)
- . " WHERE " . PMA_Util::backquote($column)
- . " RLIKE '" . PMA_Util::sqlAddSlashes($find) . "' COLLATE "
- . $charSet . "_bin"; // here we
- // change the collation of the 2nd operand to a case sensitive
- // binary collation to make sure that the comparison is case sensitive
- $sql_query .= " GROUP BY " . PMA_Util::backquote($column)
- . " ORDER BY " . PMA_Util::backquote($column) . " ASC";
-
- $result = $GLOBALS['dbi']->fetchResult($sql_query, 0);
-
- if (is_array($result)) {
- foreach ($result as $index=>$row) {
- $result[$index][1] = preg_replace(
- "/" . $find . "/",
- $replaceWith,
- $row[0]
- );
- }
- }
- return $result;
- }
-
- /**
- * Returns HTML for previewing strings found and their replacements
- *
- * @param int $columnIndex index of the column
- * @param string $find string to find in the column
- * @param string $replaceWith string to replace with
- * @param boolean $useRegex to use Regex replace or not
- * @param string $charSet character set of the connection
- *
- * @return string HTML for previewing strings found and their replacements
- */
- function getReplacePreview($columnIndex, $find, $replaceWith, $useRegex,
- $charSet
- ) {
- $column = $this->_columnNames[$columnIndex];
- if ($useRegex) {
- $result = $this->_getRegexReplaceRows(
- $columnIndex, $find, $replaceWith, $charSet
- );
- } else {
- $sql_query = "SELECT "
- . PMA_Util::backquote($column) . ","
- . " REPLACE("
- . PMA_Util::backquote($column) . ", '" . $find . "', '"
- . $replaceWith
- . "'),"
- . " COUNT(*)"
- . " FROM " . PMA_Util::backquote($this->_db)
- . "." . PMA_Util::backquote($this->_table)
- . " WHERE " . PMA_Util::backquote($column)
- . " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
- // change the collation of the 2nd operand to a case sensitive
- // binary collation to make sure that the comparison
- // is case sensitive
- $sql_query .= " GROUP BY " . PMA_Util::backquote($column)
- . " ORDER BY " . PMA_Util::backquote($column) . " ASC";
-
- $result = $GLOBALS['dbi']->fetchResult($sql_query, 0);
- }
-
- $htmlOutput = '<form method="post" action="tbl_find_replace.php"'
- . ' name="previewForm" id="previewForm" class="ajax">';
- $htmlOutput .= PMA_URL_getHiddenInputs($this->_db, $this->_table);
- $htmlOutput .= '<input type="hidden" name="replace" value="true" />';
- $htmlOutput .= '<input type="hidden" name="columnIndex" value="'
- . $columnIndex . '" />';
- $htmlOutput .= '<input type="hidden" name="findString"'
- . ' value="' . htmlspecialchars($find) . '" />';
- $htmlOutput .= '<input type="hidden" name="replaceWith"'
- . ' value="' . htmlspecialchars($replaceWith) . '" />';
- $htmlOutput .= '<input type="hidden" name="useRegex"'
- . ' value="' . $useRegex . '" />';
-
- $htmlOutput .= '<fieldset id="fieldset_find_replace_preview">';
- $htmlOutput .= '<legend>' . __('Find and replace - preview') . '</legend>';
-
- $htmlOutput .= '<table id="previewTable">'
- . '<thead><tr>'
- . '<th>' . __('Count') . '</th>'
- . '<th>' . __('Original string') . '</th>'
- . '<th>' . __('Replaced string') . '</th>'
- . '</tr></thead>';
-
- $htmlOutput .= '<tbody>';
- $odd = true;
- if (is_array($result)) {
- foreach ($result as $row) {
- $val = $row[0];
- $replaced = $row[1];
- $count = $row[2];
-
- $htmlOutput .= '<tr class="' . ($odd ? 'odd' : 'even') . '">';
- $htmlOutput .= '<td class="right">' . htmlspecialchars($count)
- . '</td>';
- $htmlOutput .= '<td>' . htmlspecialchars($val) . '</td>';
- $htmlOutput .= '<td>' . htmlspecialchars($replaced) . '</td>';
- $htmlOutput .= '</tr>';
-
- $odd = ! $odd;
- }
- }
- $htmlOutput .= '</tbody>';
- $htmlOutput .= '</table>';
- $htmlOutput .= '</fieldset>';
-
- $htmlOutput .= '<fieldset class="tblFooters">';
- $htmlOutput .= '<input type="submit" name="replace"'
- . ' value="' . __('Replace') . '" />';
- $htmlOutput .= '</fieldset>';
-
- $htmlOutput .= '</form>';
- return $htmlOutput;
- }
-
- /**
- * Replaces a given string in a column with a give replacement
- *
- * @param int $columnIndex index of the column
- * @param string $find string to find in the column
- * @param string $replaceWith string to replace with
- * @param boolean $useRegex to use Regex replace or not
- * @param string $charSet character set of the connection
- *
- * @return void
- */
- function replace($columnIndex, $find, $replaceWith, $useRegex, $charSet)
- {
- $column = $this->_columnNames[$columnIndex];
- if ($useRegex) {
- $toReplace = $this->_getRegexReplaceRows(
- $columnIndex, $find, $replaceWith, $charSet
- );
- $sql_query = "UPDATE " . PMA_Util::backquote($this->_db)
- . "." . PMA_Util::backquote($this->_table)
- . " SET " . PMA_Util::backquote($column) . " = CASE";
- if (is_array($toReplace)) {
- foreach ($toReplace as $row) {
- $sql_query .= "\n WHEN " . PMA_Util::backquote($column)
- . " = '" . PMA_Util::sqlAddSlashes($row[0])
- . "' THEN '" . PMA_Util::sqlAddSlashes($row[1]) . "'";
- }
- }
- $sql_query .= " END"
- . " WHERE " . PMA_Util::backquote($column)
- . " RLIKE '" . PMA_Util::sqlAddSlashes($find) . "' COLLATE "
- . $charSet . "_bin"; // here we
- // change the collation of the 2nd operand to a case sensitive
- // binary collation to make sure that the comparison
- // is case sensitive
- } else {
- $sql_query = "UPDATE " . PMA_Util::backquote($this->_db)
- . "." . PMA_Util::backquote($this->_table)
- . " SET " . PMA_Util::backquote($column) . " ="
- . " REPLACE("
- . PMA_Util::backquote($column) . ", '" . $find . "', '"
- . $replaceWith
- . "')"
- . " WHERE " . PMA_Util::backquote($column)
- . " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
- // change the collation of the 2nd operand to a case sensitive
- // binary collation to make sure that the comparison
- // is case sensitive
- }
- $GLOBALS['dbi']->query(
- $sql_query, null, PMA_DatabaseInterface::QUERY_STORE
- );
- $GLOBALS['sql_query'] = $sql_query;
- }
-
- /**
- * Finds minimum and maximum value of a given column.
- *
- * @param string $column Column name
- *
- * @return array
- */
- public function getColumnMinMax($column)
- {
- $sql_query = 'SELECT MIN(' . PMA_Util::backquote($column) . ') AS `min`, '
- . 'MAX(' . PMA_Util::backquote($column) . ') AS `max` '
- . 'FROM ' . PMA_Util::backquote($this->_db) . '.'
- . PMA_Util::backquote($this->_table);
-
- $result = $GLOBALS['dbi']->fetchSingleRow($sql_query);
-
- return $result;
- }
-}
-?>
diff --git a/libraries/Template.class.php b/libraries/Template.class.php
new file mode 100644
index 0000000000..2af6b491d9
--- /dev/null
+++ b/libraries/Template.class.php
@@ -0,0 +1,98 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * hold PMA\Template class
+ *
+ * @package PMA
+ */
+
+namespace PMA;
+
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+/**
+ * Class Template
+ *
+ * Handle front end templating
+ *
+ * @package PMA
+ */
+class Template
+{
+
+ protected $name = null;
+
+ const BASE_PATH = 'templates/';
+
+ /**
+ * Template constructor
+ *
+ * @param string $name Template name
+ */
+ protected function __construct($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Template getter
+ *
+ * @param string $name Template name
+ *
+ * @return Template
+ */
+ public static function get($name)
+ {
+ return new Template($name);
+ }
+
+ /**
+ * Remove whitespaces between tags and innerHTML
+ *
+ * @param string $content HTML to perform the trim method
+ *
+ * @return string
+ */
+ public static function trim($content)
+ {
+ $regexp = '/(<[^\/][^>]+>)\s+|\s+(<\/)/';
+
+ return preg_replace($regexp, "$1$2", $content);
+ }
+
+ /**
+ * Render template
+ *
+ * @param array $data Variables to provides for template
+ * @param bool $trim Trim content
+ *
+ * @return string
+ */
+ public function render($data = array(), $trim = true)
+ {
+ $template = static::BASE_PATH . $this->name . '.phtml';
+ try {
+ extract($data);
+ ob_start();
+ if (file_exists($template)) {
+ include $template;
+ } else {
+ throw new \LogicException(
+ 'The template "' . $template . '" not found.'
+ );
+ }
+ if ($trim) {
+ $content = Template::trim(ob_get_clean());
+ } else {
+ $content = ob_get_clean();
+ }
+
+ return $content;
+ } catch (\LogicException $e) {
+ ob_end_clean();
+ throw new \LogicException($e->getMessage());
+ }
+ }
+}
diff --git a/libraries/Theme.class.php b/libraries/Theme.class.php
index b60e0f7b15..4a9d8db122 100644
--- a/libraries/Theme.class.php
+++ b/libraries/Theme.class.php
@@ -482,4 +482,3 @@ class PMA_Theme
return implode("\n", $result);
}
}
-?>
diff --git a/libraries/Theme_Manager.class.php b/libraries/Theme_Manager.class.php
index a91fd572c3..cd784977d7 100644
--- a/libraries/Theme_Manager.class.php
+++ b/libraries/Theme_Manager.class.php
@@ -292,36 +292,36 @@ class PMA_Theme_Manager
{
$this->themes = array();
- if ($handleThemes = opendir($this->getThemesPath())) {
- // check for themes directory
- while (false !== ($PMA_Theme = readdir($handleThemes))) {
- // Skip non dirs, . and ..
- if ($PMA_Theme == '.'
- || $PMA_Theme == '..'
- || ! is_dir($this->getThemesPath() . '/' . $PMA_Theme)
- ) {
- continue;
- }
- if (array_key_exists($PMA_Theme, $this->themes)) {
- continue;
- }
- $new_theme = PMA_Theme::load(
- $this->getThemesPath() . '/' . $PMA_Theme
- );
- if ($new_theme) {
- $new_theme->setId($PMA_Theme);
- $this->themes[$PMA_Theme] = $new_theme;
- }
- } // end get themes
- closedir($handleThemes);
- } else {
+ if (false === ($handleThemes = opendir($this->getThemesPath()))) {
trigger_error(
'phpMyAdmin-ERROR: cannot open themes folder: '
. $this->getThemesPath(),
E_USER_WARNING
);
return false;
- } // end check for themes directory
+ }
+
+ // check for themes directory
+ while (false !== ($PMA_Theme = readdir($handleThemes))) {
+ // Skip non dirs, . and ..
+ if ($PMA_Theme == '.'
+ || $PMA_Theme == '..'
+ || ! is_dir($this->getThemesPath() . '/' . $PMA_Theme)
+ ) {
+ continue;
+ }
+ if (array_key_exists($PMA_Theme, $this->themes)) {
+ continue;
+ }
+ $new_theme = PMA_Theme::load(
+ $this->getThemesPath() . '/' . $PMA_Theme
+ );
+ if ($new_theme) {
+ $new_theme->setId($PMA_Theme);
+ $this->themes[$PMA_Theme] = $new_theme;
+ }
+ } // end get themes
+ closedir($handleThemes);
ksort($this->themes);
return true;
@@ -457,4 +457,3 @@ class PMA_Theme_Manager
return false;
}
}
-?>
diff --git a/libraries/Tracker.class.php b/libraries/Tracker.class.php
index e5d295647a..fa9d1368af 100644
--- a/libraries/Tracker.class.php
+++ b/libraries/Tracker.class.php
@@ -187,6 +187,7 @@ class PMA_Tracker
// get Export SQL instance
include_once "libraries/plugin_interface.lib.php";
+ /* @var $export_sql_plugin ExportSql */
$export_sql_plugin = PMA_getPlugin(
"export",
"sql",
@@ -438,7 +439,7 @@ class PMA_Tracker
$result = PMA_queryAsControlUser($sql_query);
- return $result;
+ return (boolean) $result;
}
/**
@@ -541,7 +542,7 @@ class PMA_Tracker
$ddl_date_from = $date = date('Y-m-d H:i:s');
$ddlog = array();
- $i = 0;
+ $first_iteration = true;
// Iterate tracked data definition statements
// For each log entry we want to get date, username and statement
@@ -551,15 +552,15 @@ class PMA_Tracker
$username = /*overload*/mb_substr(
$log_entry, 20, /*overload*/mb_strpos($log_entry, "\n") - 20
);
- if ($i == 0) {
+ if ($first_iteration) {
$ddl_date_from = $date;
+ $first_iteration = false;
}
$statement = rtrim(/*overload*/mb_strstr($log_entry, "\n"));
$ddlog[] = array( 'date' => $date,
'username'=> $username,
'statement' => $statement );
- $i++;
}
}
@@ -569,7 +570,7 @@ class PMA_Tracker
$dml_date_from = $date_from;
$dmlog = array();
- $i = 0;
+ $first_iteration = true;
// Iterate tracked data manipulation statements
// For each log entry we want to get date, username and statement
@@ -579,15 +580,15 @@ class PMA_Tracker
$username = /*overload*/mb_substr(
$log_entry, 20, /*overload*/mb_strpos($log_entry, "\n") - 20
);
- if ($i == 0) {
+ if ($first_iteration) {
$dml_date_from = $date;
+ $first_iteration = false;
}
$statement = rtrim(/*overload*/mb_strstr($log_entry, "\n"));
$dmlog[] = array( 'date' => $date,
'username' => $username,
'statement' => $statement );
- $i++;
}
}
@@ -1027,4 +1028,3 @@ class PMA_Tracker
. '.' . PMA_Util::backquote($cfgRelation['tracking']);
}
}
-?>
diff --git a/libraries/Types.class.php b/libraries/Types.class.php
index 0729a1322b..87c28b9c09 100644
--- a/libraries/Types.class.php
+++ b/libraries/Types.class.php
@@ -317,65 +317,166 @@ class PMA_Types_MySQL extends PMA_Types
$type = /*overload*/mb_strtoupper($type);
switch ($type) {
case 'TINYINT':
- return __('A 1-byte integer, signed range is -128 to 127, unsigned range is 0 to 255');
+ return __(
+ 'A 1-byte integer, signed range is -128 to 127, unsigned range is ' .
+ '0 to 255'
+ );
case 'SMALLINT':
- return __('A 2-byte integer, signed range is -32,768 to 32,767, unsigned range is 0 to 65,535');
+ return __(
+ 'A 2-byte integer, signed range is -32,768 to 32,767, unsigned ' .
+ 'range is 0 to 65,535'
+ );
case 'MEDIUMINT':
- return __('A 3-byte integer, signed range is -8,388,608 to 8,388,607, unsigned range is 0 to 16,777,215');
+ return __(
+ 'A 3-byte integer, signed range is -8,388,608 to 8,388,607, ' .
+ 'unsigned range is 0 to 16,777,215'
+ );
case 'INT':
- return __('A 4-byte integer, signed range is -2,147,483,648 to 2,147,483,647, unsigned range is 0 to 4,294,967,295');
+ return __(
+ 'A 4-byte integer, signed range is ' .
+ '-2,147,483,648 to 2,147,483,647, unsigned range is 0 to ' .
+ '4,294,967,295'
+ );
case 'BIGINT':
- return __('An 8-byte integer, signed range is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, unsigned range is 0 to 18,446,744,073,709,551,615');
+ return __(
+ 'An 8-byte integer, signed range is -9,223,372,036,854,775,808 ' .
+ 'to 9,223,372,036,854,775,807, unsigned range is 0 to ' .
+ '18,446,744,073,709,551,615'
+ );
case 'DECIMAL':
- return __('A fixed-point number (M, D) - the maximum number of digits (M) is 65 (default 10), the maximum number of decimals (D) is 30 (default 0)');
+ return __(
+ 'A fixed-point number (M, D) - the maximum number of digits (M) ' .
+ 'is 65 (default 10), the maximum number of decimals (D) is 30 ' .
+ '(default 0)'
+ );
case 'FLOAT':
- return __('A small floating-point number, allowable values are -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to 3.402823466E+38');
+ return __(
+ 'A small floating-point number, allowable values are ' .
+ '-3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to ' .
+ '3.402823466E+38'
+ );
case 'DOUBLE':
- return __('A double-precision floating-point number, allowable values are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to 1.7976931348623157E+308');
+ return __(
+ 'A double-precision floating-point number, allowable values are ' .
+ '-1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and ' .
+ '2.2250738585072014E-308 to 1.7976931348623157E+308'
+ );
case 'REAL':
- return __('Synonym for DOUBLE (exception: in REAL_AS_FLOAT SQL mode it is a synonym for FLOAT)');
+ return __(
+ 'Synonym for DOUBLE (exception: in REAL_AS_FLOAT SQL mode it is ' .
+ 'a synonym for FLOAT)'
+ );
case 'BIT':
- return __('A bit-field type (M), storing M of bits per value (default is 1, maximum is 64)');
+ return __(
+ 'A bit-field type (M), storing M of bits per value (default is 1, ' .
+ 'maximum is 64)'
+ );
case 'BOOLEAN':
- return __('A synonym for TINYINT(1), a value of zero is considered false, nonzero values are considered true');
+ return __(
+ 'A synonym for TINYINT(1), a value of zero is considered false, ' .
+ 'nonzero values are considered true'
+ );
case 'SERIAL':
return __('An alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE');
case 'DATE':
- return sprintf(__('A date, supported range is %1$s to %2$s'), '1000-01-01', '9999-12-31');
+ return sprintf(
+ __('A date, supported range is %1$s to %2$s'), '1000-01-01',
+ '9999-12-31'
+ );
case 'DATETIME':
- return sprintf(__('A date and time combination, supported range is %1$s to %2$s'), '1000-01-01 00:00:00', '9999-12-31 23:59:59');
+ return sprintf(
+ __('A date and time combination, supported range is %1$s to %2$s'),
+ '1000-01-01 00:00:00', '9999-12-31 23:59:59'
+ );
case 'TIMESTAMP':
- return __('A timestamp, range is 1970-01-01 00:00:01 UTC to 2038-01-09 03:14:07 UTC, stored as the number of seconds since the epoch (1970-01-01 00:00:00 UTC)');
+ return __(
+ 'A timestamp, range is 1970-01-01 00:00:01 UTC to 2038-01-09 ' .
+ '03:14:07 UTC, stored as the number of seconds since the epoch ' .
+ '(1970-01-01 00:00:00 UTC)'
+ );
case 'TIME':
- return sprintf(__('A time, range is %1$s to %2$s'), '-838:59:59', '838:59:59');
+ return sprintf(
+ __('A time, range is %1$s to %2$s'), '-838:59:59', '838:59:59'
+ );
case 'YEAR':
- return __("A year in four-digit (4, default) or two-digit (2) format, the allowable values are 70 (1970) to 69 (2069) or 1901 to 2155 and 0000");
+ return __(
+ "A year in four-digit (4, default) or two-digit (2) format, the " .
+ "allowable values are 70 (1970) to 69 (2069) or 1901 to 2155 and " .
+ "0000"
+ );
case 'CHAR':
- return __('A fixed-length (0-255, default 1) string that is always right-padded with spaces to the specified length when stored');
+ return __(
+ 'A fixed-length (0-255, default 1) string that is always ' .
+ 'right-padded with spaces to the specified length when stored'
+ );
case 'VARCHAR':
- return sprintf(__('A variable-length (%s) string, the effective maximum length is subject to the maximum row size'), '0-65,535');
+ return sprintf(
+ __(
+ 'A variable-length (%s) string, the effective maximum length ' .
+ 'is subject to the maximum row size'
+ ), '0-65,535'
+ );
case 'TINYTEXT':
- return __('A TEXT column with a maximum length of 255 (2^8 - 1) characters, stored with a one-byte prefix indicating the length of the value in bytes');
+ return __(
+ 'A TEXT column with a maximum length of 255 (2^8 - 1) characters, ' .
+ 'stored with a one-byte prefix indicating the length of the value ' .
+ 'in bytes'
+ );
case 'TEXT':
- return __('A TEXT column with a maximum length of 65,535 (2^16 - 1) characters, stored with a two-byte prefix indicating the length of the value in bytes');
+ return __(
+ 'A TEXT column with a maximum length of 65,535 (2^16 - 1) ' .
+ 'characters, stored with a two-byte prefix indicating the length ' .
+ 'of the value in bytes'
+ );
case 'MEDIUMTEXT':
- return __('A TEXT column with a maximum length of 16,777,215 (2^24 - 1) characters, stored with a three-byte prefix indicating the length of the value in bytes');
+ return __(
+ 'A TEXT column with a maximum length of 16,777,215 (2^24 - 1) ' .
+ 'characters, stored with a three-byte prefix indicating the ' .
+ 'length of the value in bytes'
+ );
case 'LONGTEXT':
- return __('A TEXT column with a maximum length of 4,294,967,295 or 4GiB (2^32 - 1) characters, stored with a four-byte prefix indicating the length of the value in bytes');
+ return __(
+ 'A TEXT column with a maximum length of 4,294,967,295 or 4GiB ' .
+ '(2^32 - 1) characters, stored with a four-byte prefix indicating ' .
+ 'the length of the value in bytes'
+ );
case 'BINARY':
- return __('Similar to the CHAR type, but stores binary byte strings rather than non-binary character strings');
+ return __(
+ 'Similar to the CHAR type, but stores binary byte strings rather ' .
+ 'than non-binary character strings'
+ );
case 'VARBINARY':
- return __('Similar to the VARCHAR type, but stores binary byte strings rather than non-binary character strings');
+ return __(
+ 'Similar to the VARCHAR type, but stores binary byte strings ' .
+ 'rather than non-binary character strings'
+ );
case 'TINYBLOB':
- return __('A BLOB column with a maximum length of 255 (2^8 - 1) bytes, stored with a one-byte prefix indicating the length of the value');
+ return __(
+ 'A BLOB column with a maximum length of 255 (2^8 - 1) bytes, ' .
+ 'stored with a one-byte prefix indicating the length of the value'
+ );
case 'MEDIUMBLOB':
- return __('A BLOB column with a maximum length of 16,777,215 (2^24 - 1) bytes, stored with a three-byte prefix indicating the length of the value');
+ return __(
+ 'A BLOB column with a maximum length of 16,777,215 (2^24 - 1) ' .
+ 'bytes, stored with a three-byte prefix indicating the length of ' .
+ 'the value'
+ );
case 'BLOB':
- return __('A BLOB column with a maximum length of 65,535 (2^16 - 1) bytes, stored with a two-byte prefix indicating the length of the value');
+ return __(
+ 'A BLOB column with a maximum length of 65,535 (2^16 - 1) bytes, ' .
+ 'stored with a two-byte prefix indicating the length of the value'
+ );
case 'LONGBLOB':
- return __('A BLOB column with a maximum length of 4,294,967,295 or 4GiB (2^32 - 1) bytes, stored with a four-byte prefix indicating the length of the value');
+ return __(
+ 'A BLOB column with a maximum length of 4,294,967,295 or 4GiB ' .
+ '(2^32 - 1) bytes, stored with a four-byte prefix indicating the ' .
+ 'length of the value'
+ );
case 'ENUM':
- return __("An enumeration, chosen from the list of up to 65,535 values or the special '' error value");
+ return __(
+ "An enumeration, chosen from the list of up to 65,535 values or " .
+ "the special '' error value"
+ );
case 'SET':
return __("A single value chosen from a set of up to 64 members");
case 'GEOMETRY':
@@ -389,7 +490,9 @@ class PMA_Types_MySQL extends PMA_Types
case 'MULTIPOINT':
return __('A collection of points');
case 'MULTILINESTRING':
- return __('A collection of curves with linear interpolation between points');
+ return __(
+ 'A collection of curves with linear interpolation between points'
+ );
case 'MULTIPOLYGON':
return __('A collection of polygons');
case 'GEOMETRYCOLLECTION':
@@ -474,7 +577,7 @@ class PMA_Types_MySQL extends PMA_Types
{
switch ($class) {
case 'CHAR':
- return array(
+ $ret = array(
'AES_DECRYPT',
'AES_ENCRYPT',
'BIN',
@@ -487,6 +590,7 @@ class PMA_Types_MySQL extends PMA_Types
'DES_ENCRYPT',
'ENCRYPT',
'HEX',
+ 'INET6_NTOA',
'INET_NTOA',
'LOAD_FILE',
'LOWER',
@@ -510,6 +614,13 @@ class PMA_Types_MySQL extends PMA_Types
'VERSION',
);
+ if ((PMA_MARIADB && PMA_MYSQL_INT_VERSION < 100012)
+ || PMA_MYSQL_INT_VERSION < 50603
+ ) {
+ $ret = array_diff($ret, array('INET6_NTOA'));
+ }
+ return $ret;
+
case 'DATE':
return array(
'CURRENT_DATE',
@@ -551,6 +662,7 @@ class PMA_Types_MySQL extends PMA_Types
'EXP',
'FLOOR',
'HOUR',
+ 'INET6_ATON',
'INET_ATON',
'LENGTH',
'LN',
@@ -583,6 +695,11 @@ class PMA_Types_MySQL extends PMA_Types
'WEEKOFYEAR',
'YEARWEEK',
);
+ if ((PMA_MARIADB && PMA_MYSQL_INT_VERSION < 100012)
+ || PMA_MYSQL_INT_VERSION < 50603
+ ) {
+ $ret = array_diff($ret, array('INET6_ATON'));
+ }
return $ret;
case 'SPATIAL':
@@ -767,9 +884,16 @@ class PMA_Types_Drizzle extends PMA_Types
case 'INTEGER':
return __('A 4-byte integer, range is -2,147,483,648 to 2,147,483,647');
case 'BIGINT':
- return __('An 8-byte integer, range is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807');
+ return __(
+ 'An 8-byte integer, range is -9,223,372,036,854,775,808 to ' .
+ '9,223,372,036,854,775,807'
+ );
case 'DECIMAL':
- return __('A fixed-point number (M, D) - the maximum number of digits (M) is 65 (default 10), the maximum number of decimals (D) is 30 (default 0)');
+ return __(
+ 'A fixed-point number (M, D) - the maximum number of digits ' .
+ '(M) is 65 (default 10), the maximum number of decimals (D) ' .
+ 'is 30 (default 0)'
+ );
case 'DOUBLE':
return __("A system's default double-precision floating-point number");
case 'BOOLEAN':
@@ -779,24 +903,54 @@ class PMA_Types_Drizzle extends PMA_Types
case 'UUID':
return __('Stores a Universally Unique Identifier (UUID)');
case 'DATE':
- return sprintf(__('A date, supported range is %1$s to %2$s'), '0001-01-01', '9999-12-31');
+ return sprintf(
+ __('A date, supported range is %1$s to %2$s'), '0001-01-01',
+ '9999-12-31'
+ );
case 'DATETIME':
- return sprintf(__('A date and time combination, supported range is %1$s to %2$s'), '0001-01-01 00:00:0', '9999-12-31 23:59:59');
+ return sprintf(
+ __(
+ 'A date and time combination, supported range is %1$s to ' .
+ '%2$s'
+ ), '0001-01-01 00:00:0', '9999-12-31 23:59:59'
+ );
case 'TIMESTAMP':
- return __("A timestamp, range is '0001-01-01 00:00:00' UTC to '9999-12-31 23:59:59' UTC; TIMESTAMP(6) can store microseconds");
+ return __(
+ "A timestamp, range is '0001-01-01 00:00:00' UTC to " .
+ "'9999-12-31 23:59:59' UTC; TIMESTAMP(6) can store microseconds"
+ );
case 'TIME':
- return sprintf(__('A time, range is %1$s to %2$s'), '00:00:00', '23:59:59');
+ return sprintf(
+ __('A time, range is %1$s to %2$s'), '00:00:00', '23:59:59'
+ );
case 'VARCHAR':
- return sprintf(__('A variable-length (%s) string, the effective maximum length is subject to the maximum row size'), '0-16,383');
+ return sprintf(
+ __(
+ 'A variable-length (%s) string, the effective ' .
+ 'maximum length is subject to the maximum row size'
+ ), '0-16,383'
+ );
case 'TEXT':
- return __('A TEXT column with a maximum length of 65,535 (2^16 - 1) characters, stored with a two-byte prefix indicating the length of the value in bytes');
+ return __(
+ 'A TEXT column with a maximum length of 65,535 (2^16 - 1) ' .
+ 'characters, stored with a two-byte prefix indicating the ' .
+ 'length of the value in bytes'
+ );
case 'VARBINARY':
- return __('A variable-length (0-65,535) string, uses binary collation for all comparisons');
+ return __(
+ 'A variable-length (0-65,535) string, uses binary collation ' .
+ 'for all comparisons'
+ );
case 'BLOB':
- return __('A BLOB column with a maximum length of 65,535 (2^16 - 1) bytes, stored with a two-byte prefix indicating the length of the value');
+ return __(
+ 'A BLOB column with a maximum length of 65,535 (2^16 - 1) ' .
+ 'bytes, stored with a two-byte prefix indicating the length of ' .
+ 'the value'
+ );
case 'ENUM':
return __("An enumeration, chosen from the list of defined values");
}
+
return '';
}
@@ -1024,7 +1178,7 @@ class PMA_Types_Drizzle extends PMA_Types
'-',
'ENUM',
);
- if (PMA_MYSQL_INT_VERSION >= 20120130) {
+ if (PMA_MYSQL_INT_VERSION >= 70132) {
$types_string[] = '-';
$types_string[] = 'IPV6';
}
diff --git a/libraries/Util.class.php b/libraries/Util.class.php
index 04e504ef9b..516a71dbf1 100644
--- a/libraries/Util.class.php
+++ b/libraries/Util.class.php
@@ -9,6 +9,9 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/Template.class.php';
+use PMA\Template;
+
/**
* Misc functions used all over the scripts.
*
@@ -144,7 +147,7 @@ class PMA_Util
$button .= self::getImage($icon, $alternate);
}
if ($include_icon && $include_text) {
- $button .= ' ';
+ $button .= '&nbsp;';
}
if ($include_text) {
$button .= $alternate;
@@ -451,7 +454,9 @@ class PMA_Util
$mysql = '5.5';
$lang = 'en';
if (defined('PMA_MYSQL_INT_VERSION')) {
- if (PMA_MYSQL_INT_VERSION >= 50600) {
+ if (PMA_MYSQL_INT_VERSION >= 50700) {
+ $mysql = '5.7';
+ } else if (PMA_MYSQL_INT_VERSION >= 50600) {
$mysql = '5.6';
} else if (PMA_MYSQL_INT_VERSION >= 50500) {
$mysql = '5.5';
@@ -582,68 +587,109 @@ class PMA_Util
* Displays a MySQL error message in the main panel when $exit is true.
* Returns the error message otherwise.
*
- * @param string|bool $error_message the error message
- * @param string $the_query the sql query that failed
- * @param bool $is_modify_link whether to show a "modify" link or not
- * @param string $back_url the "back" link url (full path is not
- * required)
- * @param bool $exit EXIT the page?
+ * @param string|bool $server_msg Server's error message.
+ * @param string $sql_query The SQL query that failed.
+ * @param bool $is_modify_link Whether to show a "modify" link or not.
+ * @param string $back_url URL for the "back" link (full path is
+ * not required).
+ * @param bool $exit Whether execution should be stopped or
+ * the error message should be returned.
*
* @return string
*
- * @global string $table the curent table
- * @global string $db the current db
+ * @global string $table The current table.
+ * @global string $db The current database.
*
* @access public
*/
public static function mysqlDie(
- $error_message = '', $the_query = '',
+ $server_msg = '', $sql_query = '',
$is_modify_link = true, $back_url = '', $exit = true
) {
global $table, $db;
+ /**
+ * Error message to be built.
+ * @var string $error_msg
+ */
$error_msg = '';
- if (! $error_message) {
- $error_message = $GLOBALS['dbi']->getError();
+ // Checking for any server errors.
+ if (empty($server_msg)) {
+ $server_msg = $GLOBALS['dbi']->getError();
+ }
+
+ // Finding the query that failed, if not specified.
+ if ((empty($sql_query) && (!empty($GLOBALS['sql_query'])))) {
+ $sql_query = $GLOBALS['sql_query'];
}
- if (! $the_query && ! empty($GLOBALS['sql_query'])) {
- $the_query = $GLOBALS['sql_query'];
+ $sql_query = trim($sql_query);
+
+ $errors = array();
+ if (! empty($sql_query)) {
+ /**
+ * The lexer used for analysis.
+ * @var SqlParser\Lexer $lexer
+ */
+ $lexer = new SqlParser\Lexer($sql_query);
+
+ /**
+ * The parser used for analysis.
+ * @var SqlParser\Parser $parser
+ */
+ $parser = new SqlParser\Parser($lexer->list);
+
+ /**
+ * The errors found by the lexer and the parser.
+ * @var array $errors
+ */
+ $errors = SqlParser\Utils\Error::get(array($lexer, $parser));
}
- // --- Added to solve bug #641765
- if (! function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
- $formatted_sql = htmlspecialchars($the_query);
- } elseif (empty($the_query) || (trim($the_query) == '')) {
+ if (empty($sql_query)) {
$formatted_sql = '';
+ } elseif (count($errors)) {
+ $formatted_sql = htmlspecialchars($sql_query);
} else {
- $formatted_sql = self::formatSql($the_query, true);
- }
- // ---
- $error_msg .= "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
- $error_msg .= ' <div class="error"><h1>' . __('Error')
- . '</h1>' . "\n";
-
- // if the config password is wrong, or the MySQL server does not
- // respond, do not show the query that would reveal the
- // username/password
- if (! empty($the_query) && ! /*overload*/mb_strstr($the_query, 'connect')) {
- // --- Added to solve bug #641765
- if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
- $error_msg .= PMA_SQP_getErrorString() . "\n";
- $error_msg .= '<br />' . "\n";
+ $formatted_sql = self::formatSql($sql_query, true);
+ }
+
+ $error_msg .= '<div class="error"><h1>' . __('Error') . '</h1>';
+
+ // For security reasons, if the MySQL refuses the connection, the query
+ // is hidden so no details are revealed.
+ if ((!empty($sql_query)) && (!(mb_strstr($sql_query, 'connect')))) {
+
+ // Static analysis errors.
+ if (!empty($errors)) {
+ $error_msg .= '<p><strong>' . __('Static analysis:')
+ . '</strong></p>';
+ $error_msg .= '<p>' . sprintf(
+ __('%d errors were found during analysis.'), count($errors)
+ ) . '</p>';
+ $error_msg .= '<p><ol>';
+ $error_msg .= implode(
+ SqlParser\Utils\Error::format(
+ $errors,
+ '<li>%2$s (near "%4$s" at position %5$d)</li>'
+ )
+ );
+ $error_msg .= '</ol></p>';
}
- // ---
- // modified to show the help on sql errors
+
+ // Display the SQL query and link to MySQL documentation.
$error_msg .= '<p><strong>' . __('SQL query:') . '</strong>' . "\n";
$formattedSqlToLower = /*overload*/mb_strtolower($formatted_sql);
+
+ // TODO: Show documentation for all statement types.
if (/*overload*/mb_strstr($formattedSqlToLower, 'select')) {
// please show me help to the error on select
$error_msg .= self::showMySQLDocu('SELECT');
}
+
if ($is_modify_link) {
$_url_params = array(
- 'sql_query' => $the_query,
+ 'sql_query' => $sql_query,
'show_query' => 1,
);
if (/*overload*/mb_strlen($table)) {
@@ -663,46 +709,47 @@ class PMA_Util
$error_msg .= $doedit_goto
. self::getIcon('b_edit.png', __('Edit'))
. '</a>';
- } // end if
+ }
+
$error_msg .= ' </p>' . "\n"
. '<p>' . "\n"
. $formatted_sql . "\n"
. '</p>' . "\n";
- } // end if
+ }
- if (! empty($error_message)) {
- $error_message = preg_replace(
+ // Display server's error.
+ if (!empty($server_msg)) {
+ $server_msg = preg_replace(
"@((\015\012)|(\015)|(\012)){3,}@",
"\n\n",
- $error_message
+ $server_msg
+ );
+
+ // Adds a link to MySQL documentation.
+ $error_msg .= '<p>' . "\n"
+ . ' <strong>' . __('MySQL said: ') . '</strong>'
+ . self::showMySQLDocu('Error-messages-server')
+ . "\n"
+ . '</p>' . "\n";
+
+ // The error message will be displayed within a CODE segment.
+ // To preserve original formatting, but allow word-wrapping,
+ // a couple of replacements are done.
+ // All non-single blanks and TAB-characters are replaced with their
+ // HTML-counterpart
+ $server_msg = str_replace(
+ array(' ', "\t"),
+ array('&nbsp;&nbsp;', '&nbsp;&nbsp;&nbsp;&nbsp;'),
+ $server_msg
);
+
+ // Replace line breaks
+ $server_msg = nl2br($server_msg);
+
+ $error_msg .= '<code>' . $server_msg . '</code><br/>';
}
- // modified to show the help on error-returns
- // (now error-messages-server)
- $error_msg .= '<p>' . "\n"
- . ' <strong>' . __('MySQL said: ') . '</strong>'
- . self::showMySQLDocu('Error-messages-server')
- . "\n"
- . '</p>' . "\n";
-
- // The error message will be displayed within a CODE segment.
- // To preserve original formatting, but allow wordwrapping,
- // we do a couple of replacements
-
- // Replace all non-single blanks with their HTML-counterpart
- $error_message = str_replace(' ', '&nbsp;&nbsp;', $error_message);
- // Replace TAB-characters with their HTML-counterpart
- $error_message = str_replace(
- "\t", '&nbsp;&nbsp;&nbsp;&nbsp;', $error_message
- );
- // Replace line breaks
- $error_message = nl2br($error_message);
- $error_msg .= '<code>' . "\n"
- . $error_message . "\n"
- . '</code><br />' . "\n";
$error_msg .= '</div>';
-
$_SESSION['Import_message']['message'] = $error_msg;
if (!$exit) {
@@ -710,19 +757,17 @@ class PMA_Util
}
/**
- * If in an Ajax request
- * - avoid displaying a Back link
- * - use PMA_Response() to transmit the message and exit
+ * If this is an AJAX request, there is no "Back" link and
+ * `PMA_Response()` is used to send the response.
*/
- if (isset($GLOBALS['is_ajax_request'])
- && $GLOBALS['is_ajax_request'] == true
- ) {
+ if (!empty($GLOBALS['is_ajax_request'])) {
$response = PMA_Response::getInstance();
$response->isSuccess(false);
$response->addJSON('message', $error_msg);
exit;
}
- if (! empty($back_url)) {
+
+ if (!empty($back_url)) {
if (/*overload*/mb_strstr($back_url, '?')) {
$back_url .= '&amp;no_history=true';
} else {
@@ -735,9 +780,43 @@ class PMA_Util
. '[ <a href="' . $back_url . '">' . __('Back') . '</a> ]'
. '</fieldset>' . "\n\n";
}
- echo $error_msg;
- exit;
- } // end of the 'mysqlDie()' function
+
+ exit($error_msg);
+ }
+
+ /**
+ * Check the correct row count
+ *
+ * @param string $db the db name
+ * @param array $table the table infos
+ *
+ * @return int $rowCount the possibly modified row count
+ *
+ */
+ private static function _checkRowCount($db, $table)
+ {
+ $rowCount = 0;
+
+ if ($table['Rows'] === null) {
+ // Do not check exact row count here,
+ // if row count is invalid possibly the table is defect
+ // and this would break the navigation panel;
+ // but we can check row count if this is a view or the
+ // information_schema database
+ // since PMA_Table::countRecords() returns a limited row count
+ // in this case.
+
+ // set this because PMA_Table::countRecords() can use it
+ $tbl_is_view = $table['TABLE_TYPE'] == 'VIEW';
+
+ if ($tbl_is_view || $GLOBALS['dbi']->isSystemSchema($db)) {
+ $rowCount = $GLOBALS['dbi']
+ ->getTable($db, $table['Name'])
+ ->countRecords();
+ }
+ }
+ return $rowCount;
+ }
/**
* returns array with tables of given db with extended information and grouped
@@ -777,28 +856,7 @@ class PMA_Util
$table_groups = array();
foreach ($tables as $table_name => $table) {
- // check for correct row count
- if ($table['Rows'] === null) {
- // Do not check exact row count here,
- // if row count is invalid possibly the table is defect
- // and this would break left frame;
- // but we can check row count if this is a view or the
- // information_schema database
- // since PMA_Table::countRecords() returns a limited row count
- // in this case.
-
- // set this because PMA_Table::countRecords() can use it
- $tbl_is_view = $table['TABLE_TYPE'] == 'VIEW';
-
- if ($tbl_is_view || $GLOBALS['dbi']->isSystemSchema($db)) {
- $table['Rows'] = PMA_Table::countRecords(
- $db,
- $table['Name'],
- false,
- true
- );
- }
- }
+ $table['Rows'] = self::_checkRowCount($db, $table);
// in $group we save the reference to the place in $table_groups
// where to store the table info
@@ -888,9 +946,8 @@ class PMA_Util
}
if (! $do_it) {
- global $PMA_SQPdata_forbidden_word;
- $eltNameUpper = /*overload*/mb_strtoupper($a_name);
- if (!in_array($eltNameUpper, $PMA_SQPdata_forbidden_word)) {
+ if (!(SqlParser\Context::isKeyword($a_name) & SqlParser\Token::FLAG_KEYWORD_RESERVED)
+ ) {
return $a_name;
}
}
@@ -935,9 +992,7 @@ class PMA_Util
}
if (! $do_it) {
- global $PMA_SQPdata_forbidden_word;
- $eltNameUpper = /*overload*/mb_strtoupper($a_name);
- if (!in_array($eltNameUpper, $PMA_SQPdata_forbidden_word)) {
+ if (!SqlParser\Context::isKeyword($a_name)) {
return $a_name;
}
}
@@ -985,9 +1040,9 @@ class PMA_Util
* Prepare the message and the query
* usually the message is the result of the query executed
*
- * @param string $message the message to display
- * @param string $sql_query the query to display
- * @param string $type the type (level) of the message
+ * @param PMA_Message|string $message the message to display
+ * @param string $sql_query the query to display
+ * @param string $type the type (level) of the message
*
* @return string
*
@@ -1072,56 +1127,6 @@ class PMA_Util
) . '[...]'
)
);
- } elseif (! empty($GLOBALS['parsed_sql'])
- && $query_base == $GLOBALS['parsed_sql']['raw']
- ) {
- // (here, use "! empty" because when deleting a bookmark,
- // $GLOBALS['parsed_sql'] is set but empty
- $parsed_sql = $GLOBALS['parsed_sql'];
- } else {
- // Parse SQL if needed
- $parsed_sql = PMA_SQP_parse($query_base);
- }
-
- // Analyze it
- if (isset($parsed_sql) && ! PMA_SQP_isError()) {
- $analyzed_display_query = PMA_SQP_analyze($parsed_sql);
-
- // Same as below (append LIMIT), append the remembered ORDER BY
- if ($GLOBALS['cfg']['RememberSorting']
- && isset($analyzed_display_query[0]['queryflags']['select_from'])
- && isset($GLOBALS['sql_order_to_append'])
- ) {
- $query_base = $analyzed_display_query[0]['section_before_limit']
- . "\n" . $GLOBALS['sql_order_to_append']
- . $analyzed_display_query[0]['limit_clause'] . ' '
- . $analyzed_display_query[0]['section_after_limit'];
- // update the $analyzed_display_query
- $analyzed_display_query[0]['section_before_limit']
- .= $GLOBALS['sql_order_to_append'];
- $analyzed_display_query[0]['order_by_clause']
- = $GLOBALS['sorted_col'];
- }
-
- // Here we append the LIMIT added for navigation, to
- // enable its display. Adding it higher in the code
- // to $sql_query would create a problem when
- // using the Refresh or Edit links.
-
- // Only append it on SELECTs.
-
- /**
- * @todo what would be the best to do when someone hits Refresh:
- * use the current LIMITs ?
- */
-
- if (isset($analyzed_display_query[0]['queryflags']['select_from'])
- && ! empty($GLOBALS['sql_limit_to_append'])
- ) {
- $query_base = $analyzed_display_query[0]['section_before_limit']
- . "\n" . $GLOBALS['sql_limit_to_append']
- . $analyzed_display_query[0]['section_after_limit'];
- }
}
if (! empty($GLOBALS['show_as_php'])) {
@@ -1160,19 +1165,32 @@ class PMA_Util
$explain_params = $url_params;
if ($is_select) {
$explain_params['sql_query'] = 'EXPLAIN ' . $sql_query;
- $_message = __('Explain SQL');
+ $explain_link = ' ['
+ . self::linkOrButton(
+ 'import.php' . PMA_URL_getCommon($explain_params),
+ __('Explain SQL')
+ ) . ']';
} elseif (preg_match(
'@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $sql_query
)) {
$explain_params['sql_query']
= /*overload*/mb_substr($sql_query, 8);
- $_message = __('Skip Explain SQL');
- }
- if (isset($explain_params['sql_query']) && isset($_message)) {
$explain_link = ' ['
. self::linkOrButton(
'import.php' . PMA_URL_getCommon($explain_params),
- $_message
+ __('Skip Explain SQL')
+ ) . ']';
+ $url = 'https://mariadb.org/explain_analyzer/analyze/'
+ . '?client=phpMyAdmin&raw_explain='
+ . urlencode(self::_generateRowQueryOutput($sql_query));
+ $explain_link .= ' ['
+ . self::linkOrButton(
+ 'url.php?url=' . urlencode($url),
+ sprintf(__('Analyze Explain at %s'), 'mariadb.org'),
+ array(),
+ true,
+ false,
+ '_blank'
) . ']';
}
} //show explain
@@ -1202,7 +1220,7 @@ class PMA_Util
$_message = __('Without PHP Code');
} else {
$php_params['show_as_php'] = 1;
- $_message = __('Create PHP Code');
+ $_message = __('Create PHP code');
}
$php_link = 'import.php' . PMA_URL_getCommon($php_params);
@@ -1246,7 +1264,7 @@ class PMA_Util
}
$retval .= '</div>';
- $retval .= '<div class="tools">';
+ $retval .= '<div class="tools print_ignore">';
$retval .= '<form action="sql.php" method="post">';
$retval .= PMA_URL_getHiddenInputs(
$GLOBALS['db'], $GLOBALS['table']
@@ -1292,6 +1310,44 @@ class PMA_Util
} // end of the 'getMessage()' function
/**
+ * Execute an EXPLAIN query and formats results similar to MySQL command line
+ * utility.
+ *
+ * @param string $sqlQuery EXPLAIN query
+ *
+ * @return string query resuls
+ */
+ private static function _generateRowQueryOutput($sqlQuery)
+ {
+ $ret = '';
+ $result = $GLOBALS['dbi']->query($sqlQuery);
+ if ($result) {
+ $devider = '+';
+ $columnNames = '|';
+ $fieldsMeta = $GLOBALS['dbi']->getFieldsMeta($result);
+ foreach ($fieldsMeta as $meta) {
+ $devider .= '---+';
+ $columnNames .= ' ' . $meta->name . ' |';
+ }
+ $devider .= "\n";
+
+ $ret .= $devider . $columnNames . "\n" . $devider;
+ while ($row = $GLOBALS['dbi']->fetchRow($result)) {
+ $values = '|';
+ foreach ($row as $value) {
+ if (is_null($value)) {
+ $value = 'NULL';
+ }
+ $values .= ' ' . $value . ' |';
+ }
+ $ret .= $values . "\n";
+ }
+ $ret .= $devider;
+ }
+ return $ret;
+ }
+
+ /**
* Verifies if current MySQL server supports profiling
*
* @access public
@@ -1305,7 +1361,7 @@ class PMA_Util
// (avoid a trip to the server for MySQL before 5.0.37)
// and do not set a constant as we might be switching servers
if (defined('PMA_MYSQL_INT_VERSION')
- && $GLOBALS['dbi']->fetchValue("SHOW VARIABLES LIKE 'profiling'")
+ && $GLOBALS['dbi']->fetchValue("SELECT @@profiling")
) {
self::cacheSet('profiling_supported', true);
} else {
@@ -1503,11 +1559,14 @@ class PMA_Util
);
} else {
//number_format is not multibyte safe, str_replace is safe
- $localizedValue = self::localizeNumber(number_format($value, $digits_right));
+ $localizedValue = self::localizeNumber(
+ number_format($value, $digits_right)
+ );
}
if ($originalValue != 0 && floatval($value) == 0) {
- return ' <' . self::localizeNumber((1 / self::pow(10, $digits_right))) . ' ' . $unit;
+ return ' <' . self::localizeNumber((1 / self::pow(10, $digits_right)))
+ . ' ' . $unit;
}
return $sign . $localizedValue . ' ' . $unit;
@@ -1707,21 +1766,27 @@ class PMA_Util
}
//Set the id for the tab, if set in the params
- $id_string = ( empty($tab['id']) ? '' : ' id="' . $tab['id'] . '" ' );
- $out = '<li' . ($tab['class'] == 'active' ? ' class="active"' : '') . '>';
-
- if (! empty($tab['link'])) {
- $out .= '<a class="tab' . htmlentities($tab['class']) . '"'
- . $id_string
- . ' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
- . $tab['text'] . '</a>';
+ $tabId = (empty($tab['id']) ? null : $tab['id']);
+
+ $item = array();
+ if (!empty($tab['link'])) {
+ $item = array(
+ 'content' => $tab['text'],
+ 'url' => array(
+ 'href' => empty($tab['link']) ? null : $tab['link'],
+ 'id' => $tabId,
+ 'class' => 'tab' . htmlentities($tab['class']),
+ ),
+ );
} else {
- $out .= '<span class="tab' . htmlentities($tab['class']) . '"'
- . $id_string . '>' . $tab['text'] . '</span>';
+ $item['content'] = '<span class="tab' . htmlentities($tab['class']) . '"'
+ . $tabId . '>' . $tab['text'] . '</span>';
}
- $out .= '</li>';
- return $out;
+ $item['class'] = $tab['class'] == 'active' ? 'active' : '';
+
+ return Template::get('list/item')
+ ->render($item);
} // end of the 'getHtmlTab()' function
/**
@@ -1817,13 +1882,15 @@ class PMA_Util
if ($suhosin_get_MaxValueLength) {
$query_parts = self::splitURLQuery($url);
foreach ($query_parts as $query_pair) {
- if (strpos($query_pair, '=') !== false) {
- list(, $eachval) = explode('=', $query_pair);
- if (/*overload*/mb_strlen($eachval) > $suhosin_get_MaxValueLength
- ) {
- $in_suhosin_limits = false;
- break;
- }
+ if (strpos($query_pair, '=') === false) {
+ continue;
+ }
+
+ list(, $eachval) = explode('=', $query_pair);
+ if (/*overload*/mb_strlen($eachval) > $suhosin_get_MaxValueLength
+ ) {
+ $in_suhosin_limits = false;
+ break;
}
}
}
@@ -1856,6 +1923,9 @@ class PMA_Util
$url_parts = parse_url($url);
if ($new_form) {
+ if ($target) {
+ $target = ' target="' . $target . '"';
+ }
$ret = '<form action="' . $url_parts['path'] . '" class="link"'
. ' method="post"' . $target . ' style="display: inline;">';
$subname_open = '';
@@ -2071,22 +2141,24 @@ class PMA_Util
/**
* Function to generate unique condition for specified row.
*
- * @param resource $handle current query result
- * @param integer $fields_cnt number of fields
- * @param array $fields_meta meta information about fields
- * @param array $row current row
- * @param boolean $force_unique generate condition only on pk or
- * unique
- * @param string|boolean $restrict_to_table restrict the unique condition to
- * this table or false if none
+ * @param resource $handle current query result
+ * @param integer $fields_cnt number of fields
+ * @param array $fields_meta meta information about fields
+ * @param array $row current row
+ * @param boolean $force_unique generate condition only on pk
+ * or unique
+ * @param string|boolean $restrict_to_table restrict the unique condition
+ * to this table or false if
+ * none
+ * @param array $analyzed_sql_results the analyzed query
*
* @access public
*
- * @return array the calculated condition and whether condition is unique
+ * @return array the calculated condition and whether condition is unique
*/
public static function getUniqueCondition(
$handle, $fields_cnt, $fields_meta, $row, $force_unique = false,
- $restrict_to_table = false
+ $restrict_to_table = false, $analyzed_sql_results = null
) {
$primary_key = '';
$unique_key = '';
@@ -2107,19 +2179,16 @@ class PMA_Util
if (! isset($meta->orgname) || ! /*overload*/mb_strlen($meta->orgname)) {
$meta->orgname = $meta->name;
- if (isset($GLOBALS['analyzed_sql'][0]['select_expr'])
- && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])
- ) {
- foreach (
- $GLOBALS['analyzed_sql'][0]['select_expr'] as $select_expr
- ) {
- // need (string) === (string)
- // '' !== 0 but '' == 0
- if ((string)$select_expr['alias'] === (string)$meta->name) {
- $meta->orgname = $select_expr['column'];
+ if (!empty($analyzed_sql_results['statement']->expr)) {
+ foreach ($analyzed_sql_results['statement']->expr as $expr) {
+ if ((empty($expr->alias)) || (empty($expr->column))) {
+ continue;
+ }
+ if (strcasecmp($meta->name, $expr->alias) == 0) {
+ $meta->orgname = $expr->column;
break;
- } // end if
- } // end foreach
+ }
+ }
}
}
@@ -2136,7 +2205,7 @@ class PMA_Util
// because there is some caching in the function).
if (isset($meta->orgtable)
&& ($meta->table != $meta->orgtable)
- && ! PMA_Table::isView($GLOBALS['db'], $meta->table)
+ && ! $GLOBALS['dbi']->getTable($GLOBALS['db'], $meta->table)->isView()
) {
$meta->table = $meta->orgtable;
}
@@ -2583,7 +2652,10 @@ class PMA_Util
$database = self::unescapeMysqlWildcards($database);
}
- return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
+ return '<a href="'
+ . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ )
. PMA_URL_getCommon(array('db' => $database)) . '" title="'
. htmlspecialchars(
sprintf(
@@ -2884,15 +2956,21 @@ class PMA_Util
/**
* Gets cached information from the session
*
- * @param string $var variable name
+ * @param string $var variable name
+ * @param Closure $callback callback to fetch the value
*
* @return mixed
*/
- public static function cacheGet($var)
+ public static function cacheGet($var, $callback = null)
{
- if (isset($_SESSION['cache']['server_' . $GLOBALS['server']][$var])) {
+ if (self::cacheExists($var)) {
return $_SESSION['cache']['server_' . $GLOBALS['server']][$var];
} else {
+ if ($callback) {
+ $val = $callback();
+ self::cacheSet($var, $val);
+ return $val;
+ }
return null;
}
}
@@ -3085,7 +3163,7 @@ class PMA_Util
$displayed_type .= htmlspecialchars(
/*overload*/mb_substr(
$printtype, 0, $GLOBALS['cfg']['LimitChars']
- )
+ ) . '...'
);
$displayed_type .= '</abbr>';
}
@@ -3117,9 +3195,7 @@ class PMA_Util
if (($engine == 'INNODB') || ($engine == 'PBXT')) {
return true;
} elseif ($engine == 'NDBCLUSTER' || $engine == 'NDB') {
- $ndbver = $GLOBALS['dbi']->fetchValue(
- "SHOW VARIABLES LIKE 'ndb_version_string'"
- );
+ $ndbver = $GLOBALS['dbi']->fetchValue("SELECT @@ndb_version_string");
return ($ndbver >= 7.3);
} else {
return false;
@@ -3127,6 +3203,73 @@ class PMA_Util
}
/**
+ * Is Foreign key check enabled?
+ *
+ * @return bool
+ */
+ public static function isForeignKeyCheck()
+ {
+ if ($GLOBALS['cfg']['DefaultForeignKeyChecks'] === 'enable') {
+ return true;
+ } else if ($GLOBALS['cfg']['DefaultForeignKeyChecks'] === 'disable') {
+ return false;
+ }
+ return ($GLOBALS['dbi']->getVariable('FOREIGN_KEY_CHECKS') == 'ON');
+ }
+
+ /**
+ * Get HTML for Foreign key check checkbox
+ *
+ * @return string HTML for checkbox
+ */
+ public static function getFKCheckbox()
+ {
+ $checked = self::isForeignKeyCheck();
+ $html = '<input type="hidden" name="fk_checks" value="0" />';
+ $html .= '<input type="checkbox" name="fk_checks"'
+ . ' id="fk_checks" value="1"'
+ . ($checked ? ' checked="checked"' : '') . '/>';
+ $html .= '<label for="fk_checks">' . __('Enable foreign key checks')
+ . '</label>';
+ return $html;
+ }
+
+ /**
+ * Handle foreign key check request
+ *
+ * @return bool Default foreign key checks value
+ */
+ public static function handleDisableFKCheckInit()
+ {
+ $default_fk_check_value
+ = $GLOBALS['dbi']->getVariable('FOREIGN_KEY_CHECKS') == 'ON';
+ if (isset($_REQUEST['fk_checks'])) {
+ if (empty($_REQUEST['fk_checks'])) {
+ // Disable foreign key checks
+ $GLOBALS['dbi']->setVariable('FOREIGN_KEY_CHECKS', 'OFF');
+ } else {
+ // Enable foreign key checks
+ $GLOBALS['dbi']->setVariable('FOREIGN_KEY_CHECKS', 'ON');
+ }
+ } // else do nothing, go with default
+ return $default_fk_check_value;
+ }
+
+ /**
+ * Cleanup changes done for foreign key check
+ *
+ * @param bool $default_fk_check_value original value for 'FOREIGN_KEY_CHECKS'
+ *
+ * @return void
+ */
+ public static function handleDisableFKCheckCleanup($default_fk_check_value)
+ {
+ $GLOBALS['dbi']->setVariable(
+ 'FOREIGN_KEY_CHECKS', $default_fk_check_value ? 'ON' : 'OFF'
+ );
+ }
+
+ /**
* Replaces some characters by a displayable equivalent
*
* @param string $content content
@@ -3199,18 +3342,26 @@ class PMA_Util
* $cfg['NavigationTreeDefaultTabTable2'],
* $cfg['DefaultTabTable'] or $cfg['DefaultTabDatabase']
*
- * @return array
+ * @return string Title for the $cfg value
*/
public static function getTitleForTarget($target)
{
$mapping = array(
+ 'structure' => __('Structure'),
+ 'sql' => __('SQL'),
+ 'search' =>__('Search'),
+ 'insert' =>__('Insert'),
+ 'browse' => __('Browse'),
+ 'operations' => __('Operations'),
+
+ // For backward compatiblity
+
// Values for $cfg['DefaultTabTable']
'tbl_structure.php' => __('Structure'),
'tbl_sql.php' => __('SQL'),
'tbl_select.php' =>__('Search'),
'tbl_change.php' =>__('Insert'),
'sql.php' => __('Browse'),
-
// Values for $cfg['DefaultTabDatabase']
'db_structure.php' => __('Structure'),
'db_sql.php' => __('SQL'),
@@ -3221,6 +3372,67 @@ class PMA_Util
}
/**
+ * Get the script name corresponding to a plain English config word
+ * in order to append in links on navigation and main panel
+ *
+ * @param string $target a valid value for $cfg['NavigationTreeDefaultTabTable'],
+ * $cfg['NavigationTreeDefaultTabTable2'],
+ * $cfg['DefaultTabTable'], $cfg['DefaultTabDatabase'] or
+ * $cfg['DefaultTabServer']
+ * @param string $location one out of 'server', 'table', 'database'
+ *
+ * @return string script name corresponding to the config word
+ */
+ public static function getScriptNameForOption($target, $location)
+ {
+ if ($location == 'server') {
+ // Values for $cfg['DefaultTabServer']
+ switch ($target) {
+ case 'welcome':
+ return 'index.php';
+ case 'databases':
+ return 'server_databases.php';
+ case 'status':
+ return 'server_status.php';
+ case 'variables':
+ return 'server_variables.php';
+ case 'privileges':
+ return 'server_privileges.php';
+ }
+ } elseif ($location == 'database') {
+ // Values for $cfg['DefaultTabDatabase']
+ switch ($target) {
+ case 'structure':
+ return 'db_structure.php';
+ case 'sql':
+ return 'db_sql.php';
+ case 'search':
+ return 'db_search.php';
+ case 'operations':
+ return 'db_operations.php';
+ }
+ } elseif ($location == 'table') {
+ // Values for $cfg['DefaultTabTable'],
+ // $cfg['NavigationTreeDefaultTabTable'] and
+ // $cfg['NavigationTreeDefaultTabTable2']
+ switch ($target) {
+ case 'structure':
+ return 'tbl_structure.php';
+ case 'sql':
+ return 'tbl_sql.php';
+ case 'search':
+ return 'tbl_select.php';
+ case 'insert':
+ return 'tbl_change.php';
+ case 'browse':
+ return 'sql.php';
+ }
+ }
+
+ return $target;
+ }
+
+ /**
* Formats user string, expanding @VARIABLES@, accepting strftime format
* string.
*
@@ -3359,8 +3571,8 @@ class PMA_Util
* Prepare the form used to select a file to import from the server upload
* directory
*
- * @param array $import_list array of import plugins
- * @param string $uploaddir upload directory
+ * @param ImportPlugin[] $import_list array of import plugins
+ * @param string $uploaddir upload directory
*
* @return String
*/
@@ -3408,7 +3620,7 @@ class PMA_Util
. ' <option value="">&nbsp;</option>' . "\n"
. $files
. ' </select>' . "\n";
- } elseif (empty ($files)) {
+ } elseif (empty($files)) {
$block_html .= '<i>' . __('There are no files to upload!') . '</i>';
}
@@ -3708,7 +3920,6 @@ class PMA_Util
* @param bool $insert_mode Whether the operation is 'insert'
*
* @global array $cfg PMA configuration
- * @global array $analyzed_sql Analyzed SQL query
* @global mixed $data data of currently edited row
* (used to detect whether to choose defaults)
*
@@ -3721,7 +3932,7 @@ class PMA_Util
* @todo Except for $cfg, no longer use globals but pass as parameters
* from higher levels
*/
- global $cfg, $analyzed_sql, $data;
+ global $cfg, $data;
$default_function = '';
@@ -3734,8 +3945,6 @@ class PMA_Util
}
}
- $analyzed_sql_field_array = $analyzed_sql[0]['create_table_fields']
- [$field['Field']];
// what function defined as default?
// for the first timestamp we don't set the default function
// if there is a default value for the timestamp
@@ -3746,9 +3955,8 @@ class PMA_Util
&& $field['first_timestamp']
&& empty($field['Default'])
&& empty($data)
- && ! isset($analyzed_sql_field_array['on_update_current_timestamp'])
- && ! (isset($analyzed_sql_field_array['default_value'])
- && $analyzed_sql_field_array['default_value'] == 'NULL')
+ && $field['Extra'] != 'on update CURRENT_TIMESTAMP'
+ && $field['Null'] == 'NO'
) {
$default_function = $cfg['DefaultFunctions']['first_timestamp'];
}
@@ -3848,6 +4056,10 @@ class PMA_Util
return false;
}
+ if ($user == '@') { // MySQL is started with --skip-grant-tables
+ return true;
+ }
+
$user = explode('@', $user);
$username = "''";
$username .= str_replace("'", "''", $user[0]);
@@ -3946,38 +4158,6 @@ class PMA_Util
}
/**
- * Analyzes the limit clause and return the start and length attributes of it.
- *
- * @param string $limit_clause limit clause
- *
- * @return array|bool Start and length attributes of the limit clause or false
- * on failure
- */
- public static function analyzeLimitClause($limit_clause)
- {
- $limitParams = trim(str_ireplace('LIMIT', '', $limit_clause));
- if ('' == $limitParams) {
- return false;
- }
-
- $start_and_length = explode(',', $limitParams);
- $size = count($start_and_length);
- if ($size == 1) {
- return array(
- 'start' => '0',
- 'length' => trim($start_and_length[0])
- );
- } elseif ($size == 2) {
- return array(
- 'start' => trim($start_and_length[0]),
- 'length' => trim($start_and_length[1])
- );
- }
-
- return false;
- }
-
- /**
* Prepare HTML code for display button.
*
* @return String
@@ -4009,12 +4189,12 @@ class PMA_Util
$in_string = false;
$buffer = '';
- for ($i=0, $length = /*overload*/mb_strlen($values_string);
+ for ($i = 0, $length = /*overload*/mb_strlen($values_string);
$i < $length;
$i++
) {
$curr = /*overload*/mb_substr($values_string, $i, 1);
- $next = ($i == /*overload*/mb_strlen($values_string)-1)
+ $next = ($i == /*overload*/mb_strlen($values_string) - 1)
? ''
: /*overload*/mb_substr($values_string, $i + 1, 1);
@@ -4053,63 +4233,6 @@ class PMA_Util
}
/**
- * fills given tooltip arrays
- *
- * @param array &$tooltip_truename tooltip data
- * @param array &$tooltip_aliasname tooltip data
- * @param array $table tabledata
- *
- * @return void
- */
- public static function fillTooltip(
- &$tooltip_truename, &$tooltip_aliasname, $table
- ) {
- if (/*overload*/mb_strstr($table['Comment'], '; InnoDB free') === false) {
- if (!/*overload*/mb_strstr($table['Comment'], 'InnoDB free') === false) {
- // here we have just InnoDB generated part
- $table['Comment'] = '';
- }
- } else {
- // remove InnoDB comment from end, just the minimal part
- // (*? is non greedy)
- $table['Comment'] = preg_replace(
- '@; InnoDB free:.*?$@', '', $table['Comment']
- );
- }
- // views have VIEW as comment so it's not a real comment put by a user
- if ('VIEW' == $table['Comment']) {
- $table['Comment'] = '';
- }
- if (empty($table['Comment'])) {
- $table['Comment'] = $table['Name'];
- } else {
- // todo: why?
- $table['Comment'] .= ' ';
- }
-
- $tooltip_truename[$table['Name']] = $table['Name'];
- $tooltip_aliasname[$table['Name']] = $table['Comment'];
-
- if (isset($table['Create_time']) && !empty($table['Create_time'])) {
- $tooltip_aliasname[$table['Name']] .= ', ' . __('Creation')
- . ': '
- . PMA_Util::localisedDate(strtotime($table['Create_time']));
- }
-
- if (! empty($table['Update_time'])) {
- $tooltip_aliasname[$table['Name']] .= ', ' . __('Last update')
- . ': '
- . PMA_Util::localisedDate(strtotime($table['Update_time']));
- }
-
- if (! empty($table['Check_time'])) {
- $tooltip_aliasname[$table['Name']] .= ', ' . __('Last check')
- . ': '
- . PMA_Util::localisedDate(strtotime($table['Check_time']));
- }
- }
-
- /**
* Get regular expression which occur first inside the given sql query.
*
* @param Array $regex_array Comparing regular expressions.
@@ -4256,6 +4379,10 @@ class PMA_Util
*/
public static function getLatestVersion()
{
+ if (!$GLOBALS['cfg']['VersionCheck']) {
+ return new stdClass();
+ }
+
// wait 3s at most for server response, it's enough to get information
// from a working server
$connection_timeout = 3;
@@ -4465,6 +4592,7 @@ class PMA_Util
* @param string $linkId Value to use for the ID attribute
* @param boolean $disableAjax Whether to disable ajax page loading for this link
* @param string $linkTarget The name of the target frame for the link
+ * @param array $classes HTML classes to apply
*
* @return string HTML code for one link
*/
@@ -4476,7 +4604,8 @@ class PMA_Util
$icon,
$linkId = '',
$disableAjax = false,
- $linkTarget = ''
+ $linkTarget = '',
+ $classes = array()
) {
$retval = '<a href="' . $link . '"';
if (! empty($linkId)) {
@@ -4486,7 +4615,10 @@ class PMA_Util
$retval .= ' target="' . $linkTarget . '"';
}
if ($disableAjax) {
- $retval .= ' class="disableAjax"';
+ $classes[] = 'disableAjax';
+ }
+ if (!empty($classes)) {
+ $retval .= ' class="' . join(" ", $classes) . '"';
}
$retval .= ' title="' . $text . '">';
if ($showIcon) {
@@ -4513,13 +4645,16 @@ class PMA_Util
*/
public static function getCollateForIS()
{
- $lowerCaseTableNames = $GLOBALS['dbi']->fetchValue(
- "SHOW VARIABLES LIKE 'lower_case_table_names'", 0, 1
+ $lowerCaseTableNames = self::cacheGet(
+ 'lower_case_table_names',
+ function () {
+ return $GLOBALS['dbi']->fetchValue(
+ "SELECT @@lower_case_table_names"
+ );
+ }
);
- if ($lowerCaseTableNames === '0' // issue #10961
- || $lowerCaseTableNames === '2' // issue #11461
- ) {
+ if ($lowerCaseTableNames === '0') {
return "COLLATE utf8_bin";
}
return "";
@@ -4591,14 +4726,343 @@ class PMA_Util
. 'src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png" '
. 'width="38" height="22" alt="' . __('With selected:') . '" />';
$html .= '<input type="checkbox" id="' . $formName . '_checkall" '
- . 'class="checkall_box" title="' . __('Check All') . '" />'
- . '<label for="' . $formName . '_checkall">' . __('Check All')
+ . 'class="checkall_box" title="' . __('Check all') . '" />'
+ . '<label for="' . $formName . '_checkall">' . __('Check all')
. '</label>';
$html .= '<i style="margin-left: 2em">'
. __('With selected:') . '</i>';
return $html;
}
+
+ /**
+ * Function to get html for the start row and number of rows panel
+ *
+ * @param string $sql_query sql query
+ *
+ * @return string html
+ */
+ public static function getStartAndNumberOfRowsPanel($sql_query)
+ {
+ $pos = isset($_REQUEST['pos'])
+ ? $_REQUEST['pos']
+ : $_SESSION['tmpval']['pos'];
+ if (isset($_REQUEST['session_max_rows'])) {
+ $rows = $_REQUEST['session_max_rows'];
+ } else {
+ if ($_SESSION['tmpval']['max_rows'] != 'all') {
+ $rows = $_SESSION['tmpval']['max_rows'];
+ } else {
+ $rows = $GLOBALS['cfg']['MaxRows'];
+ }
+ }
+
+ return Template::get('startAndNumberOfRowsPanel')
+ ->render(
+ array(
+ 'pos' => $pos,
+ 'unlim_num_rows' => $_REQUEST['unlim_num_rows'],
+ 'rows' => $rows,
+ 'sql_query' => $sql_query,
+ )
+ );
+ }
+
+ /**
+ * Returns whether the database server supports virtual columns
+ *
+ * @return bool
+ */
+ public static function isVirtualColumnsSupported()
+ {
+ $serverType = self::getServerType();
+ return $serverType == 'MySQL' && PMA_MYSQL_INT_VERSION >= 50705
+ || ($serverType == 'MariaDB' && PMA_MYSQL_INT_VERSION >= 50200);
+ }
+
+ /**
+ * Returns the proper class clause according to the column type
+ *
+ * @param string $type the column type
+ *
+ * @return string $class_clause the HTML class clause
+ */
+ public static function getClassForType($type)
+ {
+ if ('set' == $type
+ || 'enum' == $type
+ ) {
+ $class_clause = '';
+ } else {
+ $class_clause = ' class="nowrap"';
+ }
+ return $class_clause;
+ }
+
+ /**
+ * Gets the list of tables in the current db and information about these
+ * tables if possible
+ *
+ * @param string $db database name
+ * @param string $sub_part part of script name
+ *
+ * @return array
+ *
+ */
+ public static function getDbInfo($db, $sub_part)
+ {
+ global $cfg;
+
+ /**
+ * limits for table list
+ */
+ if (! isset($_SESSION['tmpval']['table_limit_offset'])
+ || $_SESSION['tmpval']['table_limit_offset_db'] != $db
+ ) {
+ $_SESSION['tmpval']['table_limit_offset'] = 0;
+ $_SESSION['tmpval']['table_limit_offset_db'] = $db;
+ }
+ if (isset($_REQUEST['pos'])) {
+ $_SESSION['tmpval']['table_limit_offset'] = (int) $_REQUEST['pos'];
+ }
+ $pos = $_SESSION['tmpval']['table_limit_offset'];
+
+ /**
+ * whether to display extended stats
+ */
+ $is_show_stats = $cfg['ShowStats'];
+
+ /**
+ * whether selected db is information_schema
+ */
+ $db_is_system_schema = false;
+
+ if ($GLOBALS['dbi']->isSystemSchema($db)) {
+ $is_show_stats = false;
+ $db_is_system_schema = true;
+ }
+
+ /**
+ * information about tables in db
+ */
+ $tables = array();
+
+ $tooltip_truename = array();
+ $tooltip_aliasname = array();
+
+ // Special speedup for newer MySQL Versions (in 4.0 format changed)
+ if (true === $cfg['SkipLockedTables'] && ! PMA_DRIZZLE) {
+ $db_info_result = $GLOBALS['dbi']->query(
+ 'SHOW OPEN TABLES FROM ' . PMA_Util::backquote($db) . ';'
+ );
+
+ // Blending out tables in use
+ if ($db_info_result && $GLOBALS['dbi']->numRows($db_info_result) > 0) {
+ $tables = self::getTablesWhenOpen($db, $db_info_result);
+
+ } elseif ($db_info_result) {
+ $GLOBALS['dbi']->freeResult($db_info_result);
+ }
+ }
+
+ if (empty($tables)) {
+ // Set some sorting defaults
+ $sort = 'Name';
+ $sort_order = 'ASC';
+
+ if (isset($_REQUEST['sort'])) {
+ $sortable_name_mappings = array(
+ 'table' => 'Name',
+ 'records' => 'Rows',
+ 'type' => 'Engine',
+ 'collation' => 'Collation',
+ 'size' => 'Data_length',
+ 'overhead' => 'Data_free',
+ 'creation' => 'Create_time',
+ 'last_update' => 'Update_time',
+ 'last_check' => 'Check_time',
+ 'comment' => 'Comment',
+ );
+
+ // Make sure the sort type is implemented
+ if (isset($sortable_name_mappings[$_REQUEST['sort']])) {
+ $sort = $sortable_name_mappings[$_REQUEST['sort']];
+ if ($_REQUEST['sort_order'] == 'DESC') {
+ $sort_order = 'DESC';
+ }
+ }
+ }
+
+ $tbl_group = false;
+ $groupWithSeparator = false;
+ $tbl_type = null;
+ $limit_offset = 0;
+ $limit_count = false;
+ $groupTable = array();
+
+ if (! empty($_REQUEST['tbl_group']) || ! empty($_REQUEST['tbl_type'])) {
+ if (! empty($_REQUEST['tbl_type'])) {
+ // only tables for selected type
+ $tbl_type = $_REQUEST['tbl_type'];
+ }
+ if (! empty($_REQUEST['tbl_group'])) {
+ // only tables for selected group
+ $tbl_group = $_REQUEST['tbl_group'];
+ // include the table with the exact name of the group if such exists
+ $groupTable = $GLOBALS['dbi']->getTablesFull(
+ $db, $tbl_group, false, null, $limit_offset,
+ $limit_count, $sort, $sort_order, $tbl_type
+ );
+ $groupWithSeparator = $tbl_group
+ . $GLOBALS['cfg']['NavigationTreeTableSeparator'];
+ }
+ } else {
+ // all tables in db
+ // - get the total number of tables
+ // (needed for proper working of the MaxTableList feature)
+ $tables = $GLOBALS['dbi']->getTables($db);
+ $total_num_tables = count($tables);
+ if (isset($sub_part) && $sub_part == '_export') {
+ // (don't fetch only a subset if we are coming from db_export.php,
+ // because I think it's too risky to display only a subset of the
+ // table names when exporting a db)
+ /**
+ *
+ * @todo Page selector for table names?
+ */
+ } else {
+ // fetch the details for a possible limited subset
+ $limit_offset = $pos;
+ $limit_count = true;
+ }
+ }
+ $tables = array_merge(
+ $groupTable,
+ $GLOBALS['dbi']->getTablesFull(
+ $db, $groupWithSeparator, ($groupWithSeparator !== false), null,
+ $limit_offset, $limit_count, $sort, $sort_order, $tbl_type
+ )
+ );
+ }
+
+ $num_tables = count($tables);
+ // (needed for proper working of the MaxTableList feature)
+ if (! isset($total_num_tables)) {
+ $total_num_tables = $num_tables;
+ }
+
+ /**
+ * If coming from a Show MySQL link on the home page,
+ * put something in $sub_part
+ */
+ if (empty($sub_part)) {
+ $sub_part = '_structure';
+ }
+
+ return array(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ );
+ }
+
+ /**
+ * Gets the list of tables in the current db, taking into account
+ * that they might be "in use"
+ *
+ * @param string $db database name
+ * @param object $db_info_result result set
+ *
+ * @return array $tables list of tables
+ *
+ */
+ public function getTablesWhenOpen($db, $db_info_result)
+ {
+ $tables = array();
+
+ while ($tmp = $GLOBALS['dbi']->fetchAssoc($db_info_result)) {
+ // if in use, memorize table name
+ if ($tmp['In_use'] > 0) {
+ $sot_cache[$tmp['Table']] = true;
+ }
+ }
+ $GLOBALS['dbi']->freeResult($db_info_result);
+
+ // is there at least one "in use" table?
+ if (isset($sot_cache)) {
+ $db_info_result = false;
+
+ $tblGroupSql = "";
+ $whereAdded = false;
+ if (PMA_isValid($_REQUEST['tbl_group'])) {
+ $group = PMA_Util::escapeMysqlWildcards($_REQUEST['tbl_group']);
+ $groupWithSeparator = PMA_Util::escapeMysqlWildcards(
+ $_REQUEST['tbl_group']
+ . $GLOBALS['cfg']['NavigationTreeTableSeparator']
+ );
+ $tblGroupSql .= " WHERE ("
+ . PMA_Util::backquote('Tables_in_' . $db)
+ . " LIKE '" . $groupWithSeparator . "%'"
+ . " OR "
+ . PMA_Util::backquote('Tables_in_' . $db)
+ . " LIKE '" . $group . "')";
+ $whereAdded = true;
+ }
+ if (PMA_isValid($_REQUEST['tbl_type'], array('table', 'view'))) {
+ $tblGroupSql .= $whereAdded ? " AND" : " WHERE";
+ if ($_REQUEST['tbl_type'] == 'view') {
+ $tblGroupSql .= " `Table_type` != 'BASE TABLE'";
+ } else {
+ $tblGroupSql .= " `Table_type` = 'BASE TABLE'";
+ }
+ }
+ $db_info_result = $GLOBALS['dbi']->query(
+ 'SHOW FULL TABLES FROM ' . PMA_Util::backquote($db) . $tblGroupSql,
+ null, PMA_DatabaseInterface::QUERY_STORE
+ );
+ unset($tblGroupSql, $whereAdded);
+
+ if ($db_info_result && $GLOBALS['dbi']->numRows($db_info_result) > 0) {
+ while ($tmp = $GLOBALS['dbi']->fetchRow($db_info_result)) {
+ if (! isset($sot_cache[$tmp[0]])) {
+ $sts_result = $GLOBALS['dbi']->query(
+ "SHOW TABLE STATUS FROM " . PMA_Util::backquote($db)
+ . " LIKE '" . PMA_Util::sqlAddSlashes($tmp[0], true)
+ . "';"
+ );
+ $sts_tmp = $GLOBALS['dbi']->fetchAssoc($sts_result);
+ $GLOBALS['dbi']->freeResult($sts_result);
+ unset($sts_result);
+
+ $tableArray = $GLOBALS['dbi']->copyTableProperties(
+ array($sts_tmp), $db
+ );
+ $tables[$sts_tmp['Name']] = $tableArray[0];
+ } else { // table in use
+ $tables[$tmp[0]] = array(
+ 'TABLE_NAME' => $tmp[0],
+ 'ENGINE' => '',
+ 'TABLE_TYPE' => '',
+ 'TABLE_ROWS' => 0,
+ );
+ }
+ } // end while
+ if ($GLOBALS['cfg']['NaturalOrder']) {
+ uksort($tables, 'strnatcasecmp');
+ }
+
+ } elseif ($db_info_result) {
+ $GLOBALS['dbi']->freeResult($db_info_result);
+ }
+ unset($sot_cache);
+ }
+ return $tables;
+ }
}
-?>
diff --git a/libraries/advisory_rules.txt b/libraries/advisory_rules.txt
index b3d6114967..5d6bf4e4fc 100644
--- a/libraries/advisory_rules.txt
+++ b/libraries/advisory_rules.txt
@@ -129,14 +129,14 @@ rule 'Distribution'
version_comment
preg_match('/percona/i',value)
The MySQL manual only is accurate for official MySQL binaries.
- Percona documentation is at http://www.percona.com/software/documentation/
+ Percona documentation is at <a href="http://www.percona.com/software/documentation/">http://www.percona.com/software/documentation/</a>
'percona' found in version_comment
rule 'Distribution'
version
PMA_DRIZZLE
The MySQL manual only is accurate for official MySQL binaries.
- Drizzle documentation is at http://www.drizzle.org/content/documentation/
+ Drizzle documentation is at <a href="http://www.drizzle.org/content/documentation/">http://www.drizzle.org/content/documentation/</a>
Version string (%s) matches Drizzle versioning scheme | value
rule 'MySQL Architecture'
diff --git a/libraries/bfShapeFiles/ShapeFile.lib.php b/libraries/bfShapeFiles/ShapeFile.lib.php
index 795d0aa292..649110cd35 100644
--- a/libraries/bfShapeFiles/ShapeFile.lib.php
+++ b/libraries/bfShapeFiles/ShapeFile.lib.php
@@ -679,4 +679,3 @@
}
}
-?>
diff --git a/libraries/bookmark.lib.php b/libraries/bookmark.lib.php
index 1b3d18ce1f..ae65b03f14 100644
--- a/libraries/bookmark.lib.php
+++ b/libraries/bookmark.lib.php
@@ -65,88 +65,48 @@ function PMA_Bookmark_getList($db = false)
}
if ($db !== false) {
- $query = 'SELECT label, id FROM ' . PMA_Util::backquote($cfgBookmark['db'])
- . '.' . PMA_Util::backquote($cfgBookmark['table'])
- . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND user = \'' . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . '\''
- . ' ORDER BY label';
+ $query = 'SELECT query, label, id FROM ' . PMA_Util::backquote(
+ $cfgBookmark['db']
+ ) . '.' . PMA_Util::backquote($cfgBookmark['table'])
+ . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
+ . ' AND user = \'' . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . '\''
+ . ' ORDER BY label';
$per_user = $GLOBALS['dbi']->fetchResult(
- $query, 'id', 'label', $controllink, PMA_DatabaseInterface::QUERY_STORE
+ $query, 'id', null, $controllink, PMA_DatabaseInterface::QUERY_STORE
);
- $query = 'SELECT label, id FROM ' . PMA_Util::backquote($cfgBookmark['db'])
- . '.' . PMA_Util::backquote($cfgBookmark['table'])
- . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND user = \'\''
- . ' ORDER BY label';
+ $query = 'SELECT query, label, id FROM ' . PMA_Util::backquote(
+ $cfgBookmark['db']
+ ) . '.' . PMA_Util::backquote($cfgBookmark['table'])
+ . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
+ . ' AND user = \'\''
+ . ' ORDER BY label';
$global = $GLOBALS['dbi']->fetchResult(
- $query, 'id', 'label', $controllink, PMA_DatabaseInterface::QUERY_STORE
+ $query, 'id', null, $controllink, PMA_DatabaseInterface::QUERY_STORE
);
foreach ($global as $key => $val) {
- $global[$key] = $val . ' (' . __('shared') . ')';
+ $global[$key]['label'] = $val['label'] . ' (' . __('shared') . ')';
}
$ret = $global + $per_user;
asort($ret);
} else {
- $query = 'SELECT label, id, query, dbase FROM '
- . PMA_Util::backquote($cfgBookmark['db'])
- . '.' . PMA_Util::backquote($cfgBookmark['table'])
- . ' WHERE user = \''
- . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . '\''
- . ' ORDER BY label';
- $per_user = $GLOBALS['dbi']->fetchResult(
- $query,
- Array('id', 'label', 'dbase'),
- 'query',
- $controllink,
- PMA_DatabaseInterface::QUERY_STORE
- );
-
- $query = 'SELECT label, id, query, dbase FROM '
- . PMA_Util::backquote($cfgBookmark['db'])
- . '.' . PMA_Util::backquote($cfgBookmark['table'])
- . ' WHERE user = \'\''
- . ' ORDER BY label';
- $global = $GLOBALS['dbi']->fetchResult(
+ $query = "SELECT `label`, `id`, `query`, `dbase` AS `db`,"
+ . " IF (`user` = '', true, false) AS `shared`"
+ . " FROM " . PMA_Util::backquote($cfgBookmark['db'])
+ . "." . PMA_Util::backquote($cfgBookmark['table'])
+ . " WHERE `user` = '' OR"
+ . " `user` = '" . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . "'";
+
+ $ret = $GLOBALS['dbi']->fetchResult(
$query,
- Array('id', 'label', 'dbase'),
- 'query',
+ null,
+ null,
$controllink,
PMA_DatabaseInterface::QUERY_STORE
);
-
- $ret = Array();
-
- foreach ($global as $id => $val) {
- foreach ($val as $label => $val2) {
- foreach ($val2 as $dbase => $query) {
- $ret[] = Array(
- 'db' => $dbase,
- 'id' => $id,
- 'label' => $label,
- 'query' => $query,
- 'shared' => true
- );
- }
- }
- }
-
- foreach ($per_user as $id => $val) {
- foreach ($val as $label => $val2) {
- foreach ($val2 as $dbase => $query) {
- $ret[] = Array(
- 'db' => $dbase,
- 'id' => $id,
- 'label' => $label,
- 'query' => $query,
- 'shared' => false
- );
- }
- }
- }
}
return $ret;
@@ -270,4 +230,47 @@ function PMA_Bookmark_delete($id)
return $GLOBALS['dbi']->tryQuery($query, $controllink);
} // end of the 'PMA_Bookmark_delete()' function
-?>
+/**
+ * Returns the number of variables in a bookmark
+ *
+ * @param string $query bookmarked query
+ *
+ * @return number number of variables
+ */
+function PMA_Bookmark_getVariableCount($query)
+{
+ $matches = array();
+ preg_match_all("/\[VARIABLE[0-9]*\]/", $query, $matches, PREG_SET_ORDER);
+ return count($matches);
+}
+
+/**
+ * Replace the placeholders in the bookmark query with variables
+ *
+ * @param string $query bookmarked query
+ *
+ * @return string query with variables applied
+ */
+function PMA_Bookmark_applyVariables($query)
+{
+ // remove comments that encloses a variable placeholder
+ $query = preg_replace(
+ '|/\*(.*\[VARIABLE[0-9]*\].*)\*/|imsU',
+ '${1}',
+ $query
+ );
+ // replace variable placeholders with values
+ $number_of_variables = PMA_Bookmark_getVariableCount($query);
+ for ($i = 1; $i <= $number_of_variables; $i++) {
+ $var = '';
+ if (! empty($_REQUEST['bookmark_variable'][$i])) {
+ $var = PMA_Util::sqlAddSlashes($_REQUEST['bookmark_variable'][$i]);
+ }
+ $query = str_replace('[VARIABLE' . $i . ']', $var, $query);
+ // backward compatibility
+ if ($i == 1) {
+ $query = str_replace('[VARIABLE]', $var, $query);
+ }
+ }
+ return $query;
+}
diff --git a/libraries/browse_foreigners.lib.php b/libraries/browse_foreigners.lib.php
index 6a5d1b0892..f4a1e86877 100644
--- a/libraries/browse_foreigners.lib.php
+++ b/libraries/browse_foreigners.lib.php
@@ -10,19 +10,107 @@ if (! defined('PHPMYADMIN')) {
}
/**
+ * Function to get html for one relational key
+ *
+ * @param integer $horizontal_count the current horizontal count
+ * @param string $header table header
+ * @param boolean $odd_row for the row background color
+ * @param array $keys all the keys
+ * @param integer $indexByKeyname index by keyname
+ * @param array $descriptions descriptions
+ * @param integer $indexByDescription index by description
+ * @param string $current_value current value on the edit form
+ *
+ * @return string $html the generated html
+ */
+function PMA_getHtmlForOneKey($horizontal_count, $header, $odd_row, $keys,
+ $indexByKeyname, $descriptions, $indexByDescription, $current_value
+) {
+ $horizontal_count++;
+ $output = '';
+
+ // whether the key name corresponds to the selected value in the form
+ $rightKeynameIsSelected = false;
+ $leftKeynameIsSelected = false;
+
+ if ($GLOBALS['cfg']['RepeatCells'] > 0
+ && $horizontal_count > $GLOBALS['cfg']['RepeatCells']
+ ) {
+ $output .= $header;
+ $horizontal_count = 0;
+ $odd_row = true;
+ }
+
+ // key names and descriptions for the left section,
+ // sorted by key names
+ $leftKeyname = $keys[$indexByKeyname];
+ list(
+ $leftDescription,
+ $leftDescriptionTitle
+ ) = PMA_getDescriptionAndTitle($descriptions[$indexByKeyname]);
+
+ // key names and descriptions for the right section,
+ // sorted by descriptions
+ $rightKeyname = $keys[$indexByDescription];
+ list(
+ $rightDescription,
+ $rightDescriptionTitle
+ ) = PMA_getDescriptionAndTitle($descriptions[$indexByDescription]);
+
+ $indexByDescription++;
+
+ if (! empty($current_value)) {
+ $rightKeynameIsSelected = $rightKeyname == $current_value;
+ $leftKeynameIsSelected = $leftKeyname == $current_value;
+ }
+
+ $output .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">';
+ $odd_row = ! $odd_row;
+
+ $output .= PMA_getHtmlForColumnElement(
+ 'class="nowrap"', $leftKeynameIsSelected,
+ $leftKeyname, $leftDescription,
+ $leftDescriptionTitle
+ );
+
+ $output .= PMA_getHtmlForColumnElement(
+ '', $leftKeynameIsSelected, $leftKeyname,
+ $leftDescription, $leftDescriptionTitle
+ );
+
+ $output .= '<td width="20%">'
+ . '<img src="' . $GLOBALS['pmaThemeImage'] . 'spacer.png" alt=""'
+ . ' width="1" height="1" /></td>';
+
+ $output .= PMA_getHtmlForColumnElement(
+ '', $rightKeynameIsSelected, $rightKeyname,
+ $rightDescription, $rightDescriptionTitle
+ );
+
+ $output .= PMA_getHtmlForColumnElement(
+ 'class="nowrap"', $rightKeynameIsSelected,
+ $rightKeyname, $rightDescription,
+ $rightDescriptionTitle
+ );
+ $output .= '</tr>';
+
+ return array($output, $horizontal_count, $odd_row, $indexByDescription);
+}
+
+/**
* Function to get html for relational field selection
*
- * @param string $db current database
- * @param string $table current table
- * @param string $field field
- * @param array $foreignData foreign column data
- * @param string $fieldkey field key
- * @param array $data data
+ * @param string $db current database
+ * @param string $table current table
+ * @param string $field field
+ * @param array $foreignData foreign column data
+ * @param string $fieldkey field key
+ * @param string $current_value current columns's value
*
* @return string
*/
function PMA_getHtmlForRelationalFieldSelection($db, $table, $field, $foreignData,
- $fieldkey, $data
+ $fieldkey, $current_value
) {
$gotopage = PMA_getHtmlForGotoPage($foreignData);
$showall = PMA_getHtmlForShowAll($foreignData);
@@ -93,78 +181,23 @@ function PMA_getHtmlForRelationalFieldSelection($db, $table, $field, $foreignDat
asort($keys);
- $hcount = 0;
+ $horizontal_count = 0;
$odd_row = true;
$indexByDescription = 0;
- // whether the key name corresponds to the selected value in the form
- $rightKeynameIsSelected = false;
- $leftKeynameIsSelected = false;
-
foreach ($keys as $indexByKeyname => $value) {
- $hcount++;
-
- if ($GLOBALS['cfg']['RepeatCells'] > 0
- && $hcount > $GLOBALS['cfg']['RepeatCells']
- ) {
- $output .= $header;
- $hcount = 0;
- $odd_row = true;
- }
-
- // key names and descriptions for the left section,
- // sorted by key names
- $leftKeyname = $keys[$indexByKeyname];
list(
- $leftDescription,
- $leftDescriptionTitle
- ) = PMA_getDescriptionAndTitle($descriptions[$indexByKeyname]);
-
- // key names and descriptions for the right section,
- // sorted by descriptions
- $rightKeyname = $keys[$indexByDescription];
- list(
- $rightDescription,
- $rightDescriptionTitle
- ) = PMA_getDescriptionAndTitle($descriptions[$indexByDescription]);
-
- $indexByDescription++;
-
- if (! empty($data)) {
- $rightKeynameIsSelected = $rightKeyname == $data;
- $leftKeynameIsSelected = $leftKeyname == $data;
- }
-
- $output .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">';
- $odd_row = ! $odd_row;
-
- $output .= PMA_getHtmlForColumnElement(
- 'class="nowrap"', $leftKeynameIsSelected,
- $leftKeyname, $leftDescription,
- $leftDescriptionTitle
- );
-
- $output .= PMA_getHtmlForColumnElement(
- '', $leftKeynameIsSelected, $leftKeyname,
- $leftDescription, $leftDescriptionTitle
- );
-
- $output .= '<td width="20%">'
- . '<img src="' . $GLOBALS['pmaThemeImage'] . 'spacer.png" alt=""'
- . ' width="1" height="1" /></td>';
-
- $output .= PMA_getHtmlForColumnElement(
- '', $rightKeynameIsSelected, $rightKeyname,
- $rightDescription, $rightDescriptionTitle
+ $html,
+ $horizontal_count,
+ $odd_row,
+ $indexByDescription
+ ) = PMA_getHtmlForOneKey(
+ $horizontal_count, $header, $odd_row, $keys, $indexByKeyname,
+ $descriptions, $indexByDescription, $current_value
);
+ $output .= $html;
+ }
- $output .= PMA_getHtmlForColumnElement(
- 'class="nowrap"', $rightKeynameIsSelected,
- $rightKeyname, $rightDescription,
- $rightDescriptionTitle
- );
- $output .= '</tr>';
- } // end while
$output .= '</tbody>'
. '</table>';
@@ -313,4 +346,3 @@ function PMA_getForeignLimit($foreign_showAll)
isset($_REQUEST['pos']) ? $pos = $_REQUEST['pos'] : $pos = 0;
return 'LIMIT ' . $pos . ', ' . $GLOBALS['cfg']['MaxRows'] . ' ';
}
-?>
diff --git a/libraries/build_html_for_db.lib.php b/libraries/build_html_for_db.lib.php
index 4737550b43..2ccd68e7ac 100644
--- a/libraries/build_html_for_db.lib.php
+++ b/libraries/build_html_for_db.lib.php
@@ -87,7 +87,9 @@ function PMA_buildHtmlForDb(
$out .= ' /></td>';
}
$out .= '<td class="name">'
- . '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
+ . '<a href="' . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ )
. $url_query . '&amp;db='
. urlencode($current['SCHEMA_NAME']) . '" title="'
. sprintf(
@@ -176,9 +178,8 @@ function PMA_buildHtmlForDb(
)
. '">'
. ' '
- . PMA_Util::getIcon('s_rights.png', __('Check Privileges'))
+ . PMA_Util::getIcon('s_rights.png', __('Check privileges'))
. '</a></td>';
}
return array($column_order, $out);
}
-?>
diff --git a/libraries/central_columns.lib.php b/libraries/central_columns.lib.php
index 030e7c7719..743913acc0 100644
--- a/libraries/central_columns.lib.php
+++ b/libraries/central_columns.lib.php
@@ -9,6 +9,8 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once './libraries/Template.class.php';
+
/**
* Defines the central_columns parameters for the current user
*
@@ -25,9 +27,7 @@ function PMA_centralColumnsGetParams()
$cfgRelation = PMA_getRelationsParam();
- if (isset($cfgRelation['central_columnswork'])
- && $cfgRelation['central_columnswork']
- ) {
+ if ($cfgRelation['centralcolumnswork']) {
$cfgCentralColumns = array(
'user' => $GLOBALS['cfg']['Server']['user'],
'db' => $cfgRelation['db'],
@@ -93,8 +93,8 @@ function PMA_getCentralColumnsCount($db)
$GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
$central_list_table = $cfgCentralColumns['table'];
$query = 'SELECT count(db_name) FROM ' .
- PMA_Util::backquote($central_list_table) . ' '
- . 'WHERE db_name = \'' . $db . '\';';
+ PMA_Util::backquote($central_list_table) . ' '
+ . 'WHERE db_name = \'' . $db . '\';';
$res = $GLOBALS['dbi']->fetchResult(
$query, null, null, $GLOBALS['controllink']
);
@@ -189,15 +189,15 @@ function PMA_getInsertQuery($column, $def, $db, $central_list_table)
$extra = isset($def['Extra'])?$def['Extra']:"";
$default = isset($def['Default'])?$def['Default']:"";
$insQuery = 'INSERT INTO '
- . PMA_Util::backquote($central_list_table) . ' '
- . 'VALUES ( \'' . PMA_Util::sqlAddSlashes($db) . '\' ,'
- . '\'' . PMA_Util::sqlAddSlashes($column) . '\',\''
- . PMA_Util::sqlAddSlashes($type) . '\','
- . '\'' . PMA_Util::sqlAddSlashes($length) . '\',\''
- . PMA_Util::sqlAddSlashes($collation) . '\','
- . '\'' . PMA_Util::sqlAddSlashes($isNull) . '\','
- . '\'' . implode(',', array($extra, $attribute))
- . '\',\'' . PMA_Util::sqlAddSlashes($default) . '\');';
+ . PMA_Util::backquote($central_list_table) . ' '
+ . 'VALUES ( \'' . PMA_Util::sqlAddSlashes($db) . '\' ,'
+ . '\'' . PMA_Util::sqlAddSlashes($column) . '\',\''
+ . PMA_Util::sqlAddSlashes($type) . '\','
+ . '\'' . PMA_Util::sqlAddSlashes($length) . '\',\''
+ . PMA_Util::sqlAddSlashes($collation) . '\','
+ . '\'' . PMA_Util::sqlAddSlashes($isNull) . '\','
+ . '\'' . implode(',', array($extra, $attribute))
+ . '\',\'' . PMA_Util::sqlAddSlashes($default) . '\');';
return $insQuery;
}
@@ -253,13 +253,13 @@ function PMA_syncUniqueColumns($field_select, $isTable=true, $table=null)
}
}
} else {
- if ($table == null) {
+ if ($table === null) {
$table = $_REQUEST['table'];
}
foreach ($field_select as $column) {
$cols .= "'" . PMA_Util::sqlAddSlashes($column) . "',";
}
- $has_list = PMA_findExistingColNames($db, trim($cols, ','));
+ $has_list = PMA_findExistingColNames($db, trim($cols, ','));
foreach ($field_select as $column) {
if (!in_array($column, $has_list)) {
$has_list[] = $column;
@@ -275,7 +275,7 @@ function PMA_syncUniqueColumns($field_select, $isTable=true, $table=null)
}
}
}
- if ($existingCols) {
+ if (! empty($existingCols)) {
$existingCols = implode(",", array_unique($existingCols));
$message = PMA_Message::notice(
sprintf(
@@ -292,7 +292,7 @@ function PMA_syncUniqueColumns($field_select, $isTable=true, $table=null)
);
}
$GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
- if ($insQuery) {
+ if (! empty($insQuery)) {
foreach ($insQuery as $query) {
if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
$message = PMA_Message::error(__('Could not add columns!'));
@@ -365,21 +365,21 @@ function PMA_deleteColumnsFromList($field_select, $isTable=true)
}
}
}
- if ($colNotExist) {
- $colNotExist = implode(",", array_unique($colNotExist));
- $message = PMA_Message::notice(
- sprintf(
- __(
- 'Couldn\'t remove Column(s) %1$s '
- . 'as they don\'t exist in central columns list!'
- ), htmlspecialchars($colNotExist)
- )
- );
+ if (!empty($colNotExist)) {
+ $colNotExist = implode(",", array_unique($colNotExist));
+ $message = PMA_Message::notice(
+ sprintf(
+ __(
+ 'Couldn\'t remove Column(s) %1$s '
+ . 'as they don\'t exist in central columns list!'
+ ), htmlspecialchars($colNotExist)
+ )
+ );
}
$GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
$query = 'DELETE FROM ' . PMA_Util::backquote($central_list_table) . ' '
- . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
+ . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
$message = PMA_Message::error(__('Could not remove columns!'));
@@ -488,7 +488,7 @@ function PMA_getCentralColumnsFromTable($db, $table, $allFields=false)
}
$cols = trim($cols, ',');
$has_list = PMA_findExistingColNames($db, $cols, $allFields);
- if (isset($has_list) && $has_list) {
+ if (! empty($has_list)) {
return (array)$has_list;
} else {
return array();
@@ -534,23 +534,65 @@ function PMA_updateOneColumn($db, $orig_col_name, $col_name, $col_type,
$query = PMA_getInsertQuery($col_name, $def, $db, $centralTable);
} else {
$query = 'UPDATE ' . PMA_Util::backquote($centralTable)
- . ' SET col_type = \'' . PMA_Util::sqlAddSlashes($col_type) . '\''
- . ', col_name = \'' . PMA_Util::sqlAddSlashes($col_name) . '\''
- . ', col_length = \'' . PMA_Util::sqlAddSlashes($col_length) . '\''
- . ', col_isNull = ' . $col_isNull
- . ', col_collation = \'' . PMA_Util::sqlAddSlashes($collation) . '\''
- . ', col_extra = \'' . implode(',', array($col_extra, $col_attribute)) . '\''
- . ', col_default = \'' . PMA_Util::sqlAddSlashes($col_default) . '\''
- . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($db) . '\' '
- . 'AND col_name = \'' . PMA_Util::sqlAddSlashes($orig_col_name)
- . '\'';
+ . ' SET col_type = \'' . PMA_Util::sqlAddSlashes($col_type) . '\''
+ . ', col_name = \'' . PMA_Util::sqlAddSlashes($col_name) . '\''
+ . ', col_length = \'' . PMA_Util::sqlAddSlashes($col_length) . '\''
+ . ', col_isNull = ' . $col_isNull
+ . ', col_collation = \'' . PMA_Util::sqlAddSlashes($collation) . '\''
+ . ', col_extra = \''
+ . implode(',', array($col_extra, $col_attribute)) . '\''
+ . ', col_default = \'' . PMA_Util::sqlAddSlashes($col_default) . '\''
+ . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($db) . '\' '
+ . 'AND col_name = \'' . PMA_Util::sqlAddSlashes($orig_col_name)
+ . '\'';
}
if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
return PMA_Message::error(
$GLOBALS['dbi']->getError($GLOBALS['controllink'])
);
}
- return true;
+ return true;
+}
+
+/**
+ * Update Multiple column in central columns list if a chnage is requested
+ *
+ * @return true|PMA_Message
+ */
+function PMA_updateMultipleColumn()
+{
+ $db = $_POST['db'];
+ $col_name = $_POST['field_name'];
+ $orig_col_name = $_POST['orig_col_name'];
+ $col_default = $_POST['field_default_type'];
+ $col_length = $_POST['field_length'];
+ $col_attribute = $_POST['field_attribute'];
+ $col_type = $_POST['field_type'];
+ $collation = $_POST['field_collation'];
+ $col_isNull = array();
+ $col_extra = array();
+ $num_central_fields = count($orig_col_name);
+ for ($i = 0; $i < $num_central_fields ; $i++) {
+ $col_isNull[$i] = isset($_POST['field_null'][$i]) ? 1 : 0;
+ $col_extra[$i] = isset($_POST['col_extra'][$i])
+ ? $_POST['col_extra'][$i] : '';
+
+ if ($col_default[$i] == 'NONE') {
+ $col_default[$i] = "";
+ } else if ($col_default[$i] == 'USER_DEFINED') {
+ $col_default[$i] = $_POST['field_default_value'][$i];
+ }
+
+ $message = PMA_updateOneColumn(
+ $db, $orig_col_name[$i], $col_name[$i], $col_type[$i],
+ $col_attribute[$i], $col_length[$i], $col_isNull[$i], $collation[$i],
+ $col_extra[$i], $col_default[$i]
+ );
+ if (!is_bool($message)) {
+ return $message;
+ }
+ }
+ return true;
}
/**
@@ -560,7 +602,7 @@ function PMA_updateOneColumn($db, $orig_col_name, $col_name, $col_type,
* @param int $pos offset of first result with complete result set
* @param string $db current database
*
- * @return html for table navigation in Central columns page
+ * @return string html for table navigation in Central columns page
*/
function PMA_getHTMLforTableNavigation($total_rows, $pos, $db)
{
@@ -635,7 +677,7 @@ function PMA_getHTMLforTableNavigation($total_rows, $pos, $db)
* @param string $title title of the 'th' elements
* @param integer $actionCount number of actions
*
- * @return html for table header in central columns view/edit page
+ * @return string html for table header in central columns view/edit page
*/
function PMA_getCentralColumnsTableHeader($class='', $title='', $actionCount=0)
{
@@ -646,35 +688,58 @@ function PMA_getCentralColumnsTableHeader($class='', $title='', $actionCount=0)
}
$tableheader = '<thead>';
$tableheader .= '<tr>'
- . $action
+ . '<th class="' . $class . '"></th>'
. '<th class="" style="display:none"></th>'
+ . $action
. '<th class="' . $class . '" title="' . $title . '" data-column="name">'
. __('Name') . '<div class="sorticon"></div></th>'
. '<th class="' . $class . '" title="' . $title . '" data-column="type">'
. __('Type') . '<div class="sorticon"></div></th>'
. '<th class="' . $class . '" title="' . $title . '" data-column="length">'
. __('Length/Values') . '<div class="sorticon"></div></th>'
+ . '<th class="' . $class . '" title="' . $title . '" data-column="default">'
+ . __('Default') . '<div class="sorticon"></div></th>'
. '<th class="' . $class . '" title="' . $title . '" data-column="collation"'
. '>' . __('Collation') . '<div class="sorticon"></div></th>'
- . '<th class="' . $class . '" title="' . $title . '" data-column="attribute">'
+ . '<th class="' . $class . '" title="' . $title
+ . '" data-column="attribute">'
. __('Attribute') . '<div class="sorticon"></div></th>'
. '<th class="' . $class . '" title="' . $title . '" data-column="isnull">'
. __('Null') . '<div class="sorticon"></div></th>'
. '<th class="' . $class . '" title="' . $title . '" data-column="extra">'
- . __('Extra') . '<div class="sorticon"></div></th>'
- . '<th class="' . $class . '" title="' . $title . '" data-column="default">'
- . __('Default') . '<div class="sorticon"></div></th>'
+ . __('A_I') . '<div class="sorticon"></div></th>'
. '</tr>';
$tableheader .= '</thead>';
return $tableheader;
}
/**
+ * Function generate and return the table header for
+ * multiple edit central columns page
+ *
+ * @param array $header_cells headers list
+ *
+ * @return string html for table header in central columns multi edit page
+ */
+function PMA_getCentralColumnsEditTableHeader($header_cells)
+{
+ $html = '<table id="table_columns" class="noclick"'
+ . ' style="min-width: 100%;">';
+ $html .= '<caption class="tblHeaders">' . __('Structure');
+ $html .= '<tr>';
+ foreach ($header_cells as $header_val) {
+ $html .= '<th>' . $header_val . '</th>';
+ }
+ $html .= '</tr>';
+ return $html;
+}
+
+/**
* build the dropdown select html for tables of given database
*
* @param string $db current database
*
- * @return html dropdown for selecting table
+ * @return string html dropdown for selecting table
*/
function PMA_getHTMLforTableDropdown($db)
{
@@ -698,7 +763,7 @@ function PMA_getHTMLforTableDropdown($db)
* @param string $db current database to which selected table belongs
* @param string $selected_tbl selected table
*
- * @return html to select column
+ * @return string html to select column
*/
function PMA_getHTMLforColumnDropdown($db, $selected_tbl)
{
@@ -725,7 +790,7 @@ function PMA_getHTMLforColumnDropdown($db, $selected_tbl)
* @param int $pos offset of first result with complete result set
* @param string $db current database
*
- * @return html to add a column in the central list
+ * @return string html to add a column in the central list
*/
function PMA_getHTMLforAddCentralColumn($total_rows, $pos, $db)
{
@@ -767,7 +832,7 @@ function PMA_getHTMLforAddCentralColumn($total_rows, $pos, $db)
* @param int $row_num position the row in the table
* @param string $db current database
*
- * @return html of a particular row in the central columns table.
+ * @return string html of a particular row in the central columns table.
*/
function PMA_getHTMLforCentralColumnsTableRow($row, $odd_row, $row_num, $db)
{
@@ -777,6 +842,11 @@ function PMA_getHTMLforCentralColumnsTableRow($row, $odd_row, $row_num, $db)
$db
)
. '<input type="hidden" name="edit_save" value="save">'
+ . '<td class="nowrap">'
+ . '<input type="checkbox" class="checkall" name="selected_fld[]" '
+ . 'value="' . htmlspecialchars($row['col_name']) . '" '
+ . 'id="checkbox_row_' . $row_num . '"/>'
+ . '</td>'
. '<td id="edit_' . $row_num . '" class="edit center">'
. '<a href="#">' . PMA_Util::getIcon('b_edit.png', __('Edit')) . '</a></td>'
. '<td class="del_row" data-rownum = "' . $row_num . '">'
@@ -792,55 +862,195 @@ function PMA_getHTMLforCentralColumnsTableRow($row, $odd_row, $row_num, $db)
. '<span>' . htmlspecialchars($row['col_name']) . '</span>'
. '<input name="orig_col_name" type="hidden" '
. 'value="' . htmlspecialchars($row['col_name']) . '">'
- . PMA_getHtmlForColumnName(
- $row_num, 0, 0, array('Field'=>$row['col_name']),
- array('central_columnswork'=>false)
- )
+ . PMA\Template::get('columns_definitions/column_name')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 0,
+ 'ci_offset' => 0,
+ 'columnMeta' => array(
+ 'Field'=>$row['col_name']
+ ),
+ 'cfgRelation' => array(
+ 'centralcolumnswork' => false
+ )
+ )
+ )
. '</td>';
$tableHtml .=
'<td name = "col_type" class="nowrap"><span>'
. htmlspecialchars($row['col_type']) . '</span>'
- . PMA_getHtmlForColumnType(
- $row_num, 1, 0, /*overload*/mb_strtoupper($row['col_type']), array()
- )
+ . PMA\Template::get('columns_definitions/column_type')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 1,
+ 'ci_offset' => 0,
+ 'type_upper' => /*overload*/mb_strtoupper($row['col_type']),
+ 'columnMeta' => array()
+ )
+ )
. '</td>';
$tableHtml .=
'<td class="nowrap" name="col_length">'
. '<span>' . ($row['col_length']?htmlspecialchars($row['col_length']):"")
. '</span>'
- . PMA_getHtmlForColumnLength($row_num, 2, 0, 8, $row['col_length'])
+ . PMA\Template::get('columns_definitions/column_length')->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 2,
+ 'ci_offset' => 0,
+ 'length_values_input_size' => 8,
+ 'length_to_display' => $row['col_length']
+ )
+ )
+ . '</td>';
+
+ $meta = array();
+ if (!isset($row['col_default']) || $row['col_default'] == '') {
+ $meta['DefaultType'] = 'NONE';
+ } else {
+ if ($row['col_default'] == 'CURRENT_TIMESTAMP'
+ || $row['col_default'] == 'NULL'
+ ) {
+ $meta['DefaultType'] = $row['col_default'];
+ } else {
+ $meta['DefaultType'] = 'USER_DEFINED';
+ $meta['DefaultValue'] = $row['col_default'];
+ }
+ }
+ $tableHtml .=
+ '<td class="nowrap" name="col_default"><span>' . (isset($row['col_default'])
+ ? htmlspecialchars($row['col_default']) : 'None')
+ . '</span>'
+ . PMA\Template::get('columns_definitions/column_default')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 3,
+ 'ci_offset' => 0,
+ 'type_upper' => /*overload*/mb_strtoupper($row['col_type']),
+ 'columnMeta' => $meta
+ )
+ )
. '</td>';
$tableHtml .=
'<td name="collation" class="nowrap">'
. '<span>' . htmlspecialchars($row['col_collation']) . '</span>'
- . PMA_getHtmlForColumnCollation(
- $row_num, 3, 0, array('Collation'=>$row['col_collation'])
+ . PMA_generateCharsetDropdownBox(
+ PMA_CSDROPDOWN_COLLATION, 'field_collation[' . $row_num . ']',
+ 'field_' . $row_num . '_4', $row['col_collation'], false
)
. '</td>';
$tableHtml .=
'<td class="nowrap" name="col_attribute">'
. '<span>' .
($row['col_attribute']
- ? htmlspecialchars($row['col_attribute']) : "" )
+ ? htmlspecialchars($row['col_attribute']) : "" )
. '</span>'
- . PMA_getHtmlForColumnAttribute(
- $row_num, 4, 0, array(), $row['col_attribute'], false, null
- )
+ . PMA\Template::get('columns_definitions/column_attribute')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 5,
+ 'ci_offset' => 0,
+ 'extracted_columnspec' => array(),
+ 'columnMeta' => $row['col_attribute'],
+ 'submit_attribute' => false,
+ )
+ )
. '</td>';
$tableHtml .=
'<td class="nowrap" name="col_isNull">'
. '<span>' . ($row['col_isNull'] ? __('Yes') : __('No'))
. '</span>'
- . PMA_getHtmlForColumnNull($row_num, 5, 0, array('Null'=>$row['col_isNull']))
+ . PMA\Template::get('columns_definitions/column_null')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 6,
+ 'ci_offset' => 0,
+ 'columnMeta' => array(
+ 'Null' => $row['col_isNull']
+ )
+ )
+ )
. '</td>';
$tableHtml .=
'<td class="nowrap" name="col_extra"><span>'
. htmlspecialchars($row['col_extra']) . '</span>'
- . '<select name="col_extra"><option value=""></option>'
- . '<option value="auto_increment">' . __('auto_increment') . '</option>'
- . '</select>'
+ . PMA\Template::get('columns_definitions/column_extra')->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 7,
+ 'ci_offset' => 0,
+ 'columnMeta' => array('Extra'=>$row['col_extra'])
+ )
+ )
+ . '</td>';
+
+ $tableHtml .= '</tr>';
+
+ return $tableHtml;
+}
+
+/**
+ * build html for editing a row in central columns table
+ *
+ * @param array $row array contains complete information of
+ * a particular row of central list table
+ * @param boolean $odd_row set true if the row is at odd number position
+ * @param int $row_num position the row in the table
+ *
+ * @return string html of a particular row in the central columns table.
+ */
+function PMA_getHTMLforCentralColumnsEditTableRow($row, $odd_row, $row_num)
+{
+ $tableHtml = '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
+ . '<input name="orig_col_name[' . $row_num . ']" type="hidden" '
+ . 'value="' . htmlspecialchars($row['col_name']) . '">'
+ . '<td name="col_name" class="nowrap">'
+ . PMA\Template::get('columns_definitions/column_name')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 0,
+ 'ci_offset' => 0,
+ 'columnMeta' => array(
+ 'Field' => $row['col_name']
+ ),
+ 'cfgRelation' => array(
+ 'centralcolumnswork' => false
+ )
+ )
+ )
+ . '</td>';
+ $tableHtml .=
+ '<td name = "col_type" class="nowrap">'
+ . PMA\Template::get('columns_definitions/column_type')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 1,
+ 'ci_offset' => 0,
+ 'type_upper' => /*overload*/mb_strtoupper($row['col_type']),
+ 'columnMeta' => array()
+ )
+ )
+ . '</td>';
+ $tableHtml .=
+ '<td class="nowrap" name="col_length">'
+ . PMA\Template::get('columns_definitions/column_length')->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 2,
+ 'ci_offset' => 0,
+ 'length_values_input_size' => 8,
+ 'length_to_display' => $row['col_length']
+ )
+ )
. '</td>';
$meta = array();
if (!isset($row['col_default']) || $row['col_default'] == '') {
@@ -856,11 +1066,65 @@ function PMA_getHTMLforCentralColumnsTableRow($row, $odd_row, $row_num, $db)
}
}
$tableHtml .=
- '<td class="nowrap" name="col_default"><span>' . (isset($row['col_default'])
- ? htmlspecialchars($row['col_default']) : 'None')
- . '</span>'
- . PMA_getHtmlForColumnDefault(
- $row_num, 6, 0, /*overload*/mb_strtoupper($row['col_type']), '', $meta
+ '<td class="nowrap" name="col_default">'
+ . PMA\Template::get('columns_definitions/column_default')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 3,
+ 'ci_offset' => 0,
+ 'type_upper' => /*overload*/mb_strtoupper($row['col_default']),
+ 'columnMeta' => $meta
+ )
+ )
+ . '</td>';
+ $tableHtml .=
+ '<td name="collation" class="nowrap">'
+ . PMA_generateCharsetDropdownBox(
+ PMA_CSDROPDOWN_COLLATION, 'field_collation[' . $row_num . ']',
+ 'field_' . $row_num . '_4', $row['col_collation'], false
+ )
+ . '</td>';
+ $tableHtml .=
+ '<td class="nowrap" name="col_attribute">'
+ . PMA\Template::get('columns_definitions/column_attribute')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 5,
+ 'ci_offset' => 0,
+ 'extracted_columnspec' => array(
+ 'attribute' => $row['col_attribute']
+ ),
+ 'columnMeta' => array(),
+ 'submit_attribute' => false,
+ )
+ )
+ . '</td>';
+ $tableHtml .=
+ '<td class="nowrap" name="col_isNull">'
+ . PMA\Template::get('columns_definitions/column_null')
+ ->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 6,
+ 'ci_offset' => 0,
+ 'columnMeta' => array(
+ 'Null' => $row['col_isNull']
+ )
+ )
+ )
+ . '</td>';
+
+ $tableHtml .=
+ '<td class="nowrap" name="col_extra">'
+ . PMA\Template::get('columns_definitions/column_extra')->render(
+ array(
+ 'columnNumber' => $row_num,
+ 'ci' => 7,
+ 'ci_offset' => 0,
+ 'columnMeta' => array('Extra' => $row['col_extra'])
+ )
)
. '</td>';
$tableHtml .= '</tr>';
@@ -874,7 +1138,8 @@ function PMA_getHTMLforCentralColumnsTableRow($row, $odd_row, $row_num, $db)
* @param string $db selected database
* @param string $table current table name
*
- * @return encoded list of columns present in central list for the given database
+ * @return string encoded list of columns present in central list for the given
+ * database
*/
function PMA_getCentralColumnsListRaw($db, $table)
{
@@ -885,7 +1150,7 @@ function PMA_getCentralColumnsListRaw($db, $table)
$centralTable = $cfgCentralColumns['table'];
if (empty($table) || $table == '') {
$query = 'SELECT * FROM ' . PMA_Util::backquote($centralTable) . ' '
- . 'WHERE db_name = \'' . $db . '\';';
+ . 'WHERE db_name = \'' . $db . '\';';
} else {
$GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
$columns = (array) $GLOBALS['dbi']->getColumnNames(
@@ -912,10 +1177,52 @@ function PMA_getCentralColumnsListRaw($db, $table)
}
/**
+ * Get HTML for "check all" check box with "with selected" dropdown
+ *
+ * @param string $pmaThemeImage pma theme image url
+ * @param string $text_dir url for text directory
+ *
+ * @return string $html_output
+ */
+function PMA_getCentralColumnsTableFooter($pmaThemeImage, $text_dir)
+{
+ $html_output = PMA_Util::getWithSelected(
+ $pmaThemeImage, $text_dir, "tableslistcontainer"
+ );
+ $html_output .= PMA_Util::getButtonOrImage(
+ 'edit_central_columns', 'mult_submit change_central_columns',
+ 'submit_mult_change', __('Edit'), 'b_edit.png', 'edit central columns'
+ );
+ $html_output .= PMA_Util::getButtonOrImage(
+ 'delete_central_columns', 'mult_submit',
+ 'submit_mult_central_columns_remove',
+ __('Delete'), 'b_drop.png',
+ 'remove_from_central_columns'
+ );
+ return $html_output;
+}
+
+/**
+ * function generate and return the table footer for
+ * multiple edit central columns page
+ *
+ * @return string html for table footer in central columns multi edit page
+ */
+function PMA_getCentralColumnsEditTableFooter()
+{
+ $html_output = '<fieldset class="tblFooters">'
+ . '<input type="submit" '
+ . 'name="save_multi_central_column_edit" value="' . __('Save') . '" />'
+ . '</fieldset>';
+ return $html_output;
+}
+/**
* Column `col_extra` is used to store both extra and attributes for a column.
* This method separates them.
*
- * @param array columns_list columns list
+ * @param array &$columns_list columns list
+ *
+ * @return void
*/
function PMA_handleColumnExtra(&$columns_list)
{
@@ -947,7 +1254,8 @@ function PMA_handleColumnExtra(&$columns_list)
*
* @param string $db current database
*
- * @return html of the form to let user add a new user defined column to the list
+ * @return string html of the form to let user add a new user defined column to the
+ * list
*/
function PMA_getHTMLforAddNewColumn($db)
{
@@ -962,36 +1270,95 @@ function PMA_getHTMLforAddNewColumn($db)
. '<table>';
$addNewColumn .= PMA_getCentralColumnsTableHeader();
$addNewColumn .= '<tr>'
+ . '<td></td>'
. '<td name="col_name" class="nowrap">'
- . PMA_getHtmlForColumnName(
- 0, 0, 0, array(), array('central_columnswork'=>false)
- )
+ . PMA\Template::get('columns_definitions/column_name')
+ ->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 0,
+ 'ci_offset' => 0,
+ 'columnMeta' => array(),
+ 'cfgRelation' => array(
+ 'centralcolumnswork' => false
+ )
+ )
+ )
. '</td>'
. '<td name = "col_type" class="nowrap">'
- . PMA_getHtmlForColumnType(0, 1, 0, '', array())
+ . PMA\Template::get('columns_definitions/column_type')
+ ->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 1,
+ 'ci_offset' => 0,
+ 'type_upper' => '',
+ 'columnMeta' => array()
+ )
+ )
. '</td>'
. '<td class="nowrap" name="col_length">'
- . PMA_getHtmlForColumnLength(0, 2, 0, 8, '')
+ . PMA\Template::get('columns_definitions/column_length')->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 2,
+ 'ci_offset' => 0,
+ 'length_values_input_size' => 8,
+ 'length_to_display' => ''
+ )
+ )
+ . '</td>'
+ . '<td class="nowrap" name="col_default">'
+ . PMA\Template::get('columns_definitions/column_default')
+ ->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 3,
+ 'ci_offset' => 0,
+ 'type_upper' => '',
+ 'columnMeta' => array()
+ )
+ )
. '</td>'
. '<td name="collation" class="nowrap">'
- . PMA_getHtmlForColumnCollation(
- 0, 3, 0, array()
+ . PMA_generateCharsetDropdownBox(
+ PMA_CSDROPDOWN_COLLATION, 'field_collation[0]',
+ 'field_0_4', null, false
)
. '</td>'
. '<td class="nowrap" name="col_attribute">'
- . PMA_getHtmlForColumnAttribute(0, 4, 0, array(), array(), false, null)
+ . PMA\Template::get('columns_definitions/column_attribute')
+ ->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 5,
+ 'ci_offset' => 0,
+ 'extracted_columnspec' => array(),
+ 'columnMeta' => array(),
+ 'submit_attribute' => false,
+ )
+ )
. '</td>'
. '<td class="nowrap" name="col_isNull">'
- . PMA_getHtmlForColumnNull(0, 5, 0, array())
+ . PMA\Template::get('columns_definitions/column_null')
+ ->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 6,
+ 'ci_offset' => 0,
+ 'columnMeta' => array()
+ )
+ )
. '</td>'
. '<td class="nowrap" name="col_extra">'
- . '<select name="col_extra"><option value="">'
- . '<option value="auto_increment">' . __('auto_increment') . '</option>'
- . '<option value="on update CURRENT_TIMESTAMP">'
- . __('on update CURRENT_TIMESTAMP') . '</option></select>'
- . '</td>'
- . '<td class="nowrap" name="col_default">'
- . PMA_getHtmlForColumnDefault(0, 6, 0, '', '', array())
+ . PMA\Template::get('columns_definitions/column_extra')->render(
+ array(
+ 'columnNumber' => 0,
+ 'ci' => 7,
+ 'ci_offset' => 0,
+ 'columnMeta' => array()
+ )
+ )
. '</td>'
. ' <td>'
. '<input id="add_column_save" type="submit" '
@@ -1000,4 +1367,42 @@ function PMA_getHTMLforAddNewColumn($db)
$addNewColumn .= '</table></form></div>';
return $addNewColumn;
}
-?>
+
+/**
+ * Get HTML for editing page central columns
+ *
+ * @param array $selected_fld Array containing the selected fields
+ * @param string $selected_db String containing the name of database
+ *
+ * @return string HTML for complete editing page for central columns
+ */
+function PMA_getHTMLforEditingPage($selected_fld,$selected_db)
+{
+ $html = '<form id="multi_edit_central_columns">';
+ $header_cells = array(
+ __('Name'), __('Type'), __('Length/Values'), __('Default'),
+ __('Collation'), __('Attributes'), __('Null'), __('A_I')
+ );
+ $html .= PMA_getCentralColumnsEditTableHeader($header_cells);
+ $selected_fld_safe = array();
+ foreach ($selected_fld as $key) {
+ $selected_fld_safe[] = PMA_Util::sqlAddSlashes($key);
+ }
+ $columns_list = implode("','", $selected_fld_safe);
+ $columns_list = "'" . $columns_list . "'";
+ $list_detail_cols = PMA_findExistingColNames($selected_db, $columns_list, true);
+ $odd_row = false;
+ $row_num = 0;
+ foreach ($list_detail_cols as $row) {
+ $tableHtmlRow = PMA_getHTMLforCentralColumnsEditTableRow(
+ $row, $odd_row, $row_num
+ );
+ $html .= $tableHtmlRow;
+ $odd_row = !$odd_row;
+ $row_num++;
+ }
+ $html .= '</table>';
+ $html .= PMA_getCentralColumnsEditTableFooter();
+ $html .= '</form>';
+ return $html;
+}
diff --git a/libraries/charset_conversion.lib.php b/libraries/charset_conversion.lib.php
index 27c0b8bf5d..e3dd9a40ab 100644
--- a/libraries/charset_conversion.lib.php
+++ b/libraries/charset_conversion.lib.php
@@ -60,9 +60,9 @@ if ($PMA_recoding_engine == PMA_CHARSET_ICONV_AIX) {
}
/**
- * Determines the correct recoding engine to use
+ * Determines the correct recoding engine to use
*
- * @return int $PMA_recoding_engine
+ * @return int $PMA_recoding_engine
*
* @access public
*
@@ -117,4 +117,3 @@ function PMA_convertString($src_charset, $dest_charset, $what)
}
} // end of the "PMA_convertString()" function
-?>
diff --git a/libraries/check_user_privileges.lib.php b/libraries/check_user_privileges.lib.php
index db4299c7d9..1b57c4e8c6 100644
--- a/libraries/check_user_privileges.lib.php
+++ b/libraries/check_user_privileges.lib.php
@@ -15,6 +15,208 @@ if (! defined('PHPMYADMIN')) {
$GLOBALS['is_superuser'] = $GLOBALS['dbi']->isSuperuser();
/**
+ * Check if user has required privileges for
+ * performing 'FLUSH PRIVILEGES' operation
+ *
+ * @return void
+ */
+function PMA_checkRequiredPrivilegesForFlushing()
+{
+
+ $res = $GLOBALS['dbi']->tryQuery(
+ 'FLUSH PRIVILEGES'
+ );
+
+ // Save the value
+ $GLOBALS['flush_priv'] = $res;
+}
+
+/**
+ * Check if user has required privileges for
+ * performing 'Adjust privileges' operations
+ *
+ * @return void
+ */
+function PMA_checkRequiredPrivilgesForAdjust()
+{
+ $privs_available = true;
+ // FOR DB PRIVS
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`db` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`db` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" LIMIT 1'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`db`(`host`, `Db`, `User`) VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`db` WHERE host = "pma_test_host" AND '
+ . 'Db = "mysql" AND User = "pma_test_user" LIMIT 1'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`db` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" LIMIT 1'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+ }
+ // save the value
+ $GLOBALS['db_priv'] = $privs_available;
+ // reset the value
+ $privs_available = true;
+
+ // FOR COLUMNS_PRIV
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`columns_priv` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`columns_priv` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" LIMIT 1'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`columns_priv`(`host`, `Db`, `User`, `Table_name`,'
+ . ' `Column_name`) VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user", "", "")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`columns_priv` WHERE host = "pma_test_host" AND '
+ . 'Db = "mysql" AND User = "pma_test_user" AND Table_name = ""'
+ . ' AND Column_name = "" LIMIT 1'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`columns_priv` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND Column_name = "" AND Table_name = "" LIMIT 1'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+
+ }
+ // Save the value
+ $GLOBALS['col_priv'] = $privs_available;
+ // Reset the value
+ $privs_available = true;
+
+ // FOR TABLES_PRIV
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`tables_priv` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`tables_priv` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND Table_name = "" LIMIT 1'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`tables_priv`(`host`, `Db`, `User`, `Table_name`'
+ . ') VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user", "")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`tables_priv` WHERE host = "pma_test_host" AND '
+ . 'Db = "mysql" AND User = "pma_test_user" AND Table_name = "" LIMIT 1'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`tables_priv` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND Table_name = "" LIMIT 1'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+
+ }
+ // Save the value
+ $GLOBALS['table_priv'] = $privs_available;
+ // Reset the value
+ $privs_available = true;
+
+ // FOR PROCS_PRIV
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`procs_priv` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`procs_priv` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND `Routine_name` = ""'
+ . ' AND `Routine_type` = "" LIMIT 1'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`procs_priv`(`host`, `Db`, `User`, `Routine_name`,'
+ . ' `Routine_type`) VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user", "", "PROCEDURE")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`procs_priv` WHERE `host` = "pma_test_host" AND '
+ . '`Db` = "mysql" AND `User` = "pma_test_user" AND `Routine_name` = ""'
+ . ' AND `Routine_type` = "PROCEDURE" LIMIT 1'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`procs_priv` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND `Routine_name` = "" LIMIT 1'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+ }
+ // Save the value
+ $GLOBALS['proc_priv'] = $privs_available;
+
+}
+
+/**
* sets privilege information extracted from SHOW GRANTS result
*
* Detection for some CREATE privilege.
@@ -38,9 +240,6 @@ function PMA_analyseShowGrant()
$GLOBALS['is_create_db_priv'] = PMA_Util::cacheGet(
'is_create_db_priv'
);
- $GLOBALS['is_process_priv'] = PMA_Util::cacheGet(
- 'is_process_priv'
- );
$GLOBALS['is_reload_priv'] = PMA_Util::cacheGet(
'is_reload_priv'
);
@@ -58,7 +257,6 @@ function PMA_analyseShowGrant()
// defaults
$GLOBALS['is_create_db_priv'] = false;
- $GLOBALS['is_process_priv'] = true;
$GLOBALS['is_reload_priv'] = false;
$GLOBALS['db_to_create'] = '';
$GLOBALS['dbs_where_create_table_allowed'] = array();
@@ -169,7 +367,6 @@ function PMA_analyseShowGrant()
// must also cacheUnset() them in
// libraries/plugins/auth/AuthenticationCookie.class.php
PMA_Util::cacheSet('is_create_db_priv', $GLOBALS['is_create_db_priv']);
- PMA_Util::cacheSet('is_process_priv', $GLOBALS['is_process_priv']);
PMA_Util::cacheSet('is_reload_priv', $GLOBALS['is_reload_priv']);
PMA_Util::cacheSet('db_to_create', $GLOBALS['db_to_create']);
PMA_Util::cacheSet(
@@ -180,16 +377,30 @@ function PMA_analyseShowGrant()
} // end function
if (!PMA_DRIZZLE) {
- PMA_analyseShowGrant();
+ $user = $GLOBALS['dbi']->fetchValue("SELECT CURRENT_USER();");
+ if ($user == '@') { // MySQL is started with --skip-grant-tables
+ $GLOBALS['is_create_db_priv'] = true;
+ $GLOBALS['is_reload_priv'] = true;
+ $GLOBALS['db_to_create'] = '';
+ $GLOBALS['dbs_where_create_table_allowed'] = array('*');
+ $GLOBALS['dbs_to_test'] = false;
+ } else {
+ PMA_analyseShowGrant();
+ }
+
+ // Check if privileges to 'mysql'.col_privs, 'mysql'.db,
+ // 'mysql'.table_privs, 'mysql'.proc_privs and privileges for
+ // flushing the privileges are available
+ PMA_checkRequiredPrivilegesForFlushing();
+ PMA_checkRequiredPrivilgesForAdjust();
+
} else {
// todo: for simple_user_policy only database with user's login can be created
// (unless logged in as root)
$GLOBALS['is_create_db_priv'] = $GLOBALS['is_superuser'];
- $GLOBALS['is_process_priv'] = false;
$GLOBALS['is_reload_priv'] = false;
$GLOBALS['db_to_create'] = '';
$GLOBALS['dbs_where_create_table_allowed'] = array('*');
$GLOBALS['dbs_to_test'] = false;
}
-?>
diff --git a/libraries/cleanup.lib.php b/libraries/cleanup.lib.php
index 2874f5a0e2..8db63cb56e 100644
--- a/libraries/cleanup.lib.php
+++ b/libraries/cleanup.lib.php
@@ -29,22 +29,22 @@ function PMA_removeRequestVars(&$whitelist)
foreach ($keys as $key) {
if (! in_array($key, $whitelist)) {
unset($_REQUEST[$key], $_GET[$key], $_POST[$key], $GLOBALS[$key]);
- } else {
- // allowed stuff could be compromised so escape it
- // we require it to be a string
- if (isset($_REQUEST[$key]) && ! is_string($_REQUEST[$key])) {
- unset($_REQUEST[$key]);
- }
- if (isset($_POST[$key]) && ! is_string($_POST[$key])) {
- unset($_POST[$key]);
- }
- if (isset($_COOKIE[$key]) && ! is_string($_COOKIE[$key])) {
- unset($_COOKIE[$key]);
- }
- if (isset($_GET[$key]) && ! is_string($_GET[$key])) {
- unset($_GET[$key]);
- }
+ continue;
+ }
+
+ // allowed stuff could be compromised so escape it
+ // we require it to be a string
+ if (isset($_REQUEST[$key]) && ! is_string($_REQUEST[$key])) {
+ unset($_REQUEST[$key]);
+ }
+ if (isset($_POST[$key]) && ! is_string($_POST[$key])) {
+ unset($_POST[$key]);
+ }
+ if (isset($_COOKIE[$key]) && ! is_string($_COOKIE[$key])) {
+ unset($_COOKIE[$key]);
+ }
+ if (isset($_GET[$key]) && ! is_string($_GET[$key])) {
+ unset($_GET[$key]);
}
}
}
-?>
diff --git a/libraries/common.inc.php b/libraries/common.inc.php
index 8a96f8480a..ea15788d13 100644
--- a/libraries/common.inc.php
+++ b/libraries/common.inc.php
@@ -42,8 +42,8 @@ if (getcwd() == dirname(__FILE__)) {
* Minimum PHP version; can't call PMA_fatalError() which uses a
* PHP 5 function, so cannot easily localize this message.
*/
-if (version_compare(PHP_VERSION, '5.3.0', 'lt')) {
- die('PHP 5.3+ is required');
+if (version_compare(PHP_VERSION, '5.5.0', 'lt')) {
+ die('PHP 5.5+ is required');
}
/**
@@ -376,7 +376,6 @@ $goto_whitelist = array(
'db_structure.php',
'db_import.php',
'db_operations.php',
- 'db_printview.php',
'db_search.php',
'db_routines.php',
'export.php',
@@ -408,7 +407,6 @@ $goto_whitelist = array(
'tbl_create.php',
'tbl_import.php',
'tbl_indexes.php',
- 'tbl_printview.php',
'tbl_sql.php',
'tbl_export.php',
'tbl_operations.php',
@@ -580,7 +578,10 @@ $GLOBALS['PMA_Config']->checkPermissions();
if ($GLOBALS['PMA_Config']->error_config_file) {
$error = '[strong]' . __('Failed to read configuration file!') . '[/strong]'
. '[br][br]'
- . __('This usually means there is a syntax error in it, please check any errors shown below.')
+ . __(
+ 'This usually means there is a syntax error in it, '
+ . 'please check any errors shown below.'
+ )
. '[br][br]'
. '[conferr]';
trigger_error($error, E_USER_ERROR);
@@ -641,7 +642,10 @@ if (! isset($cfg['Servers']) || count($cfg['Servers']) == 0) {
if ($each_server['connect_type'] == 'tcp' && empty($each_server['host'])) {
trigger_error(
sprintf(
- __('Invalid hostname for server %1$s. Please review your configuration.'),
+ __(
+ 'Invalid hostname for server %1$s. '
+ . 'Please review your configuration.'
+ ),
$server_index
),
E_USER_ERROR
@@ -864,11 +868,14 @@ if (! defined('PMA_MINIMUM_COMMON')) {
include_once './libraries/plugins/auth/' . $auth_class . '.class.php';
// todo: add plugin manager
$plugin_manager = null;
+ /** @var AuthenticationPlugin $auth_plugin */
$auth_plugin = new $auth_class($plugin_manager);
if (! $auth_plugin->authCheck()) {
/* Force generating of new session on login */
- PMA_secureSession();
+ if ($token_provided) {
+ PMA_secureSession();
+ }
$auth_plugin->auth();
} else {
$auth_plugin->authSetUser();
@@ -979,6 +986,7 @@ if (! defined('PMA_MINIMUM_COMMON')) {
}
// Connects to the server (validates user's login)
+ /** @var PMA_DatabaseInterface $userlink */
$userlink = $GLOBALS['dbi']->connect(
$cfg['Server']['user'], $cfg['Server']['password'], false
);
@@ -986,13 +994,19 @@ if (! defined('PMA_MINIMUM_COMMON')) {
// Set timestamp for the session, if required.
if ($cfg['Server']['SessionTimeZone'] != '') {
$sql_query_tz = 'SET ' . PMA_Util::backquote('time_zone') . ' = '
- . '\'' . PMA_Util::sqlAddSlashes($cfg['Server']['SessionTimeZone']) . '\'';
-
- if(! $userlink->query($sql_query_tz)) {
- $error_message_tz = sprintf(__('Unable to use timezone %1$s for server %2$d. '
- . 'Please check your configuration setting for '
- . '[em]$cfg[\'Servers\'][%3$d][\'SessionTimeZone\'][/em]. '
- . 'phpMyAdmin is currently using the default time zone of the database server.'),
+ . '\''
+ . PMA_Util::sqlAddSlashes($cfg['Server']['SessionTimeZone'])
+ . '\'';
+
+ if (! $userlink->query($sql_query_tz)) {
+ $error_message_tz = sprintf(
+ __(
+ 'Unable to use timezone %1$s for server %2$d. '
+ . 'Please check your configuration setting for '
+ . '[em]$cfg[\'Servers\'][%3$d][\'SessionTimeZone\'][/em]. '
+ . 'phpMyAdmin is currently using the default time zone '
+ . 'of the database server.'
+ ),
$cfg['Servers'][$GLOBALS['server']]['SessionTimeZone'],
$GLOBALS['server'],
$GLOBALS['server']
@@ -1017,10 +1031,10 @@ if (! defined('PMA_MINIMUM_COMMON')) {
/* Log success */
PMA_logUser($cfg['Server']['user']);
- if (PMA_MYSQL_INT_VERSION < 50500) {
+ if (PMA_MYSQL_INT_VERSION < $cfg['MysqlMinVersion']['internal']) {
PMA_fatalError(
__('You should upgrade to %s %s or later.'),
- array('MySQL', '5.5.0')
+ array('MySQL', $cfg['MysqlMinVersion']['human'])
);
}
@@ -1042,9 +1056,32 @@ if (! defined('PMA_MINIMUM_COMMON')) {
}
/**
- * SQL Parser code
+ * Charset information
*/
- include_once './libraries/sqlparser.lib.php';
+ if (!PMA_DRIZZLE) {
+ include_once './libraries/mysql_charsets.inc.php';
+ }
+ if (!isset($mysql_charsets)) {
+ $mysql_charsets = array();
+ $mysql_collations_flat = array();
+ }
+
+ /**
+ * Initializes the SQL parsing library.
+ */
+ include_once SQL_PARSER_AUTOLOAD;
+
+ // Loads closest context to this version.
+ SqlParser\Context::loadClosest(
+ (PMA_DRIZZLE ? 'Drizzle' : 'MySql') . PMA_MYSQL_INT_VERSION
+ );
+
+ // Sets the default delimiter (if specified).
+ if (!empty($_REQUEST['sql_delimiter'])) {
+ SqlParser\Lexer::$DEFAULT_DELIMITER = $_REQUEST['sql_delimiter'];
+ }
+
+ // TODO: Set SQL modes too.
/**
* the PMA_List_Database class
@@ -1200,4 +1237,7 @@ if (! defined('PMA_MINIMUM_COMMON')
}
}
}
-?>
+
+if (! defined('PMA_MINIMUM_COMMON')) {
+ include_once 'libraries/config/page_settings.class.php';
+}
diff --git a/libraries/config.default.php b/libraries/config.default.php
index 6abfd117a9..f059f5bfd0 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -480,6 +480,25 @@ $cfg['Servers'][$i]['savedsearches'] = '';
* @global string $cfg['Servers'][$i]['central_columns']
*/
$cfg['Servers'][$i]['central_columns'] = '';
+
+/**
+ * table to store designer settings
+ * - leave blank to disable the storage of designer settings
+ * SUGGESTED: 'pma__designer_settings'
+ *
+ * @global string $cfg['Servers'][$i]['designer_settings']
+ */
+$cfg['Servers'][$i]['designer_settings'] = '';
+
+/**
+ * table to store export templates
+ * - leave blank to disable saved searches feature
+ * SUGGESTED: 'pma__export_templates'
+ *
+ * @global string $cfg['Servers'][$i]['export_templates']
+ */
+$cfg['Servers'][$i]['export_templates'] = '';
+
/**
* Maximum number of records saved in $cfg['Servers'][$i]['table_uiprefs'] table.
*
@@ -544,7 +563,6 @@ $cfg['Servers'][$i]['DisableIS'] = false;
*
* @global bool $cfg['Servers'][$i]['tracking_version_auto_create']
*/
-
$cfg['Servers'][$i]['tracking_version_auto_create'] = false;
/**
@@ -553,7 +571,6 @@ $cfg['Servers'][$i]['tracking_version_auto_create'] = false;
*
* @global string $cfg['Servers'][$i]['tracking_default_statements']
*/
-
$cfg['Servers'][$i]['tracking_default_statements']
= 'CREATE TABLE,ALTER TABLE,DROP TABLE,RENAME TABLE,CREATE INDEX,' .
'DROP INDEX,INSERT,UPDATE,DELETE,TRUNCATE,REPLACE,CREATE VIEW,' .
@@ -565,7 +582,6 @@ $cfg['Servers'][$i]['tracking_default_statements']
*
* @global bool $cfg['Servers'][$i]['tracking_add_drop_view']
*/
-
$cfg['Servers'][$i]['tracking_add_drop_view'] = true;
/**
@@ -574,7 +590,6 @@ $cfg['Servers'][$i]['tracking_add_drop_view'] = true;
*
* @global bool $cfg['Servers'][$i]['tracking_add_drop_table']
*/
-
$cfg['Servers'][$i]['tracking_add_drop_table'] = true;
/**
@@ -583,7 +598,6 @@ $cfg['Servers'][$i]['tracking_add_drop_table'] = true;
*
* @global bool $cfg['Servers'][$i]['tracking_add_drop_database']
*/
-
$cfg['Servers'][$i]['tracking_add_drop_database'] = true;
/**
@@ -706,7 +720,7 @@ $cfg['ExecTimeLimit'] = 300;
$cfg['SessionSavePath'] = '';
/**
- * maximum allocated bytes ('-1' for no limit)
+ * maximum allocated bytes ('-1' for no limit, '0' for no change)
* this is a string because '16M' is a valid value; we must put here
* a string as the default value so that /setup accepts strings
*
@@ -744,6 +758,13 @@ $cfg['RetainQueryBox'] = false;
$cfg['CodemirrorEnable'] = true;
/**
+ * use the parser to find any errors in the query before executing
+ *
+ * @global boolean $cfg['LintEnable']
+ */
+$cfg['LintEnable'] = true;
+
+/**
* show a 'Drop database' link to normal users
*
* @global boolean $cfg['AllowUserDropDatabase']
@@ -962,25 +983,25 @@ $cfg['NavigationTreeDisplayDbFilterMinimum'] = 30;
* target of the navigation panel quick access icon
*
* Possible values:
- * 'tbl_structure.php' = fields list
- * 'tbl_sql.php' = SQL form
- * 'tbl_select.php' = search page
- * 'tbl_change.php' = insert row page
- * 'sql.php' = browse page
+ * 'structure.php' = fields list
+ * 'sql' = SQL form
+ * 'search' = search page
+ * 'insert' = insert row page
+ * 'browse' = browse page
*
* @global string $cfg['NavigationTreeDefaultTabTable']
*/
-$cfg['NavigationTreeDefaultTabTable'] = 'tbl_structure.php';
+$cfg['NavigationTreeDefaultTabTable'] = 'structure';
/**
* target of the navigation panel quick second access icon
*
* Possible values:
- * 'tbl_structure.php' = fields list
- * 'tbl_sql.php' = SQL form
- * 'tbl_select.php' = search page
- * 'tbl_change.php' = insert row page
- * 'sql.php' = browse page
+ * 'structure' = fields list
+ * 'sql' = SQL form
+ * 'search' = search page
+ * 'insert' = insert row page
+ * 'browse' = browse page
* '' = no link
*
* @global string $cfg['NavigationTreeDefaultTabTable2']
@@ -994,6 +1015,41 @@ $cfg['NavigationTreeDefaultTabTable2'] = '';
*/
$cfg['NavigationTreeEnableExpansion'] = true;
+/**
+ * Show tables in navigation panel
+ *
+ * @global boolean $cfg['NavigationTreeShowTables']
+ */
+$cfg['NavigationTreeShowTables'] = true;
+
+/**
+ * Show views in navigation panel
+ *
+ * @global boolean $cfg['NavigationTreeShowViews']
+ */
+$cfg['NavigationTreeShowViews'] = true;
+
+/**
+ * Show functions in navigation panel
+ *
+ * @global boolean $cfg['NavigationTreeShowFunctions']
+ */
+$cfg['NavigationTreeShowFunctions'] = true;
+
+/**
+ * Show procedures in navigation panel
+ *
+ * @global boolean $cfg['NavigationTreeShowProcedures']
+ */
+$cfg['NavigationTreeShowProcedures'] = true;
+
+/**
+ * Show events in navigation panel
+ *
+ * @global boolean $cfg['NavigationTreeShowEvents']
+ */
+$cfg['NavigationTreeShowEvents'] = true;
+
/*******************************************************************************
* In the main panel, at startup...
*/
@@ -1040,6 +1096,13 @@ $cfg['ShowCreateDb'] = true;
*/
/**
+ * show comment column in database structure (true|false)?
+ *
+ * @global boolean $cfg['ShowDbStructureComment']
+ */
+$cfg['ShowDbStructureComment'] = false;
+
+/**
* show creation timestamp column in database structure (true|false)?
*
* @global boolean $cfg['ShowDbStructureCreation']
@@ -1111,7 +1174,6 @@ $cfg['Order'] = 'SMART';
*
* @global boolean $cfg['SaveCellsAtOnce']
*/
-
$cfg['SaveCellsAtOnce'] = false;
/**
@@ -1136,7 +1198,6 @@ $cfg['GridEditing'] ='double-click';
* @global string $cfg['RelationalDisplay']
*
*/
-
$cfg['RelationalDisplay'] = 'K';
@@ -1215,6 +1276,12 @@ $cfg['ForeignKeyDropdownOrder'] = array('content-id', 'id-content');
*/
$cfg['ForeignKeyMaxLimit'] = 100;
+/**
+ * Whether to disable foreign key checks while importing
+ *
+ * @global boolean $cfg['DefaultForeignKeyChecks']
+ */
+$cfg['DefaultForeignKeyChecks'] = 'default';
/*******************************************************************************
* For the export features...
@@ -1278,39 +1345,39 @@ $cfg['PropertiesNumColumns'] = 1;
/**
* Possible values:
- * 'index.php' = the welcome page
+ * 'welcome' = the welcome page
* (recommended for multiuser setups)
- * 'server_databases.php' = list of databases
- * 'server_status.php' = runtime information
- * 'server_variables.php' = MySQL server variables
- * 'server_privileges.php' = user management
+ * 'databases' = list of databases
+ * 'status' = runtime information
+ * 'variables' = MySQL server variables
+ * 'privileges' = user management
*
* @global string $cfg['DefaultTabServer']
*/
-$cfg['DefaultTabServer'] = 'index.php';
+$cfg['DefaultTabServer'] = 'welcome';
/**
* Possible values:
- * 'db_structure.php' = tables list
- * 'db_sql.php' = SQL form
- * 'db_search.php' = search query
- * 'db_operations.php' = operations on database
+ * 'structure' = tables list
+ * 'sql' = SQL form
+ * 'search' = search query
+ * 'operations' = operations on database
*
* @global string $cfg['DefaultTabDatabase']
*/
-$cfg['DefaultTabDatabase'] = 'db_structure.php';
+$cfg['DefaultTabDatabase'] = 'structure';
/**
* Possible values:
- * 'tbl_structure.php' = fields list
- * 'tbl_sql.php' = SQL form
- * 'tbl_select.php' = search page
- * 'tbl_change.php' = insert row page
- * 'sql.php' = browse page
+ * 'structure' = fields list
+ * 'sql' = SQL form
+ * 'search' = search page
+ * 'insert' = insert row page
+ * 'browse' = browse page
*
* @global string $cfg['DefaultTabTable']
*/
-$cfg['DefaultTabTable'] = 'sql.php';
+$cfg['DefaultTabTable'] = 'browse';
/**
* Whether to display image or text or both image and text in table row
@@ -1345,6 +1412,20 @@ $cfg['Export']['method'] = 'quick';
$cfg['Export']['compression'] = 'none';
/**
+ * Whether to LOCK TABLES before exporting
+ *
+ * @global boolean $cfg['Export']['lock_tables']
+ */
+$cfg['Export']['lock_tables'] = false;
+
+/**
+ * Whether to export databases/tables as separate files
+ *
+ * @global boolean $cfg['Export']['as_separate_files']
+ */
+$cfg['Export']['as_separate_files'] = false;
+
+/**
*
*
* @global boolean $cfg['Export']['asfile']
@@ -1763,8 +1844,8 @@ $cfg['Export']['mediawiki_structure_or_data'] = 'data';
*
* @global boolean $cfg['Export']['mediawiki_caption']
*/
-
$cfg['Export']['mediawiki_caption'] = true;
+
/**
*
*
@@ -1801,6 +1882,13 @@ $cfg['Export']['phparray_structure_or_data'] = 'data';
$cfg['Export']['json_structure_or_data'] = 'data';
/**
+ * Export functions
+ *
+ * @global string $cfg['Export']['json_pretty_print']
+ */
+$cfg['Export']['json_pretty_print'] = false;
+
+/**
*
*
* @global string $cfg['Export']['sql_structure_or_data']
@@ -1827,6 +1915,7 @@ $cfg['Export']['sql_include_comments'] = true;
* @global boolean $cfg['Export']['sql_disable_fk']
*/
$cfg['Export']['sql_disable_fk'] = false;
+
/**
*
*
@@ -1837,6 +1926,13 @@ $cfg['Export']['sql_views_as_tables'] = false;
/**
*
*
+ * @global boolean $cfg['Export']['sql_metadata']
+ */
+$cfg['Export']['sql_metadata'] = false;
+
+/**
+ *
+ *
* @global boolean $cfg['Export']['sql_use_transaction']
*/
$cfg['Export']['sql_use_transaction'] = false;
@@ -1869,7 +1965,7 @@ $cfg['Export']['sql_drop_table'] = false;
* of VIEWs and the stand-in table
* @global boolean $cfg['Export']['sql_if_not_exists']
*/
-$cfg['Export']['sql_if_not_exists'] = true;
+$cfg['Export']['sql_if_not_exists'] = false;
/**
*
@@ -1991,13 +2087,6 @@ $cfg['Export']['sql_mime'] = false;
$cfg['Export']['sql_header_comment'] = '';
/**
- *
- *
- * @global boolean $cfg['Export']['sql_create_table_statements']
- */
-$cfg['Export']['sql_create_table_statements'] = true;
-
-/**
* Whether to use complete inserts, extended inserts, both, or neither
*
* @global string $cfg['Export']['sql_insert_syntax']
@@ -2360,6 +2449,13 @@ $cfg['Schema']['pdf_with_doc'] = true;
/**
*
*
+ * @global string $cfg['Schema']['pdf_table_order']
+ */
+$cfg['Schema']['pdf_table_order'] = '';
+
+/**
+ *
+ *
* @global string $cfg['Schema']['dia_show_color']
*/
$cfg['Schema']['dia_show_color'] = true;
@@ -2645,6 +2741,14 @@ $cfg['LimitChars'] = 50;
$cfg['RowActionLinks'] = 'left';
/**
+ * Whether to show row links (Edit, Copy, Delete) and checkboxes for
+ * multiple row operations even when the selection does not have a unique key.
+ *
+ * @global boolean $cfg['RowActionLinksWithoutUnique']
+ */
+$cfg['RowActionLinksWithoutUnique'] = false;
+
+/**
* Default sort order by primary key.
* @global string $cfg['TablePrimaryKeyOrder']
*/
@@ -2837,33 +2941,40 @@ $cfg['DefaultQueryDatabase'] = '';
$cfg['SQLQuery'] = array();
/**
- * Edit link to change a query
+ * Display an "Edit" link on the results page to change a query
*
* @global boolean $cfg['SQLQuery']['Edit']
*/
$cfg['SQLQuery']['Edit'] = true;
/**
- * EXPLAIN on SELECT queries
+ * Display an "Explain SQL" link on the results page
*
* @global boolean $cfg['SQLQuery']['Explain']
*/
$cfg['SQLQuery']['Explain'] = true;
/**
- * Wrap a query in PHP
+ * Display a "Create PHP code" link on the results page to wrap a query in PHP
*
* @global boolean $cfg['SQLQuery']['ShowAsPHP']
*/
$cfg['SQLQuery']['ShowAsPHP'] = true;
/**
- * Refresh the results page
+ * Display a "Refresh" link on the results page
*
* @global boolean $cfg['SQLQuery']['Refresh']
*/
$cfg['SQLQuery']['Refresh'] = true;
+/**
+ * Enables autoComplete for table & column names in SQL queries
+ *
+ * default = 'true'
+ */
+$cfg['EnableAutocompleteForTablesAndColumns'] = true;
+
/*******************************************************************************
* Web server upload/save/import directories
@@ -2957,6 +3068,13 @@ $cfg['DisableMultiTableMaintenance'] = false;
$cfg['SendErrorReports'] = 'ask';
/**
+ * Whether Enter or Ctrl+Enter executes queries in the console.
+ *
+ * @global boolean $cfg['ConsoleEnterExecutes']
+ */
+$cfg['ConsoleEnterExecutes'] = false;
+
+/**
* Zero Configuration mode.
*
* @global boolean $cfg['ZeroConf']
@@ -3008,4 +3126,19 @@ $cfg['DefaultFunctions'] = array(
*/
$cfg['maxRowPlotLimit'] = 500;
-?>
+/**
+ * Show Git revision if applicable
+ *
+ * @global boolean $cfg['ShowGitRevision']
+ */
+$cfg['ShowGitRevision'] = true;
+
+/**
+ * MySQL minimal version required
+ *
+ * @global array $cfg['MysqlMinVersion']
+ */
+$cfg['MysqlMinVersion'] = array(
+ 'internal' => 50500,
+ 'human' => '5.5.0'
+);
diff --git a/libraries/config.values.php b/libraries/config.values.php
index 5539dbab3c..218eab6ec0 100644
--- a/libraries/config.values.php
+++ b/libraries/config.values.php
@@ -36,19 +36,19 @@ $cfg_db['OBGzip'] = array('auto', true, false);
$cfg_db['MemoryLimit'] = 'short_string';
$cfg_db['NavigationLogoLinkWindow'] = array('main', 'new');
$cfg_db['NavigationTreeDefaultTabTable'] = array(
- 'tbl_structure.php', // fields list
- 'tbl_sql.php', // SQL form
- 'tbl_select.php', // search page
- 'tbl_change.php', // insert row page
- 'sql.php' // browse page
+ 'structure' => __('Structure'), // fields list
+ 'sql' => __('SQL'), // SQL form
+ 'search' => __('Search'), // search page
+ 'insert' => __('Insert'), // insert row page
+ 'browse' => __('Browse') // browse page
);
$cfg_db['NavigationTreeDefaultTabTable2'] = array(
- '', //don't display
- 'tbl_structure.php', // fields list
- 'tbl_sql.php', // SQL form
- 'tbl_select.php', // search page
- 'tbl_change.php', // insert row page
- 'sql.php' // browse page
+ '' => '', //don't display
+ 'structure' => __('Structure'), // fields list
+ 'sql' => __('SQL'), // SQL form
+ 'search' => __('Search'), // search page
+ 'insert' => __('Insert'), // insert row page
+ 'browse' => __('Browse') // browse page
);
$cfg_db['NavigationTreeDbSeparator'] = 'short_string';
$cfg_db['NavigationTreeTableSeparator'] = 'short_string';
@@ -99,24 +99,24 @@ $cfg_db['RelationalDisplay'] = array(
'D' => __('display column')
);
$cfg_db['DefaultTabServer'] = array(
- 'index.php', // the welcome page (recommended for multiuser setups)
- 'server_databases.php', // list of databases
- 'server_status.php', // runtime information
- 'server_variables.php', // MySQL server variables
- 'server_privileges.php' // user management
+ 'welcome' => __('Welcome'), // the welcome page (recommended for multiuser setups)
+ 'databases' => __('Databases'), // list of databases
+ 'status' => __('Status'), // runtime information
+ 'variables' => __('Variables'), // MySQL server variables
+ 'privileges' => __('Privileges') // user management
);
$cfg_db['DefaultTabDatabase'] = array(
- 'db_structure.php', // tables list
- 'db_sql.php', // SQL form
- 'db_search.php', // search query
- 'db_operations.php' // operations on database
+ 'structure' => __('Structure'), // tables list
+ 'sql' => __('SQL'), // SQL form
+ 'search' => __('Search'), // search query
+ 'operations' => __('Operations') // operations on database
);
$cfg_db['DefaultTabTable'] = array(
- 'tbl_structure.php', // fields list
- 'tbl_sql.php', // SQL form
- 'tbl_select.php', // search page
- 'tbl_change.php', // insert row page
- 'sql.php' // browse page
+ 'structure' => __('Structure'), // fields list
+ 'sql' => __('SQL'), // SQL form
+ 'search' => __('Search'), // search page
+ 'insert' => __('Insert'), // insert row page
+ 'browse' => __('Browse') // browse page
);
$cfg_db['InitialSlidersState'] = array(
'open' => __('Open'),
@@ -128,6 +128,11 @@ $cfg_db['SendErrorReports'] = array(
'always' => __('Always send error reports'),
'never' => __('Never send error reports')
);
+$cfg_db['DefaultForeignKeyChecks'] = array(
+ 'default' => __('Server default'),
+ 'enable' => __('Enable'),
+ 'disable' => __('Disable')
+);
$cfg_db['Import']['format'] = array(
'csv', // CSV
'docsql', // DocSQL
@@ -140,13 +145,13 @@ $cfg_db['Import']['charset'] = array_merge(
);
$cfg_db['Import']['sql_compatibility']
= $cfg_db['Export']['sql_compatibility'] = array(
- 'NONE', 'ANSI', 'DB2', 'MAXDB', 'MYSQL323',
- 'MYSQL40', 'MSSQL', 'ORACLE',
- // removed; in MySQL 5.0.33, this produces exports that
- // can't be read by POSTGRESQL (see our bug #1596328)
- //'POSTGRESQL',
- 'TRADITIONAL'
-);
+ 'NONE', 'ANSI', 'DB2', 'MAXDB', 'MYSQL323',
+ 'MYSQL40', 'MSSQL', 'ORACLE',
+ // removed; in MySQL 5.0.33, this produces exports that
+ // can't be read by POSTGRESQL (see our bug #1596328)
+ //'POSTGRESQL',
+ 'TRADITIONAL'
+ );
$cfg_db['Import']['csv_terminated'] = 'short_string';
$cfg_db['Import']['csv_enclosed'] = 'short_string';
$cfg_db['Import']['csv_escaped'] = 'short_string';
@@ -162,7 +167,9 @@ $cfg_db['Export']['_sod_select'] = array(
$cfg_db['Export']['method'] = array(
'quick' => __('Quick - display only the minimal options to configure'),
'custom' => __('Custom - display all possible options to configure'),
- 'custom-no-form' => __('Custom - like above, but without the quick/custom choice')
+ 'custom-no-form' => __(
+ 'Custom - like above, but without the quick/custom choice'
+ ),
);
$cfg_db['Export']['format'] = array(
'codegen', 'csv', 'excel', 'htmlexcel','htmlword', 'latex', 'ods',
@@ -267,4 +274,3 @@ $cfg_db['_userValidators'] = array(
array('validateUpperBound', 'value:QueryHistoryMax')
)
);
-?>
diff --git a/libraries/config/ConfigFile.class.php b/libraries/config/ConfigFile.class.php
index c92f0dabab..1c189cf345 100644
--- a/libraries/config/ConfigFile.class.php
+++ b/libraries/config/ConfigFile.class.php
@@ -403,7 +403,7 @@ class ConfigFile
*
* @return string
*/
- function getServerDSN($server)
+ public function getServerDSN($server)
{
if (!isset($_SESSION[$this->_id]['Servers'][$server])) {
return '';
@@ -540,4 +540,3 @@ class ConfigFile
return $c;
}
}
-?>
diff --git a/libraries/config/Form.class.php b/libraries/config/Form.class.php
index 71ba6eb0d1..d31e0f234f 100644
--- a/libraries/config/Form.class.php
+++ b/libraries/config/Form.class.php
@@ -228,4 +228,3 @@ class Form
$this->readTypes();
}
}
-?>
diff --git a/libraries/config/FormDisplay.class.php b/libraries/config/FormDisplay.class.php
index 360fd7790b..77c1de0b57 100644
--- a/libraries/config/FormDisplay.class.php
+++ b/libraries/config/FormDisplay.class.php
@@ -75,7 +75,7 @@ class FormDisplay
/**
* Dictionary with user preferences keys
- * @var array
+ * @var array|null
*/
private $_userprefsKeys;
@@ -205,50 +205,23 @@ class FormDisplay
}
/**
- * Outputs HTML for forms
+ * Outputs HTML for the forms under the menu tab
*
- * @param bool $tabbed_form if true, use a form with tabs
- * @param bool $show_restore_default whether show "restore default" button
- * besides the input field
+ * @param bool $show_restore_default whether to show "restore default"
+ * button besides the input field
+ * @param array &$js_default stores JavaScript code
+ * to be displayed
+ * @param array &$js will be updated with javascript code
+ * @param bool $show_buttons whether show submit and reset button
*
- * @return void
+ * @return string $htmlOutput
*/
- public function display($tabbed_form = false, $show_restore_default = false)
- {
- static $js_lang_sent = false;
-
- $js = array();
- $js_default = array();
- $tabbed_form = $tabbed_form && (count($this->_forms) > 1);
+ private function _displayForms(
+ $show_restore_default, array &$js_default, array &$js, $show_buttons
+ ) {
+ $htmlOutput = '';
$validators = PMA_Validator::getValidators($this->_configFile);
- PMA_displayFormTop();
-
- if ($tabbed_form) {
- $tabs = array();
- foreach ($this->_forms as $form) {
- $tabs[$form->name] = PMA_lang("Form_$form->name");
- }
- PMA_displayTabsTop($tabs);
- }
-
- // validate only when we aren't displaying a "new server" form
- $is_new_server = false;
- foreach ($this->_forms as $form) {
- /* @var $form Form */
- if ($form->index === 0) {
- $is_new_server = true;
- break;
- }
- }
- if (! $is_new_server) {
- $this->_validate();
- }
-
- // user preferences
- $this->_loadUserprefsInfo();
-
- // display forms
foreach ($this->_forms as $form) {
/* @var $form Form */
$form_desc = isset($GLOBALS["strConfigForm_{$form->name}_desc"])
@@ -256,7 +229,7 @@ class FormDisplay
: '';
$form_errors = isset($this->_errors[$form->name])
? $this->_errors[$form->name] : null;
- PMA_displayFieldsetTop(
+ $htmlOutput .= PMA_displayFieldsetTop(
PMA_lang("Form_$form->name"),
$form_desc,
$form_errors,
@@ -272,7 +245,7 @@ class FormDisplay
? !isset($this->_userprefsDisallow[$path])
: null;
// display input
- $this->_displayFieldInput(
+ $htmlOutput .= $this->_displayFieldInput(
$form,
$field,
$path,
@@ -287,13 +260,73 @@ class FormDisplay
PMA_addJsValidate($translated_path, $validators[$path], $js);
}
}
- PMA_displayFieldsetBottom();
+ $htmlOutput .= PMA_displayFieldsetBottom($show_buttons);
}
+ return $htmlOutput;
+ }
+
+ /**
+ * Outputs HTML for forms
+ *
+ * @param bool $tabbed_form if true, use a form with tabs
+ * @param bool $show_restore_default whether show "restore default" button
+ * besides the input field
+ * @param bool $show_buttons whether show submit and reset button
+ * @param string $form_action action attribute for the form
+ * @param array $hidden_fields array of form hidden fields (key: field
+ * name)
+ *
+ * @return string HTML for forms
+ */
+ public function getDisplay(
+ $tabbed_form = false,
+ $show_restore_default = false,
+ $show_buttons = true,
+ $form_action = null,
+ $hidden_fields = null
+ ) {
+ static $js_lang_sent = false;
+
+ $htmlOutput = '';
+
+ $js = array();
+ $js_default = array();
+
+ $htmlOutput .= PMA_displayFormTop($form_action, 'post', $hidden_fields);
+
+ if ($tabbed_form) {
+ $tabs = array();
+ foreach ($this->_forms as $form) {
+ $tabs[$form->name] = PMA_lang("Form_$form->name");
+ }
+ $htmlOutput .= PMA_displayTabsTop($tabs);
+ }
+
+ // validate only when we aren't displaying a "new server" form
+ $is_new_server = false;
+ foreach ($this->_forms as $form) {
+ /* @var $form Form */
+ if ($form->index === 0) {
+ $is_new_server = true;
+ break;
+ }
+ }
+ if (! $is_new_server) {
+ $this->_validate();
+ }
+
+ // user preferences
+ $this->_loadUserprefsInfo();
+
+ // display forms
+ $htmlOutput .= $this->_displayForms(
+ $show_restore_default, $js_default, $js, $show_buttons
+ );
if ($tabbed_form) {
- PMA_displayTabsBottom();
+ $htmlOutput .= PMA_displayTabsBottom();
}
- PMA_displayFormBottom();
+ $htmlOutput .= PMA_displayFormBottom();
// if not already done, send strings used for validation to JavaScript
if (! $js_lang_sent) {
@@ -308,7 +341,9 @@ class FormDisplay
$js[] = "$.extend(defaultValues, {\n\t"
. implode(",\n\t", $js_default) . '})';
- PMA_displayJavascript($js);
+ $htmlOutput .= PMA_displayJavascript($js);
+
+ return $htmlOutput;
}
/**
@@ -328,7 +363,7 @@ class FormDisplay
* @param array &$js_default array which stores JavaScript code
* to be displayed
*
- * @return void
+ * @return string HTML for input field
*/
private function _displayFieldInput(
Form $form, $field, $system_path, $work_path,
@@ -358,6 +393,7 @@ class FormDisplay
$opts['errors'] = $this->_errors[$work_path];
}
+ $type = '';
switch ($form->getOptionType($field)) {
case 'string':
$type = 'text';
@@ -383,15 +419,18 @@ class FormDisplay
break;
case 'group':
// :group:end is changed to :group:end:{unique id} in Form class
+ $htmlOutput = '';
if (/*overload*/mb_substr($field, 7, 4) != 'end:') {
- PMA_displayGroupHeader(/*overload*/mb_substr($field, 7));
+ $htmlOutput .= PMA_displayGroupHeader(
+ /*overload*/mb_substr($field, 7)
+ );
} else {
PMA_displayGroupFooter();
}
- return;
+ return $htmlOutput;
case 'NULL':
trigger_error("Field $system_path has no type", E_USER_WARNING);
- return;
+ return null;
}
// detect password fields
@@ -436,7 +475,7 @@ class FormDisplay
}
$js_default[] = $js_line;
- PMA_displayInput(
+ return PMA_displayInput(
$translated_path, $name, $type, $value,
$description, $value_is_default, $opts
);
@@ -445,15 +484,17 @@ class FormDisplay
/**
* Displays errors
*
- * @return void
+ * @return string HTML for errors
*/
public function displayErrors()
{
$this->_validate();
if (count($this->_errors) == 0) {
- return;
+ return null;
}
+ $htmlOutput = '';
+
foreach ($this->_errors as $system_path => $error_list) {
if (isset($this->_systemPaths[$system_path])) {
$path = $this->_systemPaths[$system_path];
@@ -461,8 +502,10 @@ class FormDisplay
} else {
$name = $GLOBALS["strConfigForm_$system_path"];
}
- PMA_displayErrors($name, $error_list);
+ $htmlOutput .= PMA_displayErrors($name, $error_list);
}
+
+ return $htmlOutput;
}
/**
@@ -790,7 +833,9 @@ class FormDisplay
'BZipDump' => array('bzopen', 'bzcompress'));
if (!function_exists($funcs[$system_path][0])) {
$comment = sprintf(
- __('Compressed import will not work due to missing function %s.'),
+ __(
+ 'Compressed import will not work due to missing function %s.'
+ ),
$funcs[$system_path][0]
);
}
@@ -834,4 +879,3 @@ class FormDisplay
}
}
}
-?>
diff --git a/libraries/config/FormDisplay.tpl.php b/libraries/config/FormDisplay.tpl.php
index 451cd675fe..5345d5a748 100644
--- a/libraries/config/FormDisplay.tpl.php
+++ b/libraries/config/FormDisplay.tpl.php
@@ -13,7 +13,7 @@
* @param string $method 'post' or 'get'
* @param array $hidden_fields array of form hidden fields (key: field name)
*
- * @return void
+ * @return string
*/
function PMA_displayFormTop($action = null, $method = 'post', $hidden_fields = null)
{
@@ -25,18 +25,19 @@ function PMA_displayFormTop($action = null, $method = 'post', $hidden_fields = n
if ($method != 'post') {
$method = 'get';
}
- echo '<form method="' . $method . '" action="'
+ $htmlOutput = '<form method="' . $method . '" action="'
. htmlspecialchars($action) . '" class="config-form disableAjax">';
- echo '<input type="hidden" name="tab_hash" value="" />';
+ $htmlOutput .= '<input type="hidden" name="tab_hash" value="" />';
// we do validation on page refresh when browser remembers field values,
// add a field with known value which will be used for checks
if (! $has_check_page_refresh) {
$has_check_page_refresh = true;
- echo '<input type="hidden" name="check_page_refresh" '
+ $htmlOutput .= '<input type="hidden" name="check_page_refresh" '
. ' id="check_page_refresh" value="" />' . "\n";
}
- echo PMA_URL_getHiddenInputs('', '', 0, 'server') . "\n";
- echo PMA_getHiddenFields((array)$hidden_fields);
+ $htmlOutput .= PMA_URL_getHiddenInputs('', '', 0, 'server') . "\n";
+ $htmlOutput .= PMA_getHiddenFields((array)$hidden_fields);
+ return $htmlOutput;
}
/**
@@ -45,18 +46,30 @@ function PMA_displayFormTop($action = null, $method = 'post', $hidden_fields = n
*
* @param array $tabs tab names
*
- * @return void
+ * @return string
*/
function PMA_displayTabsTop($tabs)
{
- echo '<ul class="tabs">';
+ $items = array();
foreach ($tabs as $tab_id => $tab_name) {
- echo '<li><a href="#' . $tab_id . '">'
- . htmlspecialchars($tab_name) . '</a></li>';
+ $items[] = array(
+ 'content' => htmlspecialchars($tab_name),
+ 'url' => array(
+ 'href' => '#' . $tab_id,
+ ),
+ );
}
- echo '</ul>';
- echo '<br clear="right" />';
- echo '<div class="tabs_contents">';
+
+ include_once './libraries/Template.class.php';
+ $htmlOutput = PMA\Template::get('list/unordered')->render(
+ array(
+ 'class' => 'tabs',
+ 'items' => $items,
+ )
+ );
+ $htmlOutput .= '<br clear="right" />';
+ $htmlOutput .= '<div class="tabs_contents">';
+ return $htmlOutput;
}
@@ -68,7 +81,7 @@ function PMA_displayTabsTop($tabs)
* @param array $errors error messages to display
* @param array $attributes optional extra attributes of fieldset
*
- * @return void
+ * @return string
*/
function PMA_displayFieldsetTop($title = '', $description = '', $errors = null,
$attributes = array()
@@ -82,20 +95,21 @@ function PMA_displayFieldsetTop($title = '', $description = '', $errors = null,
$attr = $k . '="' . htmlspecialchars($attr) . '"';
}
- echo '<fieldset ' . implode(' ', $attributes) . '>';
- echo '<legend>' . $title . '</legend>';
+ $htmlOutput = '<fieldset ' . implode(' ', $attributes) . '>';
+ $htmlOutput .= '<legend>' . $title . '</legend>';
if (!empty($description)) {
- echo '<p>' . $description . '</p>';
+ $htmlOutput .= '<p>' . $description . '</p>';
}
// this must match with displayErrors() in scripts.js
if (is_array($errors) && count($errors) > 0) {
- echo '<dl class="errors">';
+ $htmlOutput .= '<dl class="errors">';
foreach ($errors as $error) {
- echo '<dd>' . $error . '</dd>';
+ $htmlOutput .= '<dd>' . $error . '</dd>';
}
- echo '</dl>';
+ $htmlOutput .= '</dl>';
}
- echo '<table width="100%" cellspacing="0">';
+ $htmlOutput .= '<table width="100%" cellspacing="0">';
+ return $htmlOutput;
}
/**
@@ -109,7 +123,7 @@ function PMA_displayFieldsetTop($title = '', $description = '', $errors = null,
* o userprefs_allow - whether user preferences are enabled for this field
* (null - no support, true/false - enabled/disabled)
* o userprefs_comment - (string) field comment
- * o values - key - value paris for <select> fields
+ * o values - key - value pairs for <select> fields
* o values_escaped - (boolean) tells whether values array is already escaped
* (defaults to false)
* o values_disabled - (array)list of disabled values (keys from values)
@@ -124,7 +138,7 @@ function PMA_displayFieldsetTop($title = '', $description = '', $errors = null,
* @param bool $value_is_default whether value is default
* @param array $opts see above description
*
- * @return void
+ * @return string
*/
function PMA_displayInput($path, $name, $type, $value, $description = '',
$value_is_default = true, $opts = null
@@ -198,56 +212,57 @@ function PMA_displayInput($path, $name, $type, $value, $description = '',
}
$tr_class = $tr_class ? ' class="' . $tr_class . '"' : '';
- echo '<tr' . $tr_class . '>';
- echo '<th>';
- echo '<label for="' . htmlspecialchars($path) . '">' . $name . '</label>';
+ $htmlOutput = '<tr' . $tr_class . '>';
+ $htmlOutput .= '<th>';
+ $htmlOutput .= '<label for="' . htmlspecialchars($path) . '">' . $name
+ . '</label>';
if (! empty($opts['doc'])) {
- echo '<span class="doc">';
- echo '<a href="' . $opts['doc']
+ $htmlOutput .= '<span class="doc">';
+ $htmlOutput .= '<a href="' . $opts['doc']
. '" target="documentation">' . $icons['help'] . '</a>';
- echo "\n";
- echo '</span>';
+ $htmlOutput .= "\n";
+ $htmlOutput .= '</span>';
}
if ($option_is_disabled) {
- echo '<span class="disabled-notice" title="';
- echo __(
+ $htmlOutput .= '<span class="disabled-notice" title="';
+ $htmlOutput .= __(
'This setting is disabled, it will not be applied to your configuration.'
);
- echo '">' . __('Disabled') . "</span>";
+ $htmlOutput .= '">' . __('Disabled') . "</span>";
}
if (!empty($description)) {
- echo '<small>' . $description . '</small>';
+ $htmlOutput .= '<small>' . $description . '</small>';
}
- echo '</th>';
- echo '<td>';
+ $htmlOutput .= '</th>';
+ $htmlOutput .= '<td>';
switch ($type) {
case 'text':
- echo '<input type="text" size="60" ' . $name_id . $field_class
+ $htmlOutput .= '<input type="text" size="40" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />';
break;
case 'password':
- echo '<input type="password" size="60" ' . $name_id . $field_class
+ $htmlOutput .= '<input type="password" size="40" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />';
break;
case 'short_text':
- echo '<input type="text" size="25" ' . $name_id . $field_class
+ $htmlOutput .= '<input type="text" size="25" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />';
break;
case 'number_text':
- echo '<input type="number" ' . $name_id . $field_class
+ $htmlOutput .= '<input type="number" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />';
break;
case 'checkbox':
- echo '<span' . $field_class . '><input type="checkbox" ' . $name_id
+ $htmlOutput .= '<span' . $field_class . '><input type="checkbox" ' . $name_id
. ($value ? ' checked="checked"' : '') . ' /></span>';
break;
case 'select':
- echo '<select ' . $name_id . $field_class . '>';
+ $htmlOutput .= '<select ' . $name_id . $field_class . '>';
$escape = !(isset($opts['values_escaped']) && $opts['values_escaped']);
$values_disabled = isset($opts['values_disabled'])
? array_flip($opts['values_disabled']) : array();
@@ -271,21 +286,20 @@ function PMA_displayInput($path, $name, $type, $value, $description = '',
$selected = is_bool($value)
? (int) $value === $opt_value_key
: $opt_value_key === $value;
- echo '<option value="' . $display_value . '"';
+ $htmlOutput .= '<option value="' . $display_value . '"';
if ($selected) {
- echo ' selected="selected"';
+ $htmlOutput .= ' selected="selected"';
}
if (isset($values_disabled[$opt_value_key])) {
- echo ' disabled="disabled"';
+ $htmlOutput .= ' disabled="disabled"';
}
- echo '>' . $display . '</option>';
+ $htmlOutput .= '>' . $display . '</option>';
}
- echo '</select>';
+ $htmlOutput .= '</select>';
break;
case 'list':
- echo '<textarea cols="40" rows="5" ' . $name_id . $field_class . '>'
- . htmlspecialchars(implode("\n", $value))
- . '</textarea>';
+ $htmlOutput .= '<textarea cols="40" rows="5" ' . $name_id . $field_class
+ . '>' . htmlspecialchars(implode("\n", $value)) . '</textarea>';
break;
}
if (isset($opts['comment']) && $opts['comment']) {
@@ -293,50 +307,52 @@ function PMA_displayInput($path, $name, $type, $value, $description = '',
if (isset($opts['comment_warning']) && $opts['comment_warning']) {
$class .= ' field-comment-warning';
}
- echo '<span class="' . $class . '" title="'
+ $htmlOutput .= '<span class="' . $class . '" title="'
. htmlspecialchars($opts['comment']) . '">i</span>';
}
if ($is_setup_script
&& isset($opts['userprefs_comment'])
&& $opts['userprefs_comment']
) {
- echo '<a class="userprefs-comment" title="'
+ $htmlOutput .= '<a class="userprefs-comment" title="'
. htmlspecialchars($opts['userprefs_comment']) . '">'
. $icons['tblops'] . '</a>';
}
if (isset($opts['setvalue']) && $opts['setvalue']) {
- echo '<a class="set-value" href="#'
+ $htmlOutput .= '<a class="set-value" href="#'
. htmlspecialchars("$path={$opts['setvalue']}") . '" title="'
. sprintf(__('Set value: %s'), htmlspecialchars($opts['setvalue']))
. '" style="display:none">' . $icons['edit'] . '</a>';
}
if (isset($opts['show_restore_default']) && $opts['show_restore_default']) {
- echo '<a class="restore-default" href="#' . $path . '" title="'
+ $htmlOutput .= '<a class="restore-default" href="#' . $path . '" title="'
. __('Restore default value') . '" style="display:none">'
. $icons['reload'] . '</a>';
}
// this must match with displayErrors() in scripts/config.js
if ($has_errors) {
- echo "\n <dl class=\"inline_errors\">";
+ $htmlOutput .= "\n <dl class=\"inline_errors\">";
foreach ($opts['errors'] as $error) {
- echo '<dd>' . htmlspecialchars($error) . '</dd>';
+ $htmlOutput .= '<dd>' . htmlspecialchars($error) . '</dd>';
}
- echo '</dl>';
+ $htmlOutput .= '</dl>';
}
- echo '</td>';
+ $htmlOutput .= '</td>';
if ($is_setup_script && isset($opts['userprefs_allow'])) {
- echo '<td class="userprefs-allow" title="' .
+ $htmlOutput .= '<td class="userprefs-allow" title="' .
__('Allow users to customize this value') . '">';
- echo '<input type="checkbox" name="' . $path . '-userprefs-allow" ';
+ $htmlOutput .= '<input type="checkbox" name="' . $path
+ . '-userprefs-allow" ';
if ($opts['userprefs_allow']) {
- echo 'checked="checked"';
+ $htmlOutput .= 'checked="checked"';
};
- echo '/>';
- echo '</td>';
+ $htmlOutput .= '/>';
+ $htmlOutput .= '</td>';
} else if ($is_setup_script) {
- echo '<td>&nbsp;</td>';
+ $htmlOutput .= '<td>&nbsp;</td>';
}
- echo '</tr>';
+ $htmlOutput .= '</tr>';
+ return $htmlOutput;
}
/**
@@ -344,7 +360,7 @@ function PMA_displayInput($path, $name, $type, $value, $description = '',
*
* @param string $header_text Text of header
*
- * @return void
+ * @return string|void
*/
function PMA_displayGroupHeader($header_text)
{
@@ -352,16 +368,18 @@ function PMA_displayGroupHeader($header_text)
$_FormDisplayGroup++;
if (! $header_text) {
- return;
+ return null;
}
$colspan = defined('PMA_SETUP')
? 3
: 2;
- echo '<tr class="group-header group-header-' . $_FormDisplayGroup . '">';
- echo '<th colspan="' . $colspan . '">';
- echo $header_text;
- echo '</th>';
- echo '</tr>';
+ $htmlOutput = '<tr class="group-header group-header-' . $_FormDisplayGroup
+ . '">';
+ $htmlOutput .= '<th colspan="' . $colspan . '">';
+ $htmlOutput .= $header_text;
+ $htmlOutput .= '</th>';
+ $htmlOutput .= '</tr>';
+ return $htmlOutput;
}
/**
@@ -379,55 +397,64 @@ function PMA_displayGroupFooter()
/**
* Displays bottom part of a fieldset
*
- * @return void
+ * @param bool $show_buttons whether show submit and reset button
+ *
+ * @return string
*/
-function PMA_displayFieldsetBottom()
+function PMA_displayFieldsetBottom($show_buttons = true)
{
$colspan = 2;
if (defined('PMA_SETUP')) {
$colspan++;
}
- echo '<tr>';
- echo '<td colspan="' . $colspan . '" class="lastrow">';
- echo '<input type="submit" name="submit_save" value="'
- . __('Apply') . '" class="green" />';
- echo '<input type="button" name="submit_reset" value="'
- . __('Reset') . '" />';
- echo '</td>';
- echo '</tr>';
- echo '</table>';
- echo '</fieldset>';
+ $htmlOutput = '';
+ if ($show_buttons) {
+ $htmlOutput .= '<tr>';
+ $htmlOutput .= '<td colspan="' . $colspan . '" class="lastrow">';
+ $htmlOutput .= '<input type="submit" name="submit_save" value="'
+ . __('Apply') . '" class="green" />';
+ $htmlOutput .= '<input type="button" name="submit_reset" value="'
+ . __('Reset') . '" />';
+ $htmlOutput .= '</td>';
+ $htmlOutput .= '</tr>';
+ }
+ $htmlOutput .= '</table>';
+ $htmlOutput .= '</fieldset>';
+ return $htmlOutput;
}
/**
* Displays simple bottom part of a fieldset (without submit buttons)
*
- * @return void
+ * @return string
*/
function PMA_displayFieldsetBottomSimple()
{
- echo '</table>';
- echo '</fieldset>';
+ $htmlOutput = '</table>';
+ $htmlOutput .= '</fieldset>';
+ return $htmlOutput;
}
/**
* Closes form tabs
*
- * @return void
+ * @return string
*/
function PMA_displayTabsBottom()
{
- echo "</div>\n";
+ $htmlOutput = "</div>\n";
+ return $htmlOutput;
}
/**
* Displays bottom part of the form
*
- * @return void
+ * @return string
*/
function PMA_displayFormBottom()
{
- echo "</form>\n";
+ $htmlOutput = "</form>\n";
+ return $htmlOutput;
}
/**
@@ -459,16 +486,19 @@ function PMA_addJsValidate($field_id, $validators, &$js_array)
*
* @param array $js_array lines of javascript code
*
- * @return void
+ * @return string
*/
function PMA_displayJavascript($js_array)
{
if (empty($js_array)) {
- return;
+ return null;
}
- echo '<script type="text/javascript">' . "\n";
- echo implode(";\n", $js_array) . ";\n";
- echo '</script>' . "\n";
+
+ include_once './libraries/Template.class.php';
+
+ return PMA\Template::get('javascript/display')->render(
+ array('js_array' => $js_array,)
+ );
}
/**
@@ -477,15 +507,15 @@ function PMA_displayJavascript($js_array)
* @param string $name name of item with errors
* @param array $error_list list of errors to show
*
- * @return void
+ * @return string HTML for errors
*/
function PMA_displayErrors($name, $error_list)
{
- echo '<dl>';
- echo '<dt>' . htmlspecialchars($name) . '</dt>';
+ $htmlOutput = '<dl>';
+ $htmlOutput .= '<dt>' . htmlspecialchars($name) . '</dt>';
foreach ($error_list as $error) {
- echo '<dd>' . htmlspecialchars($error) . '</dd>';
+ $htmlOutput .= '<dd>' . htmlspecialchars($error) . '</dd>';
}
- echo '</dl>';
+ $htmlOutput .= '</dl>';
+ return $htmlOutput;
}
-?>
diff --git a/libraries/config/ServerConfigChecks.class.php b/libraries/config/ServerConfigChecks.class.php
index 6deac3d8a7..5d540a2f1f 100644
--- a/libraries/config/ServerConfigChecks.class.php
+++ b/libraries/config/ServerConfigChecks.class.php
@@ -165,7 +165,10 @@ class ServerConfigChecks
'notice',
"Servers/$i/ssl",
$title,
- __('You should use SSL connections if your database server supports it.')
+ __(
+ 'You should use SSL connections if your database server '
+ . 'supports it.'
+ )
);
}
@@ -202,8 +205,8 @@ class ServerConfigChecks
'notice',
"Servers/$i/AllowNoPassword",
$title,
- __('You allow for connecting to the server without a password.') . ' '
- . PMA_lang($sSecurityInfoMsg, $i)
+ __('You allow for connecting to the server without a password.')
+ . ' ' . PMA_lang($sSecurityInfoMsg, $i)
);
}
}
@@ -340,14 +343,21 @@ class ServerConfigChecks
// check length
if (/*overload*/mb_strlen($blowfishSecret) < 8) {
// too short key
- $blowfishWarnings[] = __('Key is too short, it should have at least 8 characters.');
+ $blowfishWarnings[] = __(
+ 'Key is too short, it should have at least 8 characters.'
+ );
}
// check used characters
$hasDigits = (bool)preg_match('/\d/', $blowfishSecret);
$hasChars = (bool)preg_match('/\S/', $blowfishSecret);
$hasNonword = (bool)preg_match('/\W/', $blowfishSecret);
if (!$hasDigits || !$hasChars || !$hasNonword) {
- $blowfishWarnings[] = PMA_lang(__('Key should contain letters, numbers [em]and[/em] special characters.'));
+ $blowfishWarnings[] = PMA_lang(
+ __(
+ 'Key should contain letters, numbers [em]and[/em] '
+ . 'special characters.'
+ )
+ );
}
if (!empty($blowfishWarnings)) {
PMA_messagesSet(
@@ -368,41 +378,76 @@ class ServerConfigChecks
*/
protected static function defineMessages()
{
- $sAllowArbitraryServerWarn = __('This %soption%s should be disabled as it allows attackers to bruteforce login to any MySQL server. If you feel this is necessary, use %srestrict login to MySQL server%s or %strusted proxies list%s. However, IP-based protection with trusted proxies list may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
+ $sAllowArbitraryServerWarn = __(
+ 'This %soption%s should be disabled as it allows attackers to '
+ . 'bruteforce login to any MySQL server. If you feel this is necessary, '
+ . 'use %srestrict login to MySQL server%s or %strusted proxies list%s. '
+ . 'However, IP-based protection with trusted proxies list may not be '
+ . 'reliable if your IP belongs to an ISP where thousands of users, '
+ . 'including you, are connected to.'
+ );
$sAllowArbitraryServerWarn = sprintf(
$sAllowArbitraryServerWarn,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]',
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]',
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]'
);
- $sBlowfishSecretMsg = __('You didn\'t have blowfish secret set and have enabled [kbd]cookie[/kbd] authentication, so a key was automatically generated for you. It is used to encrypt cookies; you don\'t need to remember it.');
- $sBZipDumpWarning = __('%sBzip2 compression and decompression%s requires functions (%s) which are unavailable on this system.');
+ $sBlowfishSecretMsg = __(
+ 'You didn\'t have blowfish secret set and have enabled '
+ . '[kbd]cookie[/kbd] authentication, so a key was automatically '
+ . 'generated for you. It is used to encrypt cookies; you don\'t need to '
+ . 'remember it.'
+ );
+ $sBZipDumpWarning = __(
+ '%sBzip2 compression and decompression%s requires functions (%s) which '
+ . 'are unavailable on this system.'
+ );
$sBZipDumpWarning = sprintf(
$sBZipDumpWarning,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Import_export]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Import_export]',
'[/a]', '%s'
);
- $sDirectoryNotice = __('This value should be double checked to ensure that this directory is neither world accessible nor readable or writable by other users on your server.');
- $sForceSSLNotice = __('This %soption%s should be enabled if your web server supports it.');
+ $sDirectoryNotice = __(
+ 'This value should be double checked to ensure that this directory is '
+ . 'neither world accessible nor readable or writable by other users on '
+ . 'your server.'
+ );
+ $sForceSSLNotice = __(
+ 'This %soption%s should be enabled if your web server supports it.'
+ );
$sForceSSLNotice = sprintf(
$sForceSSLNotice,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]'
);
- $sGZipDumpWarning = __('%sGZip compression and decompression%s requires functions (%s) which are unavailable on this system.');
+ $sGZipDumpWarning = __(
+ '%sGZip compression and decompression%s requires functions (%s) which '
+ . 'are unavailable on this system.'
+ );
$sGZipDumpWarning = sprintf(
$sGZipDumpWarning,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Import_export]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Import_export]',
'[/a]',
'%s'
);
- $sLoginCookieValidityWarn = __('%sLogin cookie validity%s greater than %ssession.gc_maxlifetime%s may cause random session invalidation (currently session.gc_maxlifetime is %d).');
+ $sLoginCookieValidityWarn = __(
+ '%sLogin cookie validity%s greater than %ssession.gc_maxlifetime%s may '
+ . 'cause random session invalidation (currently session.gc_maxlifetime '
+ . 'is %d).'
+ );
$sLoginCookieValidityWarn = sprintf(
$sLoginCookieValidityWarn,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]',
'[a@' . PMA_getPHPDocLink(
'session.configuration.php#ini.session.gc-maxlifetime'
@@ -410,45 +455,78 @@ class ServerConfigChecks
'[/a]',
ini_get('session.gc_maxlifetime')
);
- $sLoginCookieValidityWarn2 = __('%sLogin cookie validity%s should be set to 1800 seconds (30 minutes) at most. Values larger than 1800 may pose a security risk such as impersonation.');
+ $sLoginCookieValidityWarn2 = __(
+ '%sLogin cookie validity%s should be set to 1800 seconds (30 minutes) '
+ . 'at most. Values larger than 1800 may pose a security risk such as '
+ . 'impersonation.'
+ );
$sLoginCookieValidityWarn2 = sprintf(
$sLoginCookieValidityWarn2,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]'
);
- $sLoginCookieValidityWarn3 = __('If using [kbd]cookie[/kbd] authentication and %sLogin cookie store%s is not 0, %sLogin cookie validity%s must be set to a value less or equal to it.');
+ $sLoginCookieValidityWarn3 = __(
+ 'If using [kbd]cookie[/kbd] authentication and %sLogin cookie store%s '
+ . 'is not 0, %sLogin cookie validity%s must be set to a value less or '
+ . 'equal to it.'
+ );
$sLoginCookieValidityWarn3 = sprintf(
$sLoginCookieValidityWarn3,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]',
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]'
);
- $sSecurityInfoMsg = __('If you feel this is necessary, use additional protection settings - %shost authentication%s settings and %strusted proxies list%s. However, IP-based protection may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
+ $sSecurityInfoMsg = __(
+ 'If you feel this is necessary, use additional protection settings - '
+ . '%shost authentication%s settings and %strusted proxies list%s. '
+ . 'However, IP-based protection may not be reliable if your IP belongs '
+ . 'to an ISP where thousands of users, including you, are connected to.'
+ );
$sSecurityInfoMsg = sprintf(
$sSecurityInfoMsg,
- '[a@?page=servers' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;mode=edit&amp;id=%1$d#tab_Server_config]',
+ '[a@?page=servers' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;mode=edit&amp;id=%1$d#tab_Server_config]',
'[/a]',
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Security]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Security]',
'[/a]'
);
- $sServerAuthConfigMsg = __('You set the [kbd]config[/kbd] authentication type and included username and password for auto-login, which is not a desirable option for live hosts. Anyone who knows or guesses your phpMyAdmin URL can directly access your phpMyAdmin panel. Set %sauthentication type%s to [kbd]cookie[/kbd] or [kbd]http[/kbd].');
+ $sServerAuthConfigMsg = __(
+ 'You set the [kbd]config[/kbd] authentication type and included '
+ . 'username and password for auto-login, which is not a desirable '
+ . 'option for live hosts. Anyone who knows or guesses your phpMyAdmin '
+ . 'URL can directly access your phpMyAdmin panel. Set %sauthentication '
+ . 'type%s to [kbd]cookie[/kbd] or [kbd]http[/kbd].'
+ );
$sServerAuthConfigMsg = sprintf(
$sServerAuthConfigMsg,
- '[a@?page=servers' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;mode=edit&amp;id=%1$d#tab_Server]',
+ '[a@?page=servers' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;mode=edit&amp;id=%1$d#tab_Server]',
'[/a]'
);
- $sZipDumpExportWarn = __('%sZip compression%s requires functions (%s) which are unavailable on this system.');
+ $sZipDumpExportWarn = __(
+ '%sZip compression%s requires functions (%s) which are unavailable on '
+ . 'this system.'
+ );
$sZipDumpExportWarn = sprintf(
$sZipDumpExportWarn,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Import_export]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Import_export]',
'[/a]',
'%s'
);
- $sZipDumpImportWarn = __('%sZip decompression%s requires functions (%s) which are unavailable on this system.');
+ $sZipDumpImportWarn = __(
+ '%sZip decompression%s requires functions (%s) which are unavailable '
+ . 'on this system.'
+ );
$sZipDumpImportWarn = sprintf(
$sZipDumpImportWarn,
- '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&') . '&amp;formset=Features#tab_Import_export]',
+ '[a@?page=form' . PMA_URL_getCommon(array(), 'html', '&')
+ . '&amp;formset=Features#tab_Import_export]',
'[/a]',
'%s'
);
diff --git a/libraries/config/Validator.class.php b/libraries/config/Validator.class.php
index 5457e22695..a6453849f7 100644
--- a/libraries/config/Validator.class.php
+++ b/libraries/config/Validator.class.php
@@ -315,8 +315,9 @@ class PMA_Validator
if ($values['Servers/1/auth_type'] == 'config'
&& empty($values['Servers/1/user'])
) {
- $result['Servers/1/user']
- = __('Empty username while using [kbd]config[/kbd] authentication method!');
+ $result['Servers/1/user'] = __(
+ 'Empty username while using [kbd]config[/kbd] authentication method!'
+ );
$error = true;
}
if ($values['Servers/1/auth_type'] == 'signon'
@@ -331,8 +332,10 @@ class PMA_Validator
if ($values['Servers/1/auth_type'] == 'signon'
&& empty($values['Servers/1/SignonURL'])
) {
- $result['Servers/1/SignonURL']
- = __('Empty signon URL while using [kbd]signon[/kbd] authentication method!');
+ $result['Servers/1/SignonURL'] = __(
+ 'Empty signon URL while using [kbd]signon[/kbd] authentication '
+ . 'method!'
+ );
$error = true;
}
@@ -380,13 +383,17 @@ class PMA_Validator
$result = array();
if ($values['Servers/1/controluser'] == '') {
- $result['Servers/1/controluser']
- = __('Empty phpMyAdmin control user while using phpMyAdmin configuration storage!');
+ $result['Servers/1/controluser'] = __(
+ 'Empty phpMyAdmin control user while using phpMyAdmin configuration '
+ . 'storage!'
+ );
$error = true;
}
if ($values['Servers/1/controlpass'] == '') {
- $result['Servers/1/controlpass']
- = __('Empty phpMyAdmin control user password while using phpMyAdmin configuration storage!');
+ $result['Servers/1/controlpass'] = __(
+ 'Empty phpMyAdmin control user password while using phpMyAdmin '
+ . 'configuration storage!'
+ );
$error = true;
}
if (! $error) {
@@ -621,4 +628,3 @@ class PMA_Validator
: sprintf(__('Value must be equal or lower than %s!'), $max_value)));
}
}
-?>
diff --git a/libraries/config/config_functions.lib.php b/libraries/config/config_functions.lib.php
index a13fe63b98..74c8cacf69 100644
--- a/libraries/config/config_functions.lib.php
+++ b/libraries/config/config_functions.lib.php
@@ -51,4 +51,3 @@ function PMA_langName($canonical_path, $type = 'name', $default = 'key')
? ($type == 'desc' ? PMA_lang($lang_key) : $GLOBALS["strConfig$lang_key"])
: ($default == 'key' ? $lang_key : $default);
}
-?>
diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php
index e77e979a71..9f5b512d59 100644
--- a/libraries/config/messages.inc.php
+++ b/libraries/config/messages.inc.php
@@ -14,13 +14,14 @@ if (!function_exists('__')) {
PMA_fatalError('Bad invocation!');
}
-$strConfigAllowArbitraryServer_desc
- = __('If enabled, user can enter any MySQL server in login form for cookie auth.');
+$strConfigAllowArbitraryServer_desc = __(
+ 'If enabled, user can enter any MySQL server in login form for cookie auth.'
+);
$strConfigAllowArbitraryServer_name = __('Allow login to any MySQL server');
$strConfigArbitraryServerRegexp_desc = __(
'Restricts the MySQL servers the user can enter when a login to an arbitrary '
- . 'MySQL server is enabled by matching the IP or hostname of the MySQL server to the given '
- . 'regular expression.'
+ . 'MySQL server is enabled by matching the IP or hostname of the MySQL server ' .
+ 'to the given regular expression.'
);
$strConfigArbitraryServerRegexp_name = __('Restrict login to MySQL server');
$strConfigAllowThirdPartyFraming_desc = __(
@@ -38,7 +39,9 @@ $strConfigblowfish_secret_desc = __(
$strConfigblowfish_secret_name = __('Blowfish secret');
$strConfigBrowseMarkerEnable_desc = __('Highlight selected rows.');
$strConfigBrowseMarkerEnable_name = __('Row marker');
-$strConfigBrowsePointerEnable_desc = __('Highlight row pointed by the mouse cursor.');
+$strConfigBrowsePointerEnable_desc = __(
+ 'Highlight row pointed by the mouse cursor.'
+);
$strConfigBrowsePointerEnable_name = __('Highlight pointer');
$strConfigBZipDump_desc = __(
'Enable [a@http://en.wikipedia.org/wiki/Bzip2]bzip2[/a] compression for'
@@ -57,6 +60,11 @@ $strConfigCodemirrorEnable_desc = __(
. 'line numbers.'
);
$strConfigCodemirrorEnable_name = __('Enable CodeMirror');
+$strConfigLintEnable_desc = __(
+ 'Find any errors in the query before executing it.'
+ . ' Requires CodeMirror to be enabled.'
+);
+$strConfigLintEnable_name = __('Enable linter');
$strConfigMinSizeForInputField_desc = __(
'Defines the minimum size for input fields generated for CHAR and VARCHAR '
. 'columns.'
@@ -67,7 +75,9 @@ $strConfigMaxSizeForInputField_desc = __(
. 'columns.'
);
$strConfigMaxSizeForInputField_name = __('Maximum size for input field');
-$strConfigCharTextareaCols_desc = __('Number of columns for CHAR/VARCHAR textareas.');
+$strConfigCharTextareaCols_desc = __(
+ 'Number of columns for CHAR/VARCHAR textareas.'
+);
$strConfigCharTextareaCols_name = __('CHAR textarea columns');
$strConfigCharTextareaRows_desc = __('Number of rows for CHAR/VARCHAR textareas.');
$strConfigCharTextareaRows_name = __('CHAR textarea rows');
@@ -83,14 +93,25 @@ $strConfigConfirm_desc = __(
. 'when you\'re about to lose data.'
);
$strConfigConfirm_name = __('Confirm DROP queries');
+$strConfigDBG_sql_desc = __(
+ 'Log SQL queries and their execution time, to be displayed in the console'
+);
$strConfigDBG_sql_name = __('Debug SQL');
$strConfigDefaultTabDatabase_desc
= __('Tab that is displayed when entering a database.');
$strConfigDefaultTabDatabase_name = __('Default database tab');
-$strConfigDefaultTabServer_desc = __('Tab that is displayed when entering a server.');
+$strConfigDefaultTabServer_desc = __(
+ 'Tab that is displayed when entering a server.'
+);
$strConfigDefaultTabServer_name = __('Default server tab');
$strConfigDefaultTabTable_desc = __('Tab that is displayed when entering a table.');
$strConfigDefaultTabTable_name = __('Default table tab');
+$strConfigEnableAutocompleteForTablesAndColumns_desc = __(
+ 'Autocomplete of the table and column names in the SQL queries.'
+);
+$strConfigEnableAutocompleteForTablesAndColumns_name = __(
+ 'Enable autocomplete for table and column names'
+);
$strConfigHideStructureActions_desc
= __('Whether the table structure actions should be hidden.');
$strConfigHideStructureActions_name = __('Hide table structure actions');
@@ -107,6 +128,9 @@ $strConfigExecTimeLimit_desc = __(
. 'limit).'
);
$strConfigExecTimeLimit_name = __('Maximum execution time');
+$strConfigExport_lock_tables_name = sprintf(
+ __('Use %s statement'), '<code>LOCK TABLES</code>'
+);
$strConfigExport_asfile_name = __('Save as file');
$strConfigExport_charset_name = __('Character set of the file');
$strConfigExport_codegen_format_name = __('Format');
@@ -136,7 +160,7 @@ $strConfigExport_latex_data_caption_name = __('Table caption');
$strConfigExport_latex_data_continued_caption_name = __('Continued table caption');
$strConfigExport_latex_data_label_name = __('Label key');
$strConfigExport_latex_mime_name = __('MIME type');
-$strConfigExport_latex_null_name = __('Replace NULL with');
+$strConfigExport_latex_null_name = __('Replace NULL with');
$strConfigExport_latex_relation_name = __('Relations');
$strConfigExport_latex_structure_caption_name = __('Table caption');
$strConfigExport_latex_structure_continued_caption_name
@@ -154,6 +178,7 @@ $strConfigExport_odt_relation_name = __('Relations');
$strConfigExport_odt_structure_or_data_name = __('Dump table');
$strConfigExport_onserver_name = __('Save on server');
$strConfigExport_onserver_overwrite_name = __('Overwrite existing file(s)');
+$strConfigExport_as_separate_files_name = __('Export as separate files');
$strConfigExport_quick_export_onserver_name = __('Save on server');
$strConfigExport_quick_export_onserver_overwrite_name
= __('Overwrite existing file(s)');
@@ -162,21 +187,27 @@ $strConfigExport_sql_auto_increment_name = __('Add AUTO_INCREMENT value');
$strConfigExport_sql_backquotes_name
= __('Enclose table and column names with backquotes');
$strConfigExport_sql_compatibility_name = __('SQL compatibility mode');
-$strConfigExport_sql_create_table_statements_name
- = __('<code>CREATE TABLE</code> options:');
$strConfigExport_sql_dates_name = __('Creation/Update/Check dates');
$strConfigExport_sql_delayed_name = __('Use delayed inserts');
$strConfigExport_sql_disable_fk_name = __('Disable foreign key checks');
$strConfigExport_sql_views_as_tables_name = __('Export views as tables');
+$strConfigExport_sql_metadata_name = __(
+ 'Export related metadata from phpMyAdmin configuration storage'
+);
+$strConfigExport_sql_create_database_name = sprintf(__('Add %s'), 'CREATE DATABASE / USE');
$strConfigExport_sql_drop_database_name = sprintf(__('Add %s'), 'DROP DATABASE');
-$strConfigExport_sql_drop_table_name
- = sprintf(__('Add %s'), 'DROP TABLE / VIEW / PROCEDURE / FUNCTION / EVENT / TRIGGER');
+$strConfigExport_sql_drop_table_name = sprintf(
+ __('Add %s'), 'DROP TABLE / VIEW / PROCEDURE / FUNCTION / EVENT / TRIGGER'
+);
$strConfigExport_sql_create_table_name = sprintf(__('Add %s'), 'CREATE TABLE');
$strConfigExport_sql_create_view_name = sprintf(__('Add %s'), 'CREATE VIEW');
$strConfigExport_sql_create_trigger_name
= sprintf(__('Add %s'), 'CREATE TRIGGER');
$strConfigExport_sql_hex_for_binary_name = __('Use hexadecimal for BINARY & BLOB');
-$strConfigExport_sql_if_not_exists_name = sprintf(__('Add %s'), 'IF NOT EXISTS');
+$strConfigExport_sql_if_not_exists_name = __(
+ 'Add IF NOT EXISTS (less efficient as indexes will be generated during'
+ . ' table creation)'
+);
$strConfigExport_sql_ignore_name = __('Use ignore inserts');
$strConfigExport_sql_include_comments_name = __('Comments');
$strConfigExport_sql_insert_syntax_name = __('Syntax to use when inserting data');
@@ -206,6 +237,10 @@ $strConfigForeignKeyDropdownOrder_name = __('Foreign key dropdown order');
$strConfigForeignKeyMaxLimit_desc
= __('A dropdown will be used if fewer items are present.');
$strConfigForeignKeyMaxLimit_name = __('Foreign key limit');
+$strConfigDefaultForeignKeyChecks_desc = __(
+ 'Default value for foreign key checks checkbox for some queries.'
+);
+$strConfigDefaultForeignKeyChecks_name = __('Foreign key checks');
$strConfigForm_Browse = __('Browse mode');
$strConfigForm_Browse_desc = __('Customize browse mode.');
$strConfigForm_CodeGen = 'CodeGen';
@@ -234,6 +269,8 @@ $strConfigForm_Navi_databases = __('Databases');
$strConfigForm_Navi_databases_desc = __('Databases display options.');
$strConfigForm_Navi_panel = __('Navigation panel');
$strConfigForm_Navi_panel_desc = __('Customize appearance of the navigation panel.');
+$strConfigForm_Navi_tree = __('Navigation tree');
+$strConfigForm_Navi_tree_desc = __('Customize the navigation tree.');
$strConfigForm_Navi_servers = __('Servers');
$strConfigForm_Navi_servers_desc = __('Servers display options.');
$strConfigForm_Navi_tables = __('Tables');
@@ -252,8 +289,6 @@ $strConfigForm_Page_titles_desc = __(
. '[doc@faq6-27]documentation[/doc] for magic strings that can be used '
. 'to get special values.'
);
-$strConfigForm_Query_window = __('Query window');
-$strConfigForm_Query_window_desc = __('Customize query window options');
$strConfigForm_Security = __('Security');
$strConfigForm_Security_desc = __(
'Please note that phpMyAdmin is just a user interface and its features do not '
@@ -305,6 +340,7 @@ $strConfigForm_DisplayRelationalSchema = __('Display relational schema');
$strConfigForm_DisplayRelationalSchema_desc = '';
$strConfigPDFDefaultPageSize_name = __('Paper size');
$strConfigPDFDefaultPageSize_desc = '';
+$strConfigForm_Databases = __('Databases');
$strConfigForm_Text_fields = __('Text fields');
$strConfigForm_Text_fields_desc = __('Customize text input fields.');
$strConfigForm_Texy = __('Texy! text');
@@ -335,7 +371,9 @@ $strConfigImport_csv_enclosed_name = __('Columns enclosed with');
$strConfigImport_csv_escaped_name = __('Columns escaped with');
$strConfigImport_csv_ignore_name = __('Do not abort on INSERT error');
$strConfigImport_csv_replace_name = __('Add ON DUPLICATE KEY UPDATE');
-$strConfigImport_csv_replace_desc = __('Update data when duplicate keys found on import');
+$strConfigImport_csv_replace_desc = __(
+ 'Update data when duplicate keys found on import'
+);
$strConfigImport_csv_terminated_name = __('Columns terminated with');
$strConfigImport_format_desc = __(
'Default format; be aware that this list depends on location (database, table) '
@@ -347,7 +385,9 @@ $strConfigImport_ldi_escaped_name = __('Columns escaped with');
$strConfigImport_ldi_ignore_name = __('Do not abort on INSERT error');
$strConfigImport_ldi_local_option_name = __('Use LOCAL keyword');
$strConfigImport_ldi_replace_name = __('Add ON DUPLICATE KEY UPDATE');
-$strConfigImport_ldi_replace_desc = __('Update data when duplicate keys found on import');
+$strConfigImport_ldi_replace_desc = __(
+ 'Update data when duplicate keys found on import'
+);
$strConfigImport_ldi_terminated_name = __('Columns terminated with');
$strConfigImport_ods_col_names_name = __('Column names in first row');
$strConfigImport_ods_empty_rows_name = __('Do not import empty rows');
@@ -417,18 +457,24 @@ $strConfigMaxRows_desc = __(
);
$strConfigMaxRows_name = __('Maximum number of rows to display');
$strConfigMaxTableList_cmt = __('Users cannot set a higher value');
-$strConfigMaxTableList_desc = __('Maximum number of tables displayed in table list.');
+$strConfigMaxTableList_desc = __(
+ 'Maximum number of tables displayed in table list.'
+);
$strConfigMaxTableList_name = __('Maximum tables');
$strConfigMemoryLimit_desc = __(
'The number of bytes a script is allowed to allocate, eg. [kbd]32M[/kbd] '
- . '([kbd]0[/kbd] for no limit).'
+ . '([kbd]-1[/kbd] for no limit and [kbd]0[/kbd] for no change).'
);
$strConfigMemoryLimit_name = __('Memory limit');
-$strConfigShowDatabasesNavigationAsTree_desc = __('In the navigation panel, replaces the database tree with a selector');
+$strConfigShowDatabasesNavigationAsTree_desc = __(
+ 'In the navigation panel, replaces the database tree with a selector'
+);
$strConfigShowDatabasesNavigationAsTree_name = __(
'Show databases navigation as tree'
);
-$strConfigNavigationLinkWithMainPanel_desc = __('Link with main panel by highlighting the current database or table.');
+$strConfigNavigationLinkWithMainPanel_desc = __(
+ 'Link with main panel by highlighting the current database or table.'
+);
$strConfigNavigationLinkWithMainPanel_name = __('Link with main panel');
$strConfigNavigationDisplayLogo_desc = __('Show logo in navigation panel.');
$strConfigNavigationDisplayLogo_name = __('Display logo');
@@ -456,7 +502,8 @@ $strConfigNavigationTreeDisplayItemFilterMinimum_name
$strConfigNavigationTreeDisplayDbFilterMinimum_name
= __('Minimum number of databases to display the database filter box');
$strConfigNavigationTreeEnableGrouping_desc = __(
- 'Group items in the navigation tree (determined by the separator defined in the Databases and Tables tabs above).'
+ 'Group items in the navigation tree (determined by the separator defined in ' .
+ 'the Databases and Tables tabs above).'
);
$strConfigNavigationTreeEnableGrouping_name = __('Group items in the tree');
$strConfigNavigationTreeDbSeparator_desc
@@ -469,10 +516,26 @@ $strConfigNavigationTreeTableLevel_name = __('Maximum table tree depth');
$strConfigNavigationTreePointerEnable_desc
= __('Highlight server under the mouse cursor.');
$strConfigNavigationTreePointerEnable_name = __('Enable highlighting');
-$strConfigNavigationTreeEnableExpansion_desc
- = __('Whether to offer the possibility of tree expansion in the navigation panel.');
+$strConfigNavigationTreeEnableExpansion_desc = __(
+ 'Whether to offer the possibility of tree expansion in the navigation panel.'
+);
$strConfigNavigationTreeEnableExpansion_name
= __('Enable navigation tree expansion');
+$strConfigNavigationTreeShowTables_name = __('Show tables in tree');
+$strConfigNavigationTreeShowTables_desc
+ = __('Whether to show tables under database in the navigation tree');
+$strConfigNavigationTreeShowViews_name = __('Show views in tree');
+$strConfigNavigationTreeShowViews_desc
+ = __('Whether to show views under database in the navigation tree');
+$strConfigNavigationTreeShowFunctions_name = __('Show functions in tree');
+$strConfigNavigationTreeShowFunctions_desc
+ = __('Whether to show functions under database in the navigation tree');
+$strConfigNavigationTreeShowProcedures_name = __('Show procedures in tree');
+$strConfigNavigationTreeShowProcedures_desc
+ = __('Whether to show procedures under database in the navigation tree');
+$strConfigNavigationTreeShowEvents_name = __('Show events in tree');
+$strConfigNavigationTreeShowEvents_desc
+ = __('Whether to show events under database in the navigation tree');
$strConfigNumRecentTables_desc
= __('Maximum number of recently used tables; set 0 to disable.');
$strConfigNumFavoriteTables_desc
@@ -481,6 +544,10 @@ $strConfigNumRecentTables_name = __('Recently used tables');
$strConfigNumFavoriteTables_name = __('Favorite tables');
$strConfigRowActionLinks_desc = __('These are Edit, Copy and Delete links.');
$strConfigRowActionLinks_name = __('Where to show the table row links');
+$strConfigRowActionLinksWithoutUnique_desc = __(
+ 'Whether to show row links even in the absence of a unique key.'
+);
+$strConfigRowActionLinksWithoutUnique_name = __('Show row links anyway');
$strConfigNaturalOrder_desc
= __('Use natural order for sorting table and database names.');
$strConfigNaturalOrder_name = __('Natural order');
@@ -536,7 +603,9 @@ $strConfigRecodingEngine_name = __('Recoding engine');
$strConfigRememberSorting_desc
= __('When browsing tables, the sorting of each table is remembered.');
$strConfigRememberSorting_name = __('Remember table\'s sorting');
-$strConfigTablePrimaryKeyOrder_desc = __('Default sort order for tables with a primary key.');
+$strConfigTablePrimaryKeyOrder_desc = __(
+ 'Default sort order for tables with a primary key.'
+);
$strConfigTablePrimaryKeyOrder_name = __('Primary key default sort order');
$strConfigRepeatCells_desc
= __('Repeat the headers every X cells, [kbd]0[/kbd] deactivates this feature.');
@@ -555,7 +624,10 @@ $strConfigServers_AllowDeny_rules_name = __('Host authorization rules');
$strConfigServers_AllowNoPassword_name = __('Allow logins without a password');
$strConfigServers_AllowRoot_name = __('Allow root login');
$strConfigServers_SessionTimeZone_name = __('Session timezone');
-$strConfigServers_SessionTimeZone_desc = __('Sets the effective timezone; possibly different than the one from your database server');
+$strConfigServers_SessionTimeZone_desc = __(
+ 'Sets the effective timezone; possibly different than the one from your ' .
+ 'database server'
+);
$strConfigServers_auth_http_realm_desc
= __('HTTP Basic Auth Realm name to display when doing HTTP Auth.');
$strConfigServers_auth_http_realm_name = __('HTTP Realm');
@@ -601,7 +673,10 @@ $strConfigServers_controlport_desc = __(
$strConfigServers_controlport_name = __('Control port');
$strConfigServers_hide_db_desc
= __('Hide databases matching regular expression (PCRE).');
-$strConfigServers_DisableIS_desc = __('More information on [a@https://sourceforge.net/p/phpmyadmin/bugs/2606/]PMA bug tracker[/a] and [a@http://bugs.mysql.com/19588]MySQL Bugs[/a]');
+$strConfigServers_DisableIS_desc = __(
+ 'More information on [a@https://sourceforge.net/p/phpmyadmin/bugs/2606/]PMA ' .
+ 'bug tracker[/a] and [a@http://bugs.mysql.com/19588]MySQL Bugs[/a]'
+);
$strConfigServers_DisableIS_name = __('Disable use of INFORMATION_SCHEMA');
$strConfigServers_hide_db_name = __('Hide databases');
$strConfigServers_history_desc = __(
@@ -623,6 +698,11 @@ $strConfigServers_savedsearches_desc = __(
'Leave blank for no QBE saved searches support, suggested: '
. '[kbd]pma__savedsearches[/kbd].'
);
+$strConfigServers_savedsearches_name = __('Export templates table');
+$strConfigServers_savedsearches_desc = __(
+ 'Leave blank for no export template support, suggested: '
+ . '[kbd]pma__export_templates[/kbd].'
+);
$strConfigServers_central_columns_name = __('Central columns table');
$strConfigServers_central_columns_desc = __(
'Leave blank for no central columns support, suggested: '
@@ -681,7 +761,9 @@ $strConfigServers_ssl_name = __('Use SSL');
$strConfigServers_table_coords_desc = __(
'Leave blank for no PDF schema support, suggested: [kbd]pma__table_coords[/kbd].'
);
-$strConfigServers_table_coords_name = __('Designer and PDF schema: table coordinates');
+$strConfigServers_table_coords_name = __(
+ 'Designer and PDF schema: table coordinates'
+);
$strConfigServers_table_info_desc = __(
'Table to describe the display columns, leave blank for no support; '
. 'suggested: [kbd]pma__table_info[/kbd].'
@@ -721,99 +803,203 @@ $strConfigServers_tracking_version_auto_create_desc = __(
);
$strConfigServers_tracking_version_auto_create_name
= __('Automatically create versions');
-$strConfigServers_userconfig_desc = __('Leave blank for no user preferences storage in database, suggested: [kbd]pma__userconfig[/kbd].');
+$strConfigServers_userconfig_desc = __(
+ 'Leave blank for no user preferences storage in database, suggested: ' .
+ '[kbd]pma__userconfig[/kbd].'
+);
$strConfigServers_userconfig_name = __('User preferences storage table');
-$strConfigServers_users_desc = __('Both this table and the user groups table are required to enable the configurable menus feature; leaving either one of them blank will disable this feature, suggested: [kbd]pma__users[/kbd].');
+$strConfigServers_users_desc = __(
+ 'Both this table and the user groups table are required to enable the ' .
+ 'configurable menus feature; leaving either one of them blank will disable
+ this feature, suggested: [kbd]pma__users[/kbd].'
+);
$strConfigServers_users_name = __('Users table');
-$strConfigServers_usergroups_desc = __('Both this table and the users table are required to enable the configurable menus feature; leaving either one of them blank will disable this feature, suggested: [kbd]pma__usergroups[/kbd].');
+$strConfigServers_usergroups_desc = __(
+ 'Both this table and the users table are required to enable the configurable ' .
+ 'menus feature; leaving either one of them blank will disable this feature, ' .
+ 'suggested: [kbd]pma__usergroups[/kbd].'
+);
$strConfigServers_usergroups_name = __('User groups table');
-$strConfigServers_navigationhiding_desc = __('Leave blank to disable the feature to hide and show navigation items, suggested: [kbd]pma__navigationhiding[/kbd].');
+$strConfigServers_navigationhiding_desc = __(
+ 'Leave blank to disable the feature to hide and show navigation items, ' .
+ 'suggested: [kbd]pma__navigationhiding[/kbd].'
+);
$strConfigServers_navigationhiding_name = __('Hidden navigation items table');
$strConfigServers_user_desc = __('Leave empty if not using config auth.');
$strConfigServers_user_name = __('User for config auth');
-$strConfigServers_verbose_desc = __('A user-friendly description of this server. Leave blank to display the hostname instead.');
+$strConfigServers_verbose_desc = __(
+ 'A user-friendly description of this server. Leave blank to display the ' .
+ 'hostname instead.'
+);
$strConfigServers_verbose_name = __('Verbose name of this server');
-$strConfigShowAll_desc = __('Whether a user should be displayed a "show all (rows)" button.');
+$strConfigShowAll_desc = __(
+ 'Whether a user should be displayed a "show all (rows)" button.'
+);
$strConfigShowAll_name = __('Allow to display all the rows');
-$strConfigShowChgPassword_desc = __('Please note that enabling this has no effect with [kbd]config[/kbd] authentication mode because the password is hard coded in the configuration file; this does not limit the ability to execute the same command directly.');
+$strConfigShowChgPassword_desc = __(
+ 'Please note that enabling this has no effect with [kbd]config[/kbd] ' .
+ 'authentication mode because the password is hard coded in the configuration ' .
+ 'file; this does not limit the ability to execute the same command directly.'
+);
$strConfigShowChgPassword_name = __('Show password change form');
$strConfigShowCreateDb_name = __('Show create database form');
-$strConfigShowDbStructureCreation_desc = __('Show or hide a column displaying the Creation timestamp for all tables.');
-$strConfigShowDbStructureCreation_name = __('Show Creation timestamp');
-$strConfigShowDbStructureLastUpdate_desc = __('Show or hide a column displaying the Last update timestamp for all tables.');
-$strConfigShowDbStructureLastUpdate_name = __('Show Last update timestamp');
-$strConfigShowDbStructureLastCheck_desc = __('Show or hide a column displaying the Last check timestamp for all tables.');
-$strConfigShowDbStructureLastCheck_name = __('Show Last check timestamp');
-$strConfigShowFieldTypesInDataEditView_desc = __('Defines whether or not type fields should be initially displayed in edit/insert mode.');
+$strConfigShowDbStructureComment_desc = __(
+ 'Show or hide a column displaying the comments for all tables.'
+);
+$strConfigShowDbStructureComment_name = __('Show table comments');
+$strConfigShowDbStructureCreation_desc = __(
+ 'Show or hide a column displaying the Creation timestamp for all tables.'
+);
+$strConfigShowDbStructureCreation_name = __('Show creation timestamp');
+$strConfigShowDbStructureLastUpdate_desc = __(
+ 'Show or hide a column displaying the Last update timestamp for all tables.'
+);
+$strConfigShowDbStructureLastUpdate_name = __('Show last update timestamp');
+$strConfigShowDbStructureLastCheck_desc = __(
+ 'Show or hide a column displaying the Last check timestamp for all tables.'
+);
+$strConfigShowDbStructureLastCheck_name = __('Show last check timestamp');
+$strConfigShowFieldTypesInDataEditView_desc = __(
+ 'Defines whether or not type fields should be initially displayed in ' .
+ 'edit/insert mode.'
+);
$strConfigShowFieldTypesInDataEditView_name = __('Show field types');
-$strConfigShowFunctionFields_desc = __('Display the function fields in edit/insert mode.');
+$strConfigShowFunctionFields_desc = __(
+ 'Display the function fields in edit/insert mode.'
+);
$strConfigShowFunctionFields_name = __('Show function fields');
$strConfigShowHint_desc = __('Whether to show hint or not.');
$strConfigShowHint_name = __('Show hint');
-$strConfigShowPhpInfo_desc = __('Shows link to [a@http://php.net/manual/function.phpinfo.php]phpinfo()[/a] output.');
+$strConfigShowPhpInfo_desc = __(
+ 'Shows link to [a@http://php.net/manual/function.phpinfo.php]phpinfo()[/a] ' .
+ 'output.'
+);
$strConfigShowPhpInfo_name = __('Show phpinfo() link');
$strConfigShowServerInfo_name = __('Show detailed MySQL server information');
-$strConfigShowSQL_desc = __('Defines whether SQL queries generated by phpMyAdmin should be displayed.');
+$strConfigShowSQL_desc = __(
+ 'Defines whether SQL queries generated by phpMyAdmin should be displayed.'
+);
$strConfigShowSQL_name = __('Show SQL queries');
-$strConfigRetainQueryBox_desc = __('Defines whether the query box should stay on-screen after its submission.');
+$strConfigRetainQueryBox_desc = __(
+ 'Defines whether the query box should stay on-screen after its submission.'
+);
$strConfigRetainQueryBox_name = __('Retain query box');
-$strConfigShowStats_desc = __('Allow to display database and table statistics (eg. space usage).');
+$strConfigShowStats_desc = __(
+ 'Allow to display database and table statistics (eg. space usage).'
+);
$strConfigShowStats_name = __('Show statistics');
-$strConfigSkipLockedTables_desc = __('Mark used tables and make it possible to show databases with locked tables.');
+$strConfigSkipLockedTables_desc = __(
+ 'Mark used tables and make it possible to show databases with locked tables.'
+);
$strConfigSkipLockedTables_name = __('Skip locked tables');
$strConfigSQLQuery_Edit_name = __('Edit');
$strConfigSQLQuery_Explain_name = __('Explain SQL');
$strConfigSQLQuery_Refresh_name = __('Refresh');
-$strConfigSQLQuery_ShowAsPHP_name = __('Create PHP Code');
-$strConfigSuhosinDisableWarning_desc = __('A warning is displayed on the main page if Suhosin is detected.');
+$strConfigSQLQuery_ShowAsPHP_name = __('Create PHP code');
+$strConfigSuhosinDisableWarning_desc = __(
+ 'Disable the default warning that is displayed on the main page if Suhosin is ' .
+ 'detected.'
+);
$strConfigSuhosinDisableWarning_name = __('Suhosin warning');
-$strConfigLoginCookieValidityDisableWarning_desc = __('Disable the default warning that is displayed on the main page if the value of the PHP setting session.gc_maxlifetime is less than the value of `LoginCookieValidity`.');
+$strConfigLoginCookieValidityDisableWarning_desc = __(
+ 'Disable the default warning that is displayed on the main page if the value ' .
+ 'of the PHP setting session.gc_maxlifetime is less than the value of ' .
+ '`LoginCookieValidity`.'
+);
$strConfigLoginCookieValidityDisableWarning_name = __(
'Login cookie validity warning'
);
-$strConfigTextareaCols_desc = __('Textarea size (columns) in edit mode, this value will be emphasized for SQL query textareas (*2) and for query window (*1.25).');
+$strConfigTextareaCols_desc = __(
+ 'Textarea size (columns) in edit mode, this value will be emphasized for SQL ' .
+ 'query textareas (*2).'
+);
$strConfigTextareaCols_name = __('Textarea columns');
-$strConfigTextareaRows_desc = __('Textarea size (rows) in edit mode, this value will be emphasized for SQL query textareas (*2) and for query window (*1.25).');
+$strConfigTextareaRows_desc = __(
+ 'Textarea size (rows) in edit mode, this value will be emphasized for SQL ' .
+ 'query textareas (*2).'
+);
$strConfigTextareaRows_name = __('Textarea rows');
-$strConfigTitleDatabase_desc = __('Title of browser window when a database is selected.');
+$strConfigTitleDatabase_desc = __(
+ 'Title of browser window when a database is selected.'
+);
$strConfigTitleDatabase_name = __('Database');
-$strConfigTitleDefault_desc = __('Title of browser window when nothing is selected.');
+$strConfigTitleDefault_desc = __(
+ 'Title of browser window when nothing is selected.'
+);
$strConfigTitleDefault_name = __('Default title');
-$strConfigTitleServer_desc = __('Title of browser window when a server is selected.');
+$strConfigTitleServer_desc = __(
+ 'Title of browser window when a server is selected.'
+);
$strConfigTitleServer_name = __('Server');
$strConfigTitleTable_desc = __('Title of browser window when a table is selected.');
$strConfigTitleTable_name = __('Table');
-$strConfigTrustedProxies_desc = __('Input proxies as [kbd]IP: trusted HTTP header[/kbd]. The following example specifies that phpMyAdmin should trust a HTTP_X_FORWARDED_FOR (X-Forwarded-For) header coming from the proxy 1.2.3.4:[br][kbd]1.2.3.4: HTTP_X_FORWARDED_FOR[/kbd].');
+$strConfigTrustedProxies_desc = __(
+ 'Input proxies as [kbd]IP: trusted HTTP header[/kbd]. The following example ' .
+ 'specifies that phpMyAdmin should trust a HTTP_X_FORWARDED_FOR ' .
+ '(X-Forwarded-For) header coming from the proxy 1.2.3.4:[br][kbd]1.2.3.4: ' .
+ 'HTTP_X_FORWARDED_FOR[/kbd].'
+);
$strConfigTrustedProxies_name = __('List of trusted proxies for IP allow/deny');
-$strConfigUploadDir_desc = __('Directory on server where you can upload files for import.');
+$strConfigUploadDir_desc = __(
+ 'Directory on server where you can upload files for import.'
+);
$strConfigUploadDir_name = __('Upload directory');
$strConfigUseDbSearch_desc = __('Allow for searching inside the entire database.');
$strConfigUseDbSearch_name = __('Use database search');
-$strConfigUserprefsDeveloperTab_desc = __('When disabled, users cannot set any of the options below, regardless of the checkbox on the right.');
+$strConfigUserprefsDeveloperTab_desc = __(
+ 'When disabled, users cannot set any of the options below, regardless of the ' .
+ 'checkbox on the right.'
+);
$strConfigUserprefsDeveloperTab_name = __('Enable the Developer tab in settings');
$strConfigVersionCheckLink = __('Check for latest version');
-$strConfigVersionCheck_desc = __('Enables check for latest version on main phpMyAdmin page.');
+$strConfigVersionCheck_desc = __(
+ 'Enables check for latest version on main phpMyAdmin page.'
+);
$strConfigVersionCheck_name = __('Version check');
-$strConfigProxyUrl_desc = __('The url of the proxy to be used when retrieving the information about the latest version of phpMyAdmin or when submitting error reports. You need this if the server where phpMyAdmin is installed does not have direct access to the internet. The format is: "hostname:portnumber".');
+$strConfigProxyUrl_desc = __(
+ 'The url of the proxy to be used when retrieving the information about the ' .
+ 'latest version of phpMyAdmin or when submitting error reports. You need this ' .
+ 'if the server where phpMyAdmin is installed does not have direct access to ' .
+ 'the internet. The format is: "hostname:portnumber".'
+);
$strConfigProxyUrl_name = __('Proxy url');
-$strConfigProxyUser_desc = __('The username for authenticating with the proxy. By default, no authentication is performed. If a username is supplied, Basic Authentication will be performed. No other types of authentication are currently supported.');
+$strConfigProxyUser_desc = __(
+ 'The username for authenticating with the proxy. By default, no ' .
+ 'authentication is performed. If a username is supplied, Basic ' .
+ 'Authentication will be performed. No other types of authentication are ' .
+ 'currently supported.'
+);
$strConfigProxyUser_name = __('Proxy username');
$strConfigProxyPass_desc = __('The password for authenticating with the proxy.');
$strConfigProxyPass_name = __('Proxy password');
-$strConfigZipDump_desc = __('Enable [a@http://en.wikipedia.org/wiki/ZIP_(file_format)]ZIP[/a] compression for import and export operations.');
+$strConfigZipDump_desc = __(
+ 'Enable [a@http://en.wikipedia.org/wiki/ZIP_(file_format)]ZIP[/a] ' .
+ 'compression for import and export operations.'
+);
$strConfigZipDump_name = __('ZIP');
-$strConfigCaptchaLoginPublicKey_desc = __('Enter your public key for your domain reCaptcha service.');
-$strConfigCaptchaLoginPublicKey_name = __('Public key for reCaptcha');
-$strConfigCaptchaLoginPrivateKey_desc = __('Enter your private key for your domain reCaptcha service.');
+$strConfigCaptchaLoginPublicKey_desc = __(
+ 'Enter your public key for your domain reCaptcha service.'
+);
+$strConfigCaptchaLoginPublicKey_name = __('Public key for reCaptcha');
+$strConfigCaptchaLoginPrivateKey_desc = __(
+ 'Enter your private key for your domain reCaptcha service.'
+);
$strConfigCaptchaLoginPrivateKey_name = __('Private key for reCaptcha');
-$strConfigSendErrorReports_desc = __('Choose the default action when sending error reports.');
+$strConfigSendErrorReports_desc = __(
+ 'Choose the default action when sending error reports.'
+);
$strConfigSendErrorReports_name = __('Send error reports');
+
+$strConfigConsoleEnterExecutes_desc = __(
+ 'Queries are executed by pressing Enter (instead of Ctrl+Enter). New lines ' .
+ 'will be inserted with Shift+Enter.'
+);
+$strConfigConsoleEnterExecutes_name = __('Enter executes queries in console');
+
$strConfigZeroConf_desc = __(
'Enable Zero Configuration mode which lets you setup phpMyAdmin '
. 'configuration storage tables automatically.'
);
$strConfigZeroConf_name = __('Enable Zero Configuration mode');
-
-?>
diff --git a/libraries/config/page_settings.class.php b/libraries/config/page_settings.class.php
new file mode 100644
index 0000000000..a010f98142
--- /dev/null
+++ b/libraries/config/page_settings.class.php
@@ -0,0 +1,230 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Page-related settings
+ *
+ * @package PhpMyAdmin
+ */
+
+require_once 'libraries/user_preferences.lib.php';
+require_once 'libraries/config/config_functions.lib.php';
+require_once 'libraries/config/messages.inc.php';
+require_once 'libraries/config/ConfigFile.class.php';
+require_once 'libraries/config/Form.class.php';
+require_once 'libraries/config/FormDisplay.class.php';
+require 'libraries/config/user_preferences.forms.php';
+require 'libraries/config/page_settings.forms.php';
+
+/**
+ * Page-related settings
+ *
+ * @package PhpMyAdmin
+ */
+class PMA_PageSettings
+{
+
+ /**
+ * Contains id of the form element
+ * @var string
+ */
+ private $_elemId = 'page_settings_modal';
+
+ /**
+ * Name of the group to show
+ * @var string
+ */
+ private $_groupName = '';
+
+ /**
+ * Contains HTML of errors
+ * @var string
+ */
+ private $_errorHTML = '';
+
+ /**
+ * Contains HTML of settings
+ * @var string
+ */
+ private $_HTML = '';
+
+ /**
+ * Constructor
+ *
+ * @param string $formGroupName The name of config form group to display
+ * @param string $elemId Id of the div containing settings
+ */
+ public function __construct($formGroupName, $elemId = null)
+ {
+ global $forms;
+ if (empty($forms[$formGroupName])) {
+ return;
+ }
+
+ if (isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
+ return;
+ }
+
+ if (!empty($elemId)) {
+ $this->_elemId = $elemId;
+ }
+ $this->_groupName = $formGroupName;
+
+ $cf = new ConfigFile($GLOBALS['PMA_Config']->base_settings);
+ PMA_userprefsPageInit($cf);
+
+ $form_display = new FormDisplay($cf);
+ foreach ($forms[$formGroupName] as $form_name => $form) {
+ // skip Developer form if no setting is available
+ if ($form_name == 'Developer'
+ && !$GLOBALS['cfg']['UserprefsDeveloperTab']
+ ) {
+ continue;
+ }
+ $form_display->registerForm($form_name, $form, 1);
+ }
+
+ // Process form
+ $error = null;
+ if (isset($_POST['submit_save'])
+ && $_POST['submit_save'] == $formGroupName
+ ) {
+ $this->_processPageSettings($form_display, $cf, $error);
+ }
+
+ // Display forms
+ $this->_HTML = $this->_getPageSettingsDisplay($form_display, $error);
+ }
+
+ /**
+ * Process response to form
+ *
+ * @param FormDisplay &$form_display Form
+ * @param ConfigFile &$cf Configuration file
+ * @param PMA_Message|null &$error Error message
+ *
+ * @return void
+ */
+ private function _processPageSettings(&$form_display, &$cf, &$error)
+ {
+ if ($form_display->process(false) && !$form_display->hasErrors()) {
+ // save settings
+ $result = PMA_saveUserprefs($cf->getConfigArray());
+ if ($result === true) {
+ // reload page
+ header('Location: ' . $_SERVER['REQUEST_URI']);
+ exit();
+ } else {
+ $error = $result;
+ }
+ }
+ }
+
+ /**
+ * Store errors in _errorHTML
+ *
+ * @param FormDisplay &$form_display Form
+ * @param PMA_Message|null &$error Error message
+ *
+ * @return void
+ */
+ private function _storeError(&$form_display, &$error)
+ {
+ $retval = '';
+ if ($error) {
+ $retval .= $error->getDisplay();
+ }
+ if ($form_display->hasErrors()) {
+ // form has errors
+ $retval .= '<div class="error config-form">'
+ . '<b>' . __(
+ 'Cannot save settings, submitted configuration form contains '
+ . 'errors!'
+ ) . '</b>'
+ . $form_display->displayErrors()
+ . '</div>';
+ }
+ $this->_errorHTML = $retval;
+ }
+
+ /**
+ * Display page-related settings
+ *
+ * @param FormDisplay &$form_display Form
+ * @param PMA_Message &$error Error message
+ *
+ * @return string
+ */
+ private function _getPageSettingsDisplay(&$form_display, &$error)
+ {
+ $response = PMA_Response::getInstance();
+
+ $retval = '';
+
+ $this->_storeError($form_display, $error);
+
+ $retval .= '<div id="' . $this->_elemId . '">';
+ $retval .= '<div class="page_settings">';
+ $retval .= $form_display->getDisplay(
+ true,
+ true,
+ false,
+ $response->getFooter()->getSelfUrl('unencoded'),
+ array(
+ 'submit_save' => $this->_groupName
+ )
+ );
+ $retval .= '</div>';
+ $retval .= '</div>';
+
+ return $retval;
+ }
+
+ /**
+ * Get HTML output
+ *
+ * @return string
+ */
+ public function getHTML()
+ {
+ return $this->_HTML;
+ }
+
+ /**
+ * Get error HTML output
+ *
+ * @return string
+ */
+ public function getErrorHTML()
+ {
+ return $this->_errorHTML;
+ }
+
+ /**
+ * Group to show for Page-related settings
+ * @param string $formGroupName The name of config form group to display
+ * @return PMA_PageSettings
+ */
+ public static function showGroup($formGroupName)
+ {
+ $object = new PMA_PageSettings($formGroupName);
+
+ $response = PMA_Response::getInstance();
+ $response->addHTML($object->getErrorHTML());
+ $response->addHTML($object->getHTML());
+
+ return $object;
+ }
+
+ /**
+ * Get HTML for navigation settings
+ * @return string
+ */
+ public static function getNaviSettings()
+ {
+ $object = new PMA_PageSettings('Navi_panel', 'pma_navigation_settings');
+
+ $response = PMA_Response::getInstance();
+ $response->addHTML($object->getErrorHTML());
+ return $object->getHTML();
+ }
+}
diff --git a/libraries/config/page_settings.forms.php b/libraries/config/page_settings.forms.php
new file mode 100644
index 0000000000..2b925df527
--- /dev/null
+++ b/libraries/config/page_settings.forms.php
@@ -0,0 +1,29 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Used for page-related settings
+ *
+ * Extends groups defined in user_preferences.forms.php
+ * specific to page-related settings
+ *
+ * See more info in user_preferences.forms.php
+ *
+ * @package PhpMyAdmin
+ */
+
+if (!is_array($forms)) {
+ $forms = array();
+}
+
+$forms['Browse'] = array();
+$forms['Browse']['Browse'] = $forms['Main_panel']['Browse'];
+
+$forms['DbStructure'] = array();
+$forms['DbStructure']['DbStructure'] = $forms['Main_panel']['DbStructure'];
+
+$forms['Edit'] = array();
+$forms['Edit']['Edit'] = $forms['Main_panel']['Edit'];
+$forms['Edit']['Text_fields'] = $forms['Features']['Text_fields'];
+
+$forms['TableStructure'] = array();
+$forms['TableStructure']['TableStructure'] = $forms['Main_panel']['TableStructure'];
diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php
index 42f23c9924..e337ab1491 100644
--- a/libraries/config/setup.forms.php
+++ b/libraries/config/setup.forms.php
@@ -83,6 +83,8 @@ $forms['Servers']['Server_pmadb'] = array('Servers' => array(1 => array(
'pdf_pages' => 'pma__pdf_pages',
'savedsearches' => 'pma__savedsearches',
'central_columns' => 'pma__central_columns',
+ 'designer_settings' => 'pma__designer_settings',
+ 'export_templates' => 'pma__export_templates',
'MaxTableUiprefs' => 100)));
$forms['Servers']['Server_tracking'] = array('Servers' => array(1 => array(
'tracking_version_auto_create',
@@ -144,6 +146,7 @@ $forms['Features']['Other_core_settings'] = array(
'UseDbSearch',
'VersionCheck',
'SendErrorReports',
+ 'ConsoleEnterExecutes',
'ProxyUrl',
'ProxyUser',
'ProxyPass',
@@ -158,7 +161,10 @@ $forms['Sql_queries']['Sql_queries'] = array(
'IgnoreMultiSubmitErrors',
'MaxCharactersInDisplayedSQL',
'RetainQueryBox',
- 'CodemirrorEnable');
+ 'CodemirrorEnable',
+ 'LintEnable',
+ 'EnableAutocompleteForTablesAndColumns',
+ 'DefaultForeignKeyChecks');
$forms['Sql_queries']['Sql_box'] = array('SQLQuery' => array(
'Edit',
'Explain',
@@ -172,13 +178,20 @@ $forms['Navi_panel']['Navi_panel'] = array(
'NavigationLogoLinkWindow',
'NavigationTreePointerEnable',
'FirstLevelNavigationItems',
- 'MaxNavigationItems',
- 'NavigationTreeEnableGrouping',
- 'NavigationTreeEnableExpansion',
'NavigationTreeDisplayItemFilterMinimum',
'NumRecentTables',
'NumFavoriteTables'
);
+$forms['Navi_panel']['Navi_tree'] = array(
+ 'MaxNavigationItems',
+ 'NavigationTreeEnableGrouping',
+ 'NavigationTreeEnableExpansion',
+ 'NavigationTreeShowTables',
+ 'NavigationTreeShowViews',
+ 'NavigationTreeShowFunctions',
+ 'NavigationTreeShowProcedures',
+ 'NavigationTreeShowEvents'
+);
$forms['Navi_panel']['Navi_servers'] = array(
'NavigationDisplayServers',
'DisplayServersList');
@@ -197,6 +210,7 @@ $forms['Main_panel']['Startup'] = array(
'ShowPhpInfo',
'ShowChgPassword');
$forms['Main_panel']['DbStructure'] = array(
+ 'ShowDbStructureComment',
'ShowDbStructureCreation',
'ShowDbStructureLastUpdate',
'ShowDbStructureLastCheck');
@@ -214,6 +228,7 @@ $forms['Main_panel']['Browse'] = array(
'RepeatCells',
'LimitChars',
'RowActionLinks',
+ 'RowActionLinksWithoutUnique',
'TablePrimaryKeyOrder',
'RememberSorting',
'RelationalDisplay');
@@ -280,6 +295,8 @@ $forms['Export']['Export_defaults'] = array('Export' => array(
'format',
'compression',
'charset',
+ 'lock_tables',
+ 'as_separate_files',
'asfile' => ':group',
'onserver',
'onserver_overwrite',
@@ -297,21 +314,20 @@ $forms['Export']['Sql'] = array('Export' => array(
'sql_use_transaction',
'sql_disable_fk',
'sql_views_as_tables',
+ 'sql_metadata',
'sql_compatibility',
- ':group:' . __('Database export options'),
- 'sql_drop_database',
- 'sql_structure_or_data',
- ':group:end',
+ 'sql_structure_or_data',
':group:' . __('Structure'),
+ 'sql_drop_database',
+ 'sql_create_database',
'sql_drop_table',
'sql_procedure_function',
- 'sql_create_table',
- 'sql_create_view',
- 'sql_create_trigger',
- 'sql_create_table_statements' => ':group',
+ 'sql_create_table' => ':group',
'sql_if_not_exists',
'sql_auto_increment',
':group:end',
+ 'sql_create_view',
+ 'sql_create_trigger',
'sql_backquotes',
':group:end',
':group:' . __('Data'),
@@ -381,4 +397,3 @@ $forms['Export']['Texy'] = array('Export' => array(
':group:' . __('Data'),
'texytext_null',
'texytext_columns'));
-?>
diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php
index 31fdf15953..07f3072052 100644
--- a/libraries/config/user_preferences.forms.php
+++ b/libraries/config/user_preferences.forms.php
@@ -26,14 +26,17 @@ $forms['Features']['General'] = array(
'NaturalOrder',
'InitialSlidersState',
'LoginCookieValidity',
- 'Servers/1/only_db', // saves to Server/only_db
- 'Servers/1/hide_db', // saves to Server/hide_db
'SkipLockedTables',
'DisableMultiTableMaintenance',
- 'MaxDbList',
'MaxTableList',
'ShowHint',
- 'SendErrorReports'
+ 'SendErrorReports',
+ 'ConsoleEnterExecutes'
+);
+$forms['Features']['Databases'] = array(
+ 'Servers/1/only_db', // saves to Server/only_db
+ 'Servers/1/hide_db', // saves to Server/hide_db
+ 'MaxDbList'
);
$forms['Features']['Text_fields'] = array(
'CharEditing',
@@ -66,7 +69,10 @@ $forms['Sql_queries']['Sql_queries'] = array(
'IgnoreMultiSubmitErrors',
'MaxCharactersInDisplayedSQL',
'RetainQueryBox',
- 'CodemirrorEnable');
+ 'CodemirrorEnable',
+ 'LintEnable',
+ 'EnableAutocompleteForTablesAndColumns',
+ 'DefaultForeignKeyChecks');
$forms['Sql_queries']['Sql_box'] = array(
'SQLQuery/Edit',
'SQLQuery/Explain',
@@ -80,13 +86,20 @@ $forms['Navi_panel']['Navi_panel'] = array(
'NavigationLogoLinkWindow',
'NavigationTreePointerEnable',
'FirstLevelNavigationItems',
- 'MaxNavigationItems',
- 'NavigationTreeEnableGrouping',
- 'NavigationTreeEnableExpansion',
'NavigationTreeDisplayItemFilterMinimum',
'NumRecentTables',
'NumFavoriteTables'
);
+$forms['Navi_panel']['Navi_tree'] = array(
+ 'MaxNavigationItems',
+ 'NavigationTreeEnableGrouping',
+ 'NavigationTreeEnableExpansion',
+ 'NavigationTreeShowTables',
+ 'NavigationTreeShowViews',
+ 'NavigationTreeShowFunctions',
+ 'NavigationTreeShowProcedures',
+ 'NavigationTreeShowEvents'
+);
$forms['Navi_panel']['Navi_databases'] = array(
'NavigationTreeDisplayDbFilterMinimum',
'NavigationTreeDbSeparator');
@@ -101,6 +114,7 @@ $forms['Main_panel']['Startup'] = array(
'ShowStats',
'ShowServerInfo');
$forms['Main_panel']['DbStructure'] = array(
+ 'ShowDbStructureComment',
'ShowDbStructureCreation',
'ShowDbStructureLastUpdate',
'ShowDbStructureLastCheck');
@@ -119,6 +133,7 @@ $forms['Main_panel']['Browse'] = array(
'RepeatCells',
'LimitChars',
'RowActionLinks',
+ 'RowActionLinksWithoutUnique',
'TablePrimaryKeyOrder',
'RememberSorting',
'RelationalDisplay');
@@ -141,7 +156,8 @@ $forms['Import']['Import_defaults'] = array(
'Import/format',
'Import/charset',
'Import/allow_interrupt',
- 'Import/skip_queries');
+ 'Import/skip_queries'
+);
$forms['Import']['Sql'] = array(
'Import/sql_compatibility',
'Import/sql_no_auto_value_on_zero',
@@ -178,6 +194,8 @@ $forms['Export']['Export_defaults'] = array(
'Export/format',
'Export/compression',
'Export/charset',
+ 'Export/lock_tables',
+ 'Export/as_separate_files',
'Export/asfile' => ':group',
'Export/onserver',
'Export/onserver_overwrite',
@@ -194,21 +212,20 @@ $forms['Export']['Sql'] = array(
'Export/sql_use_transaction',
'Export/sql_disable_fk',
'Export/sql_views_as_tables',
+ 'Export/sql_metadata',
'Export/sql_compatibility',
- ':group:' . __('Database export options'),
- 'Export/sql_drop_database',
- 'Export/sql_structure_or_data',
- ':group:end',
+ 'Export/sql_structure_or_data',
':group:' . __('Structure'),
+ 'Export/sql_drop_database',
+ 'Export/sql_create_database',
'Export/sql_drop_table',
- 'Export/sql_create_table',
- 'Export/sql_create_view',
- 'Export/sql_procedure_function',
- 'Export/sql_create_trigger',
- 'Export/sql_create_table_statements' => ':group',
+ 'Export/sql_create_table' => ':group',
'Export/sql_if_not_exists',
'Export/sql_auto_increment',
':group:end',
+ 'Export/sql_create_view',
+ 'Export/sql_procedure_function',
+ 'Export/sql_create_trigger',
'Export/sql_backquotes',
':group:end',
':group:' . __('Data'),
@@ -278,4 +295,3 @@ $forms['Export']['Texy'] = array(
':group:' . __('Data'),
'Export/texytext_null',
'Export/texytext_columns');
-?>
diff --git a/libraries/controllers/Controller.class.php b/libraries/controllers/Controller.class.php
new file mode 100644
index 0000000000..d57563de23
--- /dev/null
+++ b/libraries/controllers/Controller.class.php
@@ -0,0 +1,55 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\TableController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers;
+
+use PMA\DI\Container;
+use PMA_DatabaseInterface;
+use PMA_Response;
+
+if (!defined('PHPMYADMIN')) {
+ exit;
+}
+
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/database_interface.inc.php';
+
+/**
+ * Base class for all of controller
+ *
+ * @package PhpMyAdmin
+ */
+abstract class Controller
+{
+
+ /**
+ * @var PMA_Response
+ */
+ protected $response;
+
+ /**
+ * @var PMA_DatabaseInterface
+ */
+ protected $dbi;
+
+ /**
+ * @var Container
+ */
+ protected $container;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $container = Container::getDefaultContainer();
+ $this->container = $container;
+ $this->dbi = $this->container->get('dbi');
+ $this->response = $this->container->get('response');
+ }
+}
diff --git a/libraries/controllers/DatabaseController.class.php b/libraries/controllers/DatabaseController.class.php
new file mode 100644
index 0000000000..6a13d93087
--- /dev/null
+++ b/libraries/controllers/DatabaseController.class.php
@@ -0,0 +1,39 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DatabaseController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers;
+
+use PMA\DI\Container;
+
+if (!defined('PHPMYADMIN')) {
+ exit;
+}
+
+require_once 'libraries/controllers/Controller.class.php';
+
+/**
+ * Handles database related logic
+ *
+ * @package PhpMyAdmin
+ */
+abstract class DatabaseController extends Controller
+{
+ /**
+ * @var string $db
+ */
+ protected $db;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->db = $this->container->get('db');
+ }
+}
diff --git a/libraries/controllers/DatabaseStructureController.class.php b/libraries/controllers/DatabaseStructureController.class.php
new file mode 100644
index 0000000000..76d4710151
--- /dev/null
+++ b/libraries/controllers/DatabaseStructureController.class.php
@@ -0,0 +1,1062 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+
+/**
+ * Holds the PMA\DatabaseStructureController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers;
+
+use PMA\Template;
+use PMA_RecentFavoriteTable;
+use PMA_Tracker;
+use PMA_Message;
+use PMA_PageSettings;
+use PMA_Util;
+
+require_once 'libraries/mysql_charsets.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+require_once 'libraries/display_create_table.lib.php';
+require_once 'libraries/Template.class.php';
+require_once 'libraries/controllers/DatabaseController.class.php';
+
+/**
+ * Handles database structure logic
+ *
+ * @package PhpMyAdmin
+ */
+class DatabaseStructureController extends DatabaseController
+{
+ /**
+ * @var string The URL query string
+ */
+ protected $_url_query;
+ /**
+ * @var int Number of tables
+ */
+ protected $_num_tables;
+ /**
+ * @var int Current position in the list
+ */
+ protected $_pos;
+ /**
+ * @var bool DB is information_schema
+ */
+ protected $_db_is_system_schema;
+ /**
+ * @var int Number of tables
+ */
+ protected $_total_num_tables;
+ /**
+ * @var array Tables in the database
+ */
+ protected $_tables;
+ /**
+ * @var bool whether stats show or not
+ */
+ protected $_is_show_stats;
+
+ /**
+ * DatabaseStructureController constructor
+ *
+ * @param string $url_query URL query
+ * @param int $num_tables Number of tables
+ * @param int $pos Current position in the list
+ * @param bool $db_is_system_schema DB is information_schema
+ * @param int $total_num_tables Number of tables
+ * @param array $tables Tables in the DB
+ * @param bool $is_show_stats Whether stats show or not
+ */
+ public function __construct(
+ $url_query, $num_tables, $pos, $db_is_system_schema,
+ $total_num_tables, $tables, $is_show_stats
+ ) {
+ parent::__construct();
+
+ $this->_url_query = $url_query;
+ $this->_num_tables = $num_tables;
+ $this->_pos = $pos;
+ $this->_db_is_system_schema = $db_is_system_schema;
+ $this->_total_num_tables = $total_num_tables;
+ $this->_tables = $tables;
+ $this->_is_show_stats = $is_show_stats;
+ }
+
+ /**
+ * Index action
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ // Add/Remove favorite tables using Ajax request.
+ if ($GLOBALS['is_ajax_request'] && !empty($_REQUEST['favorite_table'])) {
+ $this->addRemoveFavoriteTablesAction();
+ return;
+ }
+
+ $this->response->getHeader()->getScripts()->addFiles(
+ array(
+ 'db_structure.js',
+ 'tbl_change.js',
+ 'jquery/jquery-ui-timepicker-addon.js'
+ )
+ );
+
+ // Drops/deletes/etc. multiple tables if required
+ if ((!empty($_POST['submit_mult']) && isset($_POST['selected_tbl']))
+ || isset($_POST['mult_btn'])
+ ) {
+ $action = 'db_structure.php';
+ $err_url = 'db_structure.php' . PMA_URL_getCommon(
+ array('db' => $this->db)
+ );
+
+ // see bug #2794840; in this case, code path is:
+ // db_structure.php -> libraries/mult_submits.inc.php -> sql.php
+ // -> db_structure.php and if we got an error on the multi submit,
+ // we must display it here and not call again mult_submits.inc.php
+ if (! isset($_POST['error']) || false === $_POST['error']) {
+ include 'libraries/mult_submits.inc.php';
+ }
+ if (empty($_POST['message'])) {
+ $_POST['message'] = PMA_Message::success();
+ }
+ }
+
+ $this->_url_query .= '&amp;goto=db_structure.php';
+
+ // Gets the database structure
+ $sub_part = '_structure';
+
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($GLOBALS['db'], isset($sub_part) ? $sub_part : '');
+
+ $this->_tables = $tables;
+ // updating $tables seems enough for #11376, but updating other
+ // variables too in case they may cause some other problem.
+ $this->_num_tables = $num_tables;
+ $this->_pos = $pos;
+ $this->_db_is_system_schema = $db_is_system_schema;
+ $this->_total_num_tables = $total_num_tables;
+ $this->_is_show_stats = $is_show_stats;
+
+ // If there is an Ajax request for real row count of a table.
+ if ($GLOBALS['is_ajax_request']
+ && isset($_REQUEST['real_row_count'])
+ && $_REQUEST['real_row_count'] == true
+ ) {
+ $this->handleRealRowCountRequestAction();
+ return;
+ }
+
+ if (!PMA_DRIZZLE) {
+ include_once 'libraries/replication.inc.php';
+ } else {
+ $GLOBALS['replication_info']['slave']['status'] = false;
+ }
+
+ PMA_PageSettings::showGroup('DbStructure');
+
+ $db_collation = PMA_getDbCollation($this->db);
+
+ $titles = PMA_Util::buildActionTitles();
+
+ // 1. No tables
+
+ if ($this->_num_tables == 0) {
+ $this->response->addHTML(
+ PMA_message::notice(__('No tables found in database.'))
+ );
+ if (empty($db_is_system_schema)) {
+ $this->response->addHTML(PMA_getHtmlForCreateTable($this->db));
+ }
+ return;
+ }
+
+ // else
+ // 2. Shows table information
+
+ /**
+ * Displays the tables list
+ */
+ $this->response->addHTML('<div id="tableslistcontainer">');
+ $_url_params = array(
+ 'pos' => $this->_pos,
+ 'db' => $this->db);
+
+ // Add the sort options if they exists
+ if (isset($_REQUEST['sort'])) {
+ $_url_params['sort'] = $_REQUEST['sort'];
+ }
+
+ if (isset($_REQUEST['sort_order'])) {
+ $_url_params['sort_order'] = $_REQUEST['sort_order'];
+ }
+
+ $this->response->addHTML(
+ PMA_Util::getListNavigator(
+ $this->_total_num_tables, $this->_pos, $_url_params,
+ 'db_structure.php', 'frame_content', $GLOBALS['cfg']['MaxTableList']
+ )
+ );
+
+ // table form
+ $this->response->addHTML(
+ Template::get('database/structure/table_header')
+ ->render(
+ array(
+ 'db' => $this->db,
+ 'db_is_system_schema' => $this->_db_is_system_schema,
+ 'replication' => $GLOBALS['replication_info']['slave']['status'],
+ )
+ )
+ );
+
+ $i = $sum_entries = 0;
+ $overhead_check = '';
+ $create_time_all = '';
+ $update_time_all = '';
+ $check_time_all = '';
+ $num_columns = $GLOBALS['cfg']['PropertiesNumColumns'] > 1
+ ? ceil($this->_num_tables / $GLOBALS['cfg']['PropertiesNumColumns']) + 1
+ : 0;
+ $row_count = 0;
+ $sum_size = (double) 0;
+ $overhead_size = (double) 0;
+
+ $hidden_fields = array();
+ $odd_row = true;
+ $overall_approx_rows = false;
+ // Instance of PMA_RecentFavoriteTable class.
+ $fav_instance = PMA_RecentFavoriteTable::getInstance('favorite');
+ foreach ($this->_tables as $keyname => $current_table) {
+ // Get valid statistics whatever is the table type
+
+ $drop_query = '';
+ $drop_message = '';
+ $already_favorite = false;
+ $overhead = '';
+
+ $table_is_view = false;
+ $table_encoded = urlencode($current_table['TABLE_NAME']);
+ // Sets parameters for links
+ $tbl_url_query = $this->_url_query . '&amp;table=' . $table_encoded;
+ // do not list the previous table's size info for a view
+
+ list($current_table, $formatted_size, $unit, $formatted_overhead,
+ $overhead_unit, $overhead_size, $table_is_view, $sum_size)
+ = $this->getStuffForEngineTypeTable(
+ $current_table, $sum_size, $overhead_size
+ );
+
+ $curTable = $this->dbi
+ ->getTable($this->db, $current_table['TABLE_NAME']);
+ if (!$curTable->isMerge()) {
+ $sum_entries += $current_table['TABLE_ROWS'];
+ }
+
+ if (isset($current_table['Collation'])) {
+ $collation = '<dfn title="'
+ . PMA_getCollationDescr($current_table['Collation']) . '">'
+ . $current_table['Collation'] . '</dfn>';
+ } else {
+ $collation = '---';
+ }
+
+ if ($this->_is_show_stats) {
+ if ($formatted_overhead != '') {
+ $overhead = '<a href="tbl_structure.php'
+ . $tbl_url_query . '#showusage">'
+ . '<span>' . $formatted_overhead . '</span>&nbsp;'
+ . '<span class="unit">' . $overhead_unit . '</span>'
+ . '</a>' . "\n";
+ $overhead_check .=
+ "markAllRows('row_tbl_" . ($i + 1) . "');";
+ } else {
+ $overhead = '-';
+ }
+ } // end if
+
+ $showtable = $this->dbi->getTable(
+ $this->db, $current_table['TABLE_NAME']
+ )->getStatusInfo(null, true);
+
+ if ($GLOBALS['cfg']['ShowDbStructureCreation']) {
+ $create_time = isset($showtable['Create_time'])
+ ? $showtable['Create_time'] : '';
+ if ($create_time
+ && (!$create_time_all
+ || $create_time < $create_time_all)
+ ) {
+ $create_time_all = $create_time;
+ }
+ }
+
+ if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) {
+ // $showtable might already be set from ShowDbStructureCreation,
+ // see above
+ $update_time = isset($showtable['Update_time'])
+ ? $showtable['Update_time'] : '';
+ if ($update_time
+ && (!$update_time_all
+ || $update_time < $update_time_all)
+ ) {
+ $update_time_all = $update_time;
+ }
+ }
+
+ if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) {
+ // $showtable might already be set from ShowDbStructureCreation,
+ // see above
+ $check_time = isset($showtable['Check_time'])
+ ? $showtable['Check_time'] : '';
+ if ($check_time
+ && (!$check_time_all
+ || $check_time < $check_time_all)
+ ) {
+ $check_time_all = $check_time;
+ }
+ }
+
+ $alias = htmlspecialchars(
+ (!empty($tooltip_aliasname)
+ && isset($tooltip_aliasname[$current_table['TABLE_NAME']]))
+ ? $tooltip_aliasname[$current_table['TABLE_NAME']]
+ : $current_table['TABLE_NAME']
+ );
+ $alias = str_replace(' ', '&nbsp;', $alias);
+
+ $truename = htmlspecialchars(
+ (!empty($tooltip_truename)
+ && isset($tooltip_truename[$current_table['TABLE_NAME']]))
+ ? $tooltip_truename[$current_table['TABLE_NAME']]
+ : $current_table['TABLE_NAME']
+ );
+ $truename = str_replace(' ', '&nbsp;', $truename);
+
+ $i++;
+
+ $row_count++;
+ if ($table_is_view) {
+ $hidden_fields[] = '<input type="hidden" name="views[]" value="'
+ . htmlspecialchars($current_table['TABLE_NAME']) . '" />';
+ }
+
+ /*
+ * Always activate links for Browse, Search and Empty, even if
+ * the icons are greyed, because
+ * 1. for views, we don't know the number of rows at this point
+ * 2. for tables, another source could have populated them since the
+ * page was generated
+ *
+ * I could have used the PHP ternary conditional operator but I find
+ * the code easier to read without this operator.
+ */
+ $may_have_rows = $current_table['TABLE_ROWS'] > 0 || $table_is_view;
+
+ $browse_table = Template::get('database/structure/browse_table')
+ ->render(
+ array(
+ 'tbl_url_query' => $tbl_url_query,
+ 'title' => $may_have_rows ? $titles['Browse']
+ : $titles['NoBrowse'],
+ )
+ );
+
+ $search_table = Template::get('database/structure/search_table')
+ ->render(
+ array(
+ 'tbl_url_query' => $tbl_url_query,
+ 'title' => $may_have_rows ? $titles['Search']
+ : $titles['NoSearch'],
+ )
+ );
+
+ $browse_table_label = Template::get(
+ 'database/structure/browse_table_label'
+ )
+ ->render(
+ array(
+ 'tbl_url_query' => $tbl_url_query,
+ 'title' => htmlspecialchars(
+ $current_table['TABLE_COMMENT']
+ ),
+ 'truename' => $truename,
+ )
+ );
+
+ $empty_table = '';
+ if (!$this->_db_is_system_schema) {
+ $empty_table = '&nbsp;';
+ if (!$table_is_view) {
+ $empty_table = Template::get('database/structure/empty_table')
+ ->render(
+ array(
+ 'tbl_url_query' => $tbl_url_query,
+ 'sql_query' => urlencode(
+ 'TRUNCATE ' . PMA_Util::backquote(
+ $current_table['TABLE_NAME']
+ )
+ ),
+ 'message_to_show' => urlencode(
+ sprintf(
+ __('Table %s has been emptied.'),
+ htmlspecialchars(
+ $current_table['TABLE_NAME']
+ )
+ )
+ ),
+ 'title' => $may_have_rows ? $titles['Empty']
+ : $titles['NoEmpty'],
+ )
+ );
+ }
+ $drop_query = sprintf(
+ 'DROP %s %s',
+ ($table_is_view || $current_table['ENGINE'] == null) ? 'VIEW'
+ : 'TABLE',
+ PMA_Util::backquote(
+ $current_table['TABLE_NAME']
+ )
+ );
+ $drop_message = sprintf(
+ (($table_is_view || $current_table['ENGINE'] == null)
+ ? __('View %s has been dropped.')
+ : __('Table %s has been dropped.')),
+ str_replace(
+ ' ', '&nbsp;',
+ htmlspecialchars($current_table['TABLE_NAME'])
+ )
+ );
+ }
+
+ $tracking_icon = '';
+ if (PMA_Tracker::isActive()) {
+ $is_tracked = PMA_Tracker::isTracked($GLOBALS["db"], $truename);
+ if ($is_tracked
+ || PMA_Tracker::getVersion($GLOBALS["db"], $truename) > 0
+ ) {
+ $tracking_icon = Template::get(
+ 'database/structure/tracking_icon'
+ )
+ ->render(
+ array(
+ 'url_query' => $this->_url_query,
+ 'truename' => $truename,
+ 'is_tracked' => $is_tracked,
+ )
+ );
+ }
+ }
+
+ if ($num_columns > 0
+ && $this->_num_tables > $num_columns
+ && ($row_count % $num_columns) == 0
+ ) {
+ $row_count = 1;
+ $odd_row = true;
+
+ $this->response->addHTML(
+ '</tr></tbody></table>'
+ );
+
+ $this->response->addHTML(
+ Template::get('database/structure/table_header')->render(
+ array(
+ 'db_is_system_schema' => false,
+ 'replication' => $GLOBALS['replication_info']['slave']['status']
+ )
+ )
+ );
+ }
+
+ $do = $ignored = false;
+ if ($GLOBALS['replication_info']['slave']['status']) {
+
+ $nbServSlaveDoDb = count(
+ $GLOBALS['replication_info']['slave']['Do_DB']
+ );
+ $nbServSlaveIgnoreDb = count(
+ $GLOBALS['replication_info']['slave']['Ignore_DB']
+ );
+ $searchDoDBInTruename = array_search(
+ $truename, $GLOBALS['replication_info']['slave']['Do_DB']
+ );
+ $searchDoDBInDB = array_search(
+ $this->db, $GLOBALS['replication_info']['slave']['Do_DB']
+ );
+
+ $do = strlen($searchDoDBInTruename) > 0
+ || strlen($searchDoDBInDB) > 0
+ || ($nbServSlaveDoDb == 1 && $nbServSlaveIgnoreDb == 1)
+ || $this->hasTable(
+ $GLOBALS['replication_info']['slave']['Wild_Do_Table'],
+ $truename
+ );
+
+ $searchDb = array_search(
+ $this->db,
+ $GLOBALS['replication_info']['slave']['Ignore_DB']
+ );
+ $searchTable = array_search(
+ $truename,
+ $GLOBALS['replication_info']['slave']['Ignore_Table']
+ );
+ $ignored = strlen($searchTable) > 0
+ || strlen($searchDb) > 0
+ || $this->hasTable(
+ $GLOBALS['replication_info']['slave']['Wild_Ignore_Table'],
+ $truename
+ );
+ }
+
+ // Handle favorite table list. ----START----
+ $already_favorite = $this->checkFavoriteTable(
+ $current_table['TABLE_NAME']
+ );
+
+ if (isset($_REQUEST['remove_favorite'])) {
+ if ($already_favorite) {
+ // If already in favorite list, remove it.
+ $favorite_table = $_REQUEST['favorite_table'];
+ $fav_instance->remove($this->db, $favorite_table);
+ }
+ }
+
+ if (isset($_REQUEST['add_favorite'])) {
+ if (!$already_favorite) {
+ // Otherwise add to favorite list.
+ $favorite_table = $_REQUEST['favorite_table'];
+ $fav_instance->add($this->db, $favorite_table);
+ }
+ } // Handle favorite table list. ----ENDS----
+
+ $show_superscript = '';
+
+ // there is a null value in the ENGINE
+ // - when the table needs to be repaired, or
+ // - when it's a view
+ // so ensure that we'll display "in use" below for a table
+ // that needs to be repaired
+ $approx_rows = false;
+ if (isset($current_table['TABLE_ROWS'])
+ && ($current_table['ENGINE'] != null || $table_is_view)
+ ) {
+ // InnoDB table: we did not get an accurate row count
+ $approx_rows = !$table_is_view
+ && $current_table['ENGINE'] == 'InnoDB'
+ && !$current_table['COUNTED'];
+
+ // Drizzle views use FunctionEngine, and the only place where
+ // they are available are I_S and D_D schemas, where we do exact
+ // counting
+ if ($table_is_view
+ && $current_table['TABLE_ROWS'] >= $GLOBALS['cfg']['MaxExactCountViews']
+ && $current_table['ENGINE'] != 'FunctionEngine'
+ ) {
+ $approx_rows = true;
+ $show_superscript = PMA_Util::showHint(
+ PMA_sanitize(
+ sprintf(
+ __(
+ 'This view has at least this number of '
+ . 'rows. Please refer to %sdocumentation%s.'
+ ),
+ '[doc@cfg_MaxExactCountViews]', '[/doc]'
+ )
+ )
+ );
+ }
+ }
+
+ $this->response->addHTML(
+ Template::get('database/structure/structure_table_row')
+ ->render(
+ array(
+ 'db' => $this->db,
+ 'curr' => $i,
+ 'odd_row' => $odd_row,
+ 'table_is_view' => $table_is_view,
+ 'current_table' => $current_table,
+ 'browse_table_label' => $browse_table_label,
+ 'tracking_icon' => $tracking_icon,
+ 'server_slave_status' => $GLOBALS['replication_info']['slave']['status'],
+ 'browse_table' => $browse_table,
+ 'tbl_url_query' => $tbl_url_query,
+ 'search_table' => $search_table,
+ 'db_is_system_schema' => $this->_db_is_system_schema,
+ 'titles' => $titles,
+ 'empty_table' => $empty_table,
+ 'drop_query' => $drop_query,
+ 'drop_message' => $drop_message,
+ 'collation' => $collation,
+ 'formatted_size' => $formatted_size,
+ 'unit' => $unit,
+ 'overhead' => $overhead,
+ 'create_time' => isset($create_time)
+ ? $create_time : '',
+ 'update_time' => isset($update_time)
+ ? $update_time : '',
+ 'check_time' => isset($check_time)
+ ? $check_time : '',
+ 'is_show_stats' => $this->_is_show_stats,
+ 'ignored' => $ignored,
+ 'do' => $do,
+ 'colspan_for_structure' => $GLOBALS['colspan_for_structure'],
+ 'approx_rows' => $approx_rows,
+ 'show_superscript' => $show_superscript,
+ 'already_favorite' => $this->checkFavoriteTable(
+ $current_table['TABLE_NAME']
+ ),
+ )
+ )
+ );
+
+ $odd_row = ! $odd_row;
+ $overall_approx_rows = $overall_approx_rows || $approx_rows;
+ } // end foreach
+
+ // Show Summary
+ $this->response->addHTML('</tbody>');
+ $this->response->addHTML(
+ Template::get('database/structure/body_for_table_summary')->render(
+ array(
+ 'num_tables' => $this->_num_tables,
+ 'server_slave_status' => $GLOBALS['replication_info']['slave']['status'],
+ 'db_is_system_schema' => $this->_db_is_system_schema,
+ 'sum_entries' => $sum_entries,
+ 'db_collation' => $db_collation,
+ 'is_show_stats' => $this->_is_show_stats,
+ 'sum_size' => $sum_size,
+ 'overhead_size' => $overhead_size,
+ 'create_time_all' => $create_time_all,
+ 'update_time_all' => $update_time_all,
+ 'check_time_all' => $check_time_all,
+ 'approx_rows' => $overall_approx_rows
+ )
+ )
+ );
+ $this->response->addHTML('</table>');
+ //check all
+ $this->response->addHTML(
+ Template::get('database/structure/check_all_tables')->render(
+ array(
+ 'pmaThemeImage' => $GLOBALS['pmaThemeImage'],
+ 'text_dir' => $GLOBALS['text_dir'],
+ 'overhead_check' => $overhead_check,
+ 'db_is_system_schema' => $this->_db_is_system_schema,
+ 'hidden_fields' => $hidden_fields
+ )
+ )
+ );
+ $this->response->addHTML('</form>'); //end of form
+
+ // display again the table list navigator
+ $this->response->addHTML(
+ PMA_Util::getListNavigator(
+ $this->_total_num_tables, $this->_pos, $_url_params,
+ 'db_structure.php', 'frame_content',
+ $GLOBALS['cfg']['MaxTableList']
+ )
+ );
+
+ $this->response->addHTML('</div><hr />');
+
+ /**
+ * Work on the database
+ */
+ /* DATABASE WORK */
+ /* Printable view of a table */
+ $this->response->addHTML(
+ Template::get('database/structure/print_view_data_dictionary_link')
+ ->render(array('url_query' => $this->_url_query))
+ );
+
+ if (empty($db_is_system_schema)) {
+ $this->response->addHTML(PMA_getHtmlForCreateTable($this->db));
+ }
+ }
+
+ /**
+ * Add or remove favorite tables
+ *
+ * @return void
+ */
+ public function addRemoveFavoriteTablesAction()
+ {
+ $fav_instance = PMA_RecentFavoriteTable::getInstance('favorite');
+ if (isset($_REQUEST['favorite_tables'])) {
+ $favorite_tables = json_decode($_REQUEST['favorite_tables'], true);
+ } else {
+ $favorite_tables = array();
+ }
+ // Required to keep each user's preferences separate.
+ $user = sha1($GLOBALS['cfg']['Server']['user']);
+
+ // Request for Synchronization of favorite tables.
+ if (isset($_REQUEST['sync_favorite_tables'])) {
+ $this->synchronizeFavoriteTables($fav_instance, $user, $favorite_tables);
+ return;
+ }
+ $changes = true;
+ $titles = PMA_Util::buildActionTitles();
+ $favorite_table = $_REQUEST['favorite_table'];
+ $already_favorite = $this->checkFavoriteTable($favorite_table);
+
+ if (isset($_REQUEST['remove_favorite'])) {
+ if ($already_favorite) {
+ // If already in favorite list, remove it.
+ $fav_instance->remove($this->db, $favorite_table);
+ }
+ } elseif (isset($_REQUEST['add_favorite'])) {
+ if (!$already_favorite) {
+ $nbTables = count($fav_instance->getTables());
+ if ($nbTables == $GLOBALS['cfg']['NumFavoriteTables']) {
+ $changes = false;
+ } else {
+ // Otherwise add to favorite list.
+ $fav_instance->add($this->db, $favorite_table);
+ }
+ }
+ }
+
+ $favorite_tables[$user] = $fav_instance->getTables();
+ $this->response->addJSON('changes', $changes);
+ if (!$changes) {
+ $this->response->addJSON(
+ 'message',
+ Template::get('components/error_message')
+ ->render(
+ array(
+ 'msg' => __("Favorite List is full!")
+ )
+ )
+ );
+ return;
+ }
+ $this->response->addJSON(
+ array(
+ 'user' => $user,
+ 'favorite_tables' => json_encode($favorite_tables),
+ 'list' => $fav_instance->getHtmlList(),
+ 'anchor' => Template::get('database/structure/favorite_anchor')
+ ->render(
+ array(
+ 'db' => $this->db,
+ 'current_table' => array(
+ 'TABLE_NAME' => $favorite_table
+ ),
+ 'titles' => $titles
+ )
+ )
+ )
+ );
+ }
+
+ /**
+ * Handles request for real row count on database level view page.
+ *
+ * @return boolean true
+ */
+ public function handleRealRowCountRequestAction()
+ {
+ $ajax_response = $this->response;
+ // If there is a request to update all table's row count.
+ if (!isset($_REQUEST['real_row_count_all'])) {
+ // Get the real row count for the table.
+ $real_row_count = $this->dbi
+ ->getTable($this->db, $_REQUEST['table'])
+ ->getRealRowCountTable();
+ // Format the number.
+ $real_row_count = PMA_Util::formatNumber($real_row_count, 0);
+ $ajax_response->addJSON('real_row_count', $real_row_count);
+ return;
+ }
+
+ // Array to store the results.
+ $real_row_count_all = array();
+ // Iterate over each table and fetch real row count.
+ foreach ($GLOBALS['tables'] as $table) {
+ $row_count = $this->dbi
+ ->getTable($this->db, $table['TABLE_NAME'])
+ ->getRealRowCountTable();
+ $real_row_count_all[] = array(
+ 'table' => $table['TABLE_NAME'],
+ 'row_count' => $row_count
+ );
+ }
+
+ $ajax_response->addJSON(
+ 'real_row_count_all',
+ json_encode($real_row_count_all)
+ );
+ }
+
+ /**
+ * Synchronize favorite tables
+ *
+ *
+ * @param PMA_RecentFavoriteTable $fav_instance Instance of this class
+ * @param string $user The user hash
+ * @param array $favorite_tables Existing favorites
+ *
+ * @return void
+ */
+ protected function synchronizeFavoriteTables(
+ $fav_instance,
+ $user,
+ $favorite_tables
+ ) {
+ $fav_instance_tables = $fav_instance->getTables();
+
+ if (empty($fav_instance_tables)
+ && isset($favorite_tables[$user])
+ ) {
+ foreach ($favorite_tables[$user] as $key => $value) {
+ $fav_instance->add($value['db'], $value['table']);
+ }
+ }
+ $favorite_tables[$user] = $fav_instance->getTables();
+
+ $this->response->addJSON(
+ array(
+ 'favorite_tables' => json_encode($favorite_tables),
+ 'list' => $fav_instance->getHtmlList()
+ )
+ );
+ $server_id = $GLOBALS['server'];
+ // Set flag when localStorage and pmadb(if present) are in sync.
+ $_SESSION['tmpval']['favorites_synced'][$server_id] = true;
+ }
+
+ /**
+ * Function to check if a table is already in favorite list.
+ *
+ * @param string $current_table current table
+ *
+ * @return true|false
+ */
+ protected function checkFavoriteTable($current_table)
+ {
+ foreach (
+ $_SESSION['tmpval']['favorite_tables'][$GLOBALS['server']] as $value
+ ) {
+ if ($value['db'] == $this->db && $value['table'] == $current_table) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Find table with truename
+ *
+ * @param array $db DB to look into
+ * @param string $truename Table name
+ *
+ * @return bool
+ */
+ protected function hasTable($db, $truename)
+ {
+ foreach ($db as $db_table) {
+ if ($this->db == PMA_extractDbOrTable($db_table)
+ && preg_match(
+ "@^" . /*overload*/
+ mb_substr(PMA_extractDbOrTable($db_table, 'table'), 0, -1) . "@",
+ $truename
+ )
+ ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the value set for ENGINE table,
+ *
+ * @param array $current_table current table
+ * @param double $sum_size total table size
+ * @param double $overhead_size overhead size
+ *
+ * @return array
+ * @internal param bool $table_is_view whether table is view or not
+ */
+ protected function getStuffForEngineTypeTable(
+ $current_table, $sum_size, $overhead_size
+ ) {
+ $formatted_size = '-';
+ $unit = '';
+ $formatted_overhead = '';
+ $overhead_unit = '';
+ $table_is_view = false;
+
+ switch ( $current_table['ENGINE']) {
+ // MyISAM, ISAM or Heap table: Row count, data size and index size
+ // are accurate; data size is accurate for ARCHIVE
+ case 'MyISAM' :
+ case 'ISAM' :
+ case 'HEAP' :
+ case 'MEMORY' :
+ case 'ARCHIVE' :
+ case 'Aria' :
+ case 'Maria' :
+ list($current_table, $formatted_size, $unit, $formatted_overhead,
+ $overhead_unit, $overhead_size, $sum_size)
+ = $this->getValuesForAriaTable(
+ $current_table, $sum_size, $overhead_size,
+ $formatted_size, $unit, $formatted_overhead, $overhead_unit
+ );
+ break;
+ case 'InnoDB' :
+ case 'PBMS' :
+ // InnoDB table: Row count is not accurate but data and index sizes are.
+ // PBMS table in Drizzle: TABLE_ROWS is taken from table cache,
+ // so it may be unavailable
+ list($current_table, $formatted_size, $unit, $sum_size)
+ = $this->getValuesForInnodbTable(
+ $current_table, $sum_size
+ );
+ //$display_rows = ' - ';
+ break;
+ // Mysql 5.0.x (and lower) uses MRG_MyISAM
+ // and MySQL 5.1.x (and higher) uses MRG_MYISAM
+ // Both are aliases for MERGE
+ case 'MRG_MyISAM' :
+ case 'MRG_MYISAM' :
+ case 'MERGE' :
+ case 'BerkeleyDB' :
+ // Merge or BerkleyDB table: Only row count is accurate.
+ if ($this->_is_show_stats) {
+ $formatted_size = ' - ';
+ $unit = '';
+ }
+ break;
+ // for a view, the ENGINE is sometimes reported as null,
+ // or on some servers it's reported as "SYSTEM VIEW"
+ case null :
+ case 'SYSTEM VIEW' :
+ case 'FunctionEngine' :
+ // possibly a view, do nothing
+ break;
+ default :
+ // Unknown table type.
+ if ($this->_is_show_stats) {
+ $formatted_size = __('unknown');
+ $unit = '';
+ }
+ } // end switch
+
+ if ($current_table['TABLE_TYPE'] == 'VIEW'
+ || $current_table['TABLE_TYPE'] == 'SYSTEM VIEW'
+ ) {
+ // countRecords() takes care of $cfg['MaxExactCountViews']
+ $current_table['TABLE_ROWS'] = $this->dbi
+ ->getTable($this->db, $current_table['TABLE_NAME'])
+ ->countRecords(true);
+ $table_is_view = true;
+ }
+
+ return array($current_table, $formatted_size, $unit, $formatted_overhead,
+ $overhead_unit, $overhead_size, $table_is_view, $sum_size
+ );
+ }
+
+ /**
+ * Get values for ARIA/MARIA tables
+ *
+ * @param array $current_table current table
+ * @param double $sum_size sum size
+ * @param double $overhead_size overhead size
+ * @param number $formatted_size formatted size
+ * @param string $unit unit
+ * @param number $formatted_overhead overhead formatted
+ * @param string $overhead_unit overhead unit
+ *
+ * @return array
+ */
+ protected function getValuesForAriaTable(
+ $current_table, $sum_size, $overhead_size, $formatted_size, $unit,
+ $formatted_overhead, $overhead_unit
+ ) {
+ if ($this->_db_is_system_schema) {
+ $current_table['Rows'] = $this->dbi
+ ->getTable($this->db, $current_table['Name'])
+ ->countRecords();
+ }
+
+ if ($this->_is_show_stats) {
+ $tblsize = doubleval($current_table['Data_length'])
+ + doubleval($current_table['Index_length']);
+ $sum_size += $tblsize;
+ list($formatted_size, $unit) = PMA_Util::formatByteDown(
+ $tblsize, 3, ($tblsize > 0) ? 1 : 0
+ );
+ if (isset($current_table['Data_free'])
+ && $current_table['Data_free'] > 0
+ ) {
+ // here, the value 4 as the second parameter
+ // would transform 6.1MiB into 6,224.6KiB
+ list($formatted_overhead, $overhead_unit)
+ = PMA_Util::formatByteDown(
+ $current_table['Data_free'], 4,
+ (($current_table['Data_free'] > 0) ? 1 : 0)
+ );
+ $overhead_size += $current_table['Data_free'];
+ }
+ }
+ return array($current_table, $formatted_size, $unit, $formatted_overhead,
+ $overhead_unit, $overhead_size, $sum_size
+ );
+ }
+
+ /**
+ * Get values for InnoDB table
+ *
+ * @param array $current_table current table
+ * @param double $sum_size sum size
+ *
+ * @return array
+ */
+ protected function getValuesForInnodbTable(
+ $current_table, $sum_size
+ ) {
+ $formatted_size = $unit = '';
+
+ if (($current_table['ENGINE'] == 'InnoDB'
+ && $current_table['TABLE_ROWS'] < $GLOBALS['cfg']['MaxExactCount'])
+ || !isset($current_table['TABLE_ROWS'])
+ ) {
+ $current_table['COUNTED'] = true;
+ $current_table['TABLE_ROWS'] = $this->dbi
+ ->getTable($this->db, $current_table['TABLE_NAME'])
+ ->countRecords(true);
+ } else {
+ $current_table['COUNTED'] = false;
+ }
+
+ // Drizzle doesn't provide data and index length, check for null
+ if ($this->_is_show_stats && $current_table['Data_length'] !== null) {
+ $tblsize = $current_table['Data_length']
+ + $current_table['Index_length'];
+ $sum_size += $tblsize;
+ list($formatted_size, $unit) = PMA_Util::formatByteDown(
+ $tblsize, 3, (($tblsize > 0) ? 1 : 0)
+ );
+ }
+
+ return array($current_table, $formatted_size, $unit, $sum_size);
+ }
+}
diff --git a/libraries/controllers/TableChartController.class.php b/libraries/controllers/TableChartController.class.php
new file mode 100644
index 0000000000..807a5da0df
--- /dev/null
+++ b/libraries/controllers/TableChartController.class.php
@@ -0,0 +1,248 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+
+/**
+ * Holds the PMA\TableChartController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers\Table;
+
+use PMA\DI\Container;
+use PMA_Util;
+use PMA_Message;
+use PMA\Template;
+use PMA\Controllers\TableController;
+
+require_once 'libraries/Util.class.php';
+require_once 'libraries/Message.class.php';
+require_once 'libraries/Template.class.php';
+require_once 'libraries/controllers/TableController.class.php';
+
+/**
+ * Handles table related logic
+ *
+ * @package PhpMyAdmin
+ */
+class TableChartController extends TableController
+{
+
+ /**
+ * @var string $sql_query
+ */
+ protected $sql_query;
+
+ /**
+ * @var string $url_query
+ */
+ protected $url_query;
+
+ /**
+ * @var array $cfg
+ */
+ protected $cfg;
+
+ /**
+ * Constructor
+ *
+ * @param string $sql_query Query
+ * @param string $url_query Query URL
+ * @param array $cfg Configuration
+ */
+ public function __construct($sql_query, $url_query, $cfg)
+ {
+ parent::__construct();
+
+ $this->sql_query = $sql_query;
+ $this->url_query = $url_query;
+ $this->cfg = $cfg;
+ }
+
+ /**
+ * Execute the query and return the result
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ if (isset($_REQUEST['ajax_request'])
+ && isset($_REQUEST['pos'])
+ && isset($_REQUEST['session_max_rows'])
+ ) {
+ $this->ajaxAction();
+ return;
+ }
+
+ // Throw error if no sql query is set
+ if (!isset($this->sql_query) || $this->sql_query == '') {
+ $this->response->isSuccess(false);
+ $this->response->addHTML(
+ PMA_Message::error(__('No SQL query was set to fetch data.'))
+ );
+ return;
+ }
+
+ $this->response->getHeader()->getScripts()->addFiles(
+ array(
+ 'chart.js',
+ 'tbl_chart.js',
+ 'jqplot/jquery.jqplot.js',
+ 'jqplot/plugins/jqplot.barRenderer.js',
+ 'jqplot/plugins/jqplot.canvasAxisLabelRenderer.js',
+ 'jqplot/plugins/jqplot.canvasTextRenderer.js',
+ 'jqplot/plugins/jqplot.categoryAxisRenderer.js',
+ 'jqplot/plugins/jqplot.dateAxisRenderer.js',
+ 'jqplot/plugins/jqplot.pointLabels.js',
+ 'jqplot/plugins/jqplot.pieRenderer.js',
+ 'jqplot/plugins/jqplot.highlighter.js'
+ )
+ );
+
+ /**
+ * Extract values for common work
+ * @todo Extract common files
+ */
+ $db = &$this->db;
+ $table = &$this->table;
+
+ /**
+ * Runs common work
+ */
+ if (/*overload*/ mb_strlen($this->table)) {
+ $url_params['goto'] = PMA_Util::getScriptNameForOption(
+ $this->cfg['DefaultTabTable'], 'table'
+ );
+ $url_params['back'] = 'tbl_sql.php';
+ include 'libraries/tbl_common.inc.php';
+ include 'libraries/tbl_info.inc.php';
+ } elseif (/*overload*/ mb_strlen($this->db)) {
+ $url_params['goto'] = PMA_Util::getScriptNameForOption(
+ $this->cfg['DefaultTabDatabase'], 'database'
+ );
+ $url_params['back'] = 'sql.php';
+ include 'libraries/db_common.inc.php';
+
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
+
+ } else {
+ $url_params['goto'] = PMA_Util::getScriptNameForOption(
+ $this->cfg['DefaultTabServer'], 'server'
+ );
+ $url_params['back'] = 'sql.php';
+ include 'libraries/server_common.inc.php';
+ }
+
+ $data = array();
+
+ $result = $this->dbi->tryQuery($this->sql_query);
+ $fields_meta = $this->dbi->getFieldsMeta($result);
+ while ($row = $this->dbi->fetchAssoc($result)) {
+ $data[] = $row;
+ }
+
+ $keys = array_keys($data[0]);
+
+ $numeric_types = array('int', 'real');
+ $numeric_column_count = 0;
+ foreach ($keys as $idx => $key) {
+ if (in_array($fields_meta[$idx]->type, $numeric_types)) {
+ $numeric_column_count++;
+ }
+ }
+
+ if ($numeric_column_count == 0) {
+ $this->response->isSuccess(false);
+ $this->response->addJSON(
+ 'message',
+ __('No numeric columns present in the table to plot.')
+ );
+ return;
+ }
+
+ $url_params['db'] = $this->db;
+ $url_params['reload'] = 1;
+
+ /**
+ * Displays the page
+ */
+ $this->response->addHTML(
+ Template::get('table/chart/tbl_chart')->render(
+ array(
+ 'url_query' => $this->url_query,
+ 'url_params' => $url_params,
+ 'keys' => $keys,
+ 'fields_meta' => $fields_meta,
+ 'numeric_types' => $numeric_types,
+ 'numeric_column_count' => $numeric_column_count,
+ 'sql_query' => $this->sql_query
+ )
+ )
+ );
+ }
+
+ /**
+ * Handle ajax request
+ *
+ * @return void
+ */
+ public function ajaxAction()
+ {
+ /**
+ * Extract values for common work
+ * @todo Extract common files
+ */
+ $db = &$this->db;
+ $table = &$this->table;
+
+ $tableLength = /*overload*/
+ mb_strlen($this->table);
+ $dbLength = /*overload*/
+ mb_strlen($this->db);
+ if ($tableLength && $dbLength) {
+ include './libraries/tbl_common.inc.php';
+ }
+
+ $sql_with_limit = sprintf(
+ 'SELECT * FROM(%s) AS `temp_res` LIMIT %s, %s',
+ $this->sql_query,
+ $_REQUEST['pos'],
+ $_REQUEST['session_max_rows']
+ );
+ $data = array();
+ $result = $this->dbi->tryQuery($sql_with_limit);
+ while ($row = $this->dbi->fetchAssoc($result)) {
+ $data[] = $row;
+ }
+
+ if (empty($data)) {
+ $this->response->isSuccess(false);
+ $this->response->addJSON('message', __('No data to display'));
+ return;
+ }
+ $sanitized_data = array();
+
+ foreach ($data as $data_row_number => $data_row) {
+ $tmp_row = array();
+ foreach ($data_row as $data_column => $data_value) {
+ $tmp_row[htmlspecialchars($data_column)] = htmlspecialchars(
+ $data_value
+ );
+ }
+ $sanitized_data[] = $tmp_row;
+ }
+ $this->response->isSuccess(true);
+ $this->response->addJSON('message', null);
+ $this->response->addJSON('chartData', json_encode($sanitized_data));
+ }
+}
diff --git a/libraries/controllers/TableController.class.php b/libraries/controllers/TableController.class.php
new file mode 100644
index 0000000000..70ddaf8325
--- /dev/null
+++ b/libraries/controllers/TableController.class.php
@@ -0,0 +1,45 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\TableController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers;
+
+use PMA\DI\Container;
+
+if (!defined('PHPMYADMIN')) {
+ exit;
+}
+
+require_once 'libraries/controllers/Controller.class.php';
+
+/**
+ * Handles table related logic
+ *
+ * @package PhpMyAdmin
+ */
+abstract class TableController extends Controller
+{
+ /**
+ * @var string $db
+ */
+ protected $db;
+
+ /**
+ * @var string $table
+ */
+ protected $table;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->db = $this->container->get('db');
+ $this->table = $this->container->get('table');
+ }
+}
diff --git a/libraries/controllers/TableGisVisualizationController.class.php b/libraries/controllers/TableGisVisualizationController.class.php
new file mode 100644
index 0000000000..5dfc48d0a3
--- /dev/null
+++ b/libraries/controllers/TableGisVisualizationController.class.php
@@ -0,0 +1,216 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+
+/**
+ * Holds the PMA\TableIndexesController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers\Table;
+
+use PMA\Template;
+use PMA_GIS_Visualization;
+use PMA_Message;
+use PMA\Controllers\TableController;
+
+require_once 'libraries/common.inc.php';
+require_once 'libraries/db_common.inc.php';
+require_once 'libraries/controllers/TableController.class.php';
+require_once 'libraries/gis/GIS_Visualization.class.php';
+require_once 'libraries/gis/GIS_Factory.class.php';
+require_once 'libraries/Message.class.php';
+
+/**
+ * Class TableGisVisualizationController
+ *
+ * @package PMA\Controllers\Table
+ */
+class TableGisVisualizationController extends TableController
+{
+
+ /**
+ * @var array $url_params
+ */
+ protected $url_params;
+
+ /**
+ * @var string $sql_query
+ */
+ protected $sql_query;
+
+ /**
+ * @var array $visualizationSettings
+ */
+ protected $visualizationSettings;
+
+ /**
+ * @var PMA_GIS_Visualization $visualization
+ */
+ protected $visualization;
+
+ /**
+ * Constructor
+ *
+ * @param string $sql_query SQL query for retrieving GIS data
+ * @param array $url_params array of URL parameters
+ * @param string $goto goto script
+ * @param string $back back script
+ * @param array $visualizationSettings visualization settings
+ */
+ public function __construct(
+ $sql_query,
+ $url_params,
+ $goto,
+ $back,
+ $visualizationSettings
+ ) {
+ parent::__construct();
+
+ $this->sql_query = $sql_query;
+ $this->url_params = $url_params;
+ $this->url_params['goto'] = $goto;
+ $this->url_params['back'] = $back;
+ $this->visualizationSettings = $visualizationSettings;
+ }
+
+ /**
+ * Save to file
+ *
+ * @return void
+ */
+ public function saveToFileAction()
+ {
+ $this->response->disable();
+ $file_name = $this->visualizationSettings['spatialColumn'];
+ $save_format = $_REQUEST['fileFormat'];
+ $this->visualization->toFile($file_name, $save_format);
+ }
+
+ /**
+ * Index
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ // Throw error if no sql query is set
+ if (! isset($this->sql_query) || $this->sql_query == '') {
+ $this->response->isSuccess(false);
+ $this->response->addHTML(
+ PMA_Message::error(__('No SQL query was set to fetch data.'))
+ );
+ return;
+ }
+
+ // Execute the query and return the result
+ $result = $this->dbi->tryQuery($this->sql_query);
+ // Get the meta data of results
+ $meta = $this->dbi->getFieldsMeta($result);
+
+ // Find the candidate fields for label column and spatial column
+ $labelCandidates = array();
+ $spatialCandidates = array();
+ foreach ($meta as $column_meta) {
+ if ($column_meta->type == 'geometry') {
+ $spatialCandidates[] = $column_meta->name;
+ } else {
+ $labelCandidates[] = $column_meta->name;
+ }
+ }
+
+ // Get settings if any posted
+ if (PMA_isValid($_REQUEST['visualizationSettings'], 'array')) {
+ $this->visualizationSettings = $_REQUEST['visualizationSettings'];
+ }
+
+ if (!isset($this->visualizationSettings['labelColumn'])
+ && isset($labelCandidates[0])
+ ) {
+ $this->visualizationSettings['labelColumn'] = '';
+ }
+
+ // If spatial column is not set, use first geometric column as spatial column
+ if (! isset($this->visualizationSettings['spatialColumn'])) {
+ $this->visualizationSettings['spatialColumn'] = $spatialCandidates[0];
+ }
+
+ // Convert geometric columns from bytes to text.
+ $pos = isset($_REQUEST['pos']) ? $_REQUEST['pos']
+ : $_SESSION['tmpval']['pos'];
+ if (isset($_REQUEST['session_max_rows'])) {
+ $rows = $_REQUEST['session_max_rows'];
+ } else {
+ if ($_SESSION['tmpval']['max_rows'] != 'all') {
+ $rows = $_SESSION['tmpval']['max_rows'];
+ } else {
+ $rows = $GLOBALS['cfg']['MaxRows'];
+ }
+ }
+ $this->visualization = PMA_GIS_Visualization::get(
+ $this->sql_query,
+ $this->visualizationSettings,
+ $rows,
+ $pos
+ );
+
+ if (isset($_REQUEST['saveToFile'])) {
+ $this->saveToFileAction();
+ return;
+ }
+
+ $this->response->getHeader()->getScripts()->addFiles(
+ array(
+ 'openlayers/OpenLayers.js',
+ 'jquery/jquery.svg.js',
+ 'tbl_gis_visualization.js',
+ 'OpenStreetMap.js'
+ )
+ );
+
+ // If all the rows contain SRID, use OpenStreetMaps on the initial loading.
+ if (! isset($_REQUEST['displayVisualization'])) {
+ if ($this->visualization->hasSrid()) {
+ $this->visualizationSettings['choice'] = 'useBaseLayer';
+ } else {
+ unset($this->visualizationSettings['choice']);
+ }
+ }
+
+ $this->visualization->setUserSpecifiedSettings($this->visualizationSettings);
+ if ($this->visualizationSettings != null) {
+ foreach ($this->visualization->getSettings() as $setting => $val) {
+ if (! isset($this->visualizationSettings[$setting])) {
+ $this->visualizationSettings[$setting] = $val;
+ }
+ }
+ }
+
+ /**
+ * Displays the page
+ */
+ $this->url_params['sql_query'] = $this->sql_query;
+ $downloadUrl = 'tbl_gis_visualization.php' . PMA_URL_getCommon(
+ $this->url_params
+ ) . '&saveToFile=true';
+ $svgSupport = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8)
+ ? false : true;
+ $html = Template::get('table/gis_visualization/gis_visualization')->render(
+ array(
+ 'url_params' => $this->url_params,
+ 'downloadUrl' => $downloadUrl,
+ 'labelCandidates' => $labelCandidates,
+ 'spatialCandidates' => $spatialCandidates,
+ 'visualizationSettings' => $this->visualizationSettings,
+ 'sql_query' => $this->sql_query,
+ 'visualization' => $this->visualization->toImage(
+ $svgSupport ? 'svg' : 'png'
+ ),
+ 'svgSupport' => $svgSupport,
+ 'drawOl' => $this->visualization->asOl()
+ )
+ );
+
+ $this->response->addHTML($html);
+ }
+}
diff --git a/libraries/controllers/TableIndexesController.class.php b/libraries/controllers/TableIndexesController.class.php
new file mode 100644
index 0000000000..6d29877ee0
--- /dev/null
+++ b/libraries/controllers/TableIndexesController.class.php
@@ -0,0 +1,180 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+
+/**
+ * Holds the PMA\TableIndexesController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers\Table;
+
+use PMA\Controllers\TableController;
+use PMA_Index;
+use PMA_Message;
+use PMA_Response;
+use PMA\Template;
+use PMA_Util;
+
+require_once 'libraries/Index.class.php';
+require_once 'libraries/Message.class.php';
+require_once 'libraries/Util.class.php';
+require_once 'libraries/Index.class.php';
+require_once 'libraries/controllers/TableController.class.php';
+require_once 'libraries/Template.class.php';
+
+/**
+ * Class TableIndexesController
+ *
+ * @package PMA\Controllers\Table
+ */
+class TableIndexesController extends TableController
+{
+ /**
+ * @var PMA_Index $index
+ */
+ protected $index;
+
+ /**
+ * Constructor
+ *
+ * @param PMA_Index $index Index
+ */
+ public function __construct($index)
+ {
+ parent::__construct();
+
+ $this->index = $index;
+ }
+
+ /**
+ * Index
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ if (isset($_REQUEST['do_save_data'])) {
+ $this->doSaveDataAction();
+ return;
+ } // end builds the new index
+
+ $this->displayFormAction();
+ }
+
+ /**
+ * Display the form to edit/create an index
+ *
+ * @return void
+ */
+ public function displayFormAction()
+ {
+ include_once 'libraries/tbl_info.inc.php';
+
+ $add_fields = 0;
+ if (isset($_REQUEST['index']) && is_array($_REQUEST['index'])) {
+ // coming already from form
+ if (isset($_REQUEST['index']['columns']['names'])) {
+ $add_fields = count($_REQUEST['index']['columns']['names'])
+ - $this->index->getColumnCount();
+ }
+ if (isset($_REQUEST['add_fields'])) {
+ $add_fields += $_REQUEST['added_fields'];
+ }
+ } elseif (isset($_REQUEST['create_index'])) {
+ $add_fields = $_REQUEST['added_fields'];
+ } // end preparing form values
+
+ // Get fields and stores their name/type
+ if (isset($_REQUEST['create_edit_table'])) {
+ $fields = json_decode($_REQUEST['columns'], true);
+ $index_params = array(
+ 'Non_unique' => ($_REQUEST['index']['Index_choice'] == 'UNIQUE')
+ ? '0' : '1',
+ );
+ $this->index->set($index_params);
+ $add_fields = count($fields);
+ } else {
+ $fields = $this->dbi->getTable($this->db, $this->table)
+ ->getNameAndTypeOfTheColumns();
+ }
+
+ $form_params = array(
+ 'db' => $this->db,
+ 'table' => $this->table,
+ );
+
+ if (isset($_REQUEST['create_index'])) {
+ $form_params['create_index'] = 1;
+ } elseif (isset($_REQUEST['old_index'])) {
+ $form_params['old_index'] = $_REQUEST['old_index'];
+ } elseif (isset($_REQUEST['index'])) {
+ $form_params['old_index'] = $_REQUEST['index'];
+ }
+
+ $this->response->getHeader()->getScripts()->addFile('indexes.js');
+
+ $this->response->addHTML(
+ Template::get('table/index_form')->render(
+ array(
+ 'fields' => $fields,
+ 'index' => $this->index,
+ 'form_params' => $form_params,
+ 'add_fields' => $add_fields
+ )
+ )
+ );
+ }
+
+ /**
+ * Process the data from the edit/create index form,
+ * run the query to build the new index
+ * and moves back to "tbl_sql.php"
+ *
+ * @return void
+ */
+ public function doSaveDataAction()
+ {
+ $error = false;
+
+ $sql_query = $this->dbi->getTable($this->db, $this->table)
+ ->getSqlQueryForIndexCreateOrEdit($this->index, $error);
+
+ // If there is a request for SQL previewing.
+ if (isset($_REQUEST['preview_sql'])) {
+
+ $this->response->addJSON(
+ 'sql_data',
+ Template::get('preview_sql')
+ ->render(
+ array(
+ 'query_data' => $sql_query
+ )
+ )
+ );
+ } elseif (!$error) {
+
+ $this->dbi->query($sql_query);
+ if ($GLOBALS['is_ajax_request'] == true) {
+ $message = PMA_Message::success(
+ __('Table %1$s has been altered successfully.')
+ );
+ $message->addParam($this->table);
+ $this->response->addJSON(
+ 'message', PMA_Util::getMessage($message, $sql_query, 'success')
+ );
+ $this->response->addJSON(
+ 'index_table',
+ PMA_Index::getHtmlForIndexes(
+ $this->table, $this->db
+ )
+ );
+ } else {
+ include 'tbl_structure.php';
+ }
+ } else {
+ $this->response->isSuccess(false);
+ $this->response->addJSON('message', $error);
+ }
+ }
+}
diff --git a/libraries/controllers/TableRelationController.class.php b/libraries/controllers/TableRelationController.class.php
new file mode 100644
index 0000000000..58705bae62
--- /dev/null
+++ b/libraries/controllers/TableRelationController.class.php
@@ -0,0 +1,384 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\TableRelationController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers\Table;
+
+require_once 'libraries/DatabaseInterface.class.php';
+require_once 'libraries/controllers/TableController.class.php';
+require_once 'libraries/index.lib.php';
+require_once 'libraries/Template.class.php';
+require_once 'libraries/Table.class.php';
+require_once 'libraries/Index.class.php';
+require_once 'libraries/Util.class.php';
+
+use PMA_DatabaseInterface;
+use PMA_Table;
+use PMA_Index;
+use PMA_Util;
+use PMA\Controllers\TableController;
+use PMA\Template;
+
+/**
+ * Handles table relation logic
+ *
+ * @package PhpMyAdmin
+ */
+class TableRelationController extends TableController
+{
+ /**
+ * @var array $options_array
+ */
+ protected $options_array;
+
+ /**
+ * @var array $cfgRelation
+ */
+ protected $cfgRelation;
+
+ /**
+ * @var array $existrel
+ */
+ protected $existrel;
+
+ /**
+ * @var string $disp
+ */
+ protected $disp;
+
+ /**
+ * @var string $tbl_storage_engine
+ */
+ protected $tbl_storage_engine;
+
+ /**
+ * @var array $existrel_foreign
+ */
+ protected $existrel_foreign;
+
+ /**
+ * @var PMA_Table $udp_query
+ */
+ protected $upd_query;
+
+ /**
+ * Constructor
+ *
+ * @param array $options_array Options
+ * @param array $cfgRelation Config relation
+ * @param string $tbl_storage_engine Table storage engine
+ * @param array $existrel Relations
+ * @param array $existrel_foreign External relations
+ * @param string $disp Display
+ * @param string $upd_query Update query
+ */
+ public function __construct($options_array, $cfgRelation, $tbl_storage_engine,
+ $existrel, $existrel_foreign, $disp, $upd_query
+ ) {
+ parent::__construct();
+
+ $this->options_array = $options_array;
+ $this->cfgRelation = $cfgRelation;
+ $this->tbl_storage_engine = $tbl_storage_engine;
+ $this->existrel = $existrel;
+ $this->existrel_foreign = $existrel_foreign;
+ $this->disp = $disp;
+ $this->upd_query = $upd_query;
+ }
+
+ /**
+ * Index
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ // Send table of column names to populate corresponding dropdowns depending
+ // on the current selection
+ if (isset($_REQUEST['getDropdownValues'])
+ && $_REQUEST['getDropdownValues'] === 'true'
+ ) {
+ // if both db and table are selected
+ if (isset($_REQUEST['foreignTable'])) {
+ $this->getDropdownValueForTableAction();
+ } else { // if only the db is selected
+ $this->getDropdownValueForDbAction();
+ }
+ return;
+ }
+
+ $this->response->getHeader()->getScripts()->addFiles(
+ array(
+ 'tbl_relation.js',
+ 'indexes.js'
+ )
+ );
+
+ // Gets tables information
+ include_once 'libraries/tbl_info.inc.php';
+
+ // updates for Internal relations
+ if (isset($_POST['destination_db']) && $this->cfgRelation['relwork']) {
+ $this->updateForInternalRelationAction();
+ }
+
+ // updates for foreign keys
+ if (isset($_POST['destination_foreign_db'])) {
+ $this->updateForForeignKeysAction();
+ }
+
+ // Updates for display field
+ if ($this->cfgRelation['displaywork'] && isset($_POST['display_field'])) {
+ $this->updateForDisplayField();
+ }
+
+ // If we did an update, refresh our data
+ if (isset($_POST['destination_db']) && $this->cfgRelation['relwork']) {
+ $this->existrel = PMA_getForeigners(
+ $this->db, $this->table, '', 'internal'
+ );
+ }
+ if (isset($_POST['destination_foreign_db'])
+ && PMA_Util::isForeignKeySupported($this->tbl_storage_engine)
+ ) {
+ $this->existrel_foreign = PMA_getForeigners(
+ $this->db, $this->table, '', 'foreign'
+ );
+ }
+
+ if ($this->cfgRelation['displaywork']) {
+ $this->disp = PMA_getDisplayField($this->db, $this->table);
+ }
+
+ // display secondary level tabs if necessary
+ $engine = $this->dbi->getTable($this->db, $this->table)
+ ->getStatusInfo('ENGINE');
+
+ $this->response->addHTML(
+ Template::get('table/secondary_tabs')->render(
+ array(
+ 'url_params' => array(
+ 'db' => $GLOBALS['db'],
+ 'table' => $GLOBALS['table']
+ ),
+ 'engine' => $engine
+ )
+ )
+ );
+ $this->response->addHTML('<div id="structure_content">');
+
+ /**
+ * Dialog
+ */
+ // Now find out the columns of our $table
+ // need to use PMA_DatabaseInterface::QUERY_STORE with $this->dbi->numRows()
+ // in mysqli
+ $columns = $this->dbi->getColumns($this->db, $this->table);
+
+ // common form
+ $this->response->addHTML(
+ Template::get('table/relation/common_form')->render(
+ array(
+ 'db' => $this->db,
+ 'table' => $this->table,
+ 'columns' => $columns,
+ 'cfgRelation' => $this->cfgRelation,
+ 'tbl_storage_engine' => $this->tbl_storage_engine,
+ 'existrel' => isset($this->existrel) ? $this->existrel : array(),
+ 'existrel_foreign' => isset($this->existrel_foreign)
+ ? $this->existrel_foreign['foreign_keys_data'] : array(),
+ 'options_array' => $this->options_array
+ )
+ )
+ );
+
+ if (PMA_Util::isForeignKeySupported($this->tbl_storage_engine)) {
+ $this->response->addHTML(PMA_getHtmlForDisplayIndexes());
+ }
+ $this->response->addHTML('</div>');
+ }
+
+ /**
+ * Update for display field
+ *
+ * @return void
+ */
+ public function updateForDisplayField()
+ {
+ if ($this->upd_query->updateDisplayField(
+ $this->disp, $_POST['display_field'], $this->cfgRelation
+ )
+ ) {
+ $this->response->addHTML(
+ PMA_Util::getMessage(
+ __('Display column was successfully updated.'),
+ '', 'success'
+ )
+ );
+ }
+ }
+
+ /**
+ * Update for FK
+ *
+ * @return void
+ */
+ public function updateForForeignKeysAction()
+ {
+ $multi_edit_columns_name = isset($_REQUEST['foreign_key_fields_name'])
+ ? $_REQUEST['foreign_key_fields_name']
+ : null;
+
+ // (for now, one index name only; we keep the definitions if the
+ // foreign db is not the same)
+ list($html, $preview_sql_data, $display_query, $seen_error)
+ = $this->upd_query->updateForeignKeys(
+ $_POST['destination_foreign_db'],
+ $multi_edit_columns_name, $_POST['destination_foreign_table'],
+ $_POST['destination_foreign_column'], $this->options_array,
+ $this->table,
+ isset($this->existrel_foreign)
+ ? $this->existrel_foreign['foreign_keys_data']
+ : null
+ );
+ $this->response->addHTML($html);
+
+ // If there is a request for SQL previewing.
+ if (isset($_REQUEST['preview_sql'])) {
+ PMA_previewSQL($preview_sql_data);
+ }
+
+ if (!empty($display_query) && !$seen_error) {
+ $GLOBALS['display_query'] = $display_query;
+ $this->response->addHTML(
+ PMA_Util::getMessage(
+ __('Your SQL query has been executed successfully.'),
+ null, 'success'
+ )
+ );
+ }
+ }
+
+ /**
+ * Update for internal relation
+ *
+ * @return void
+ */
+ public function updateForInternalRelationAction()
+ {
+ $multi_edit_columns_name = isset($_REQUEST['fields_name'])
+ ? $_REQUEST['fields_name']
+ : null;
+
+ if ($this->upd_query->updateInternalRelations(
+ $multi_edit_columns_name,
+ $_POST['destination_db'],
+ $_POST['destination_table'],
+ $_POST['destination_column'],
+ $this->cfgRelation,
+ isset($this->existrel) ? $this->existrel : null
+ )
+ ) {
+ $this->response->addHTML(
+ PMA_Util::getMessage(
+ __('Internal relations were successfully updated.'),
+ '', 'success'
+ )
+ );
+ }
+ }
+
+ /**
+ * Send table columns for foreign table dropdown
+ *
+ * @return void
+ *
+ */
+ public function getDropdownValueForTableAction()
+ {
+ $foreignTable = $_REQUEST['foreignTable'];
+ $table_obj = $this->dbi->getTable($_REQUEST['foreignDb'], $foreignTable);
+ // Since views do not have keys defined on them provide the full list of
+ // columns
+ if ($table_obj->isView()) {
+ $columnList = $table_obj->getColumns(false, false);
+ } else {
+ $columnList = $table_obj->getIndexedColumns(false, false);
+ }
+ $columns = array();
+ foreach ($columnList as $column) {
+ $columns[] = htmlspecialchars($column);
+ }
+ $this->response->addJSON('columns', $columns);
+
+ // @todo should be: $server->db($db)->table($table)->primary()
+ $primary = PMA_Index::getPrimary($foreignTable, $_REQUEST['foreignDb']);
+ if (false === $primary) {
+ return;
+ }
+
+ $this->response->addJSON('primary', array_keys($primary->getColumns()));
+ }
+
+ /**
+ * Send database selection values for dropdown
+ *
+ * @return void
+ *
+ */
+ public function getDropdownValueForDbAction()
+ {
+ $tables = array();
+ $foreign = isset($_REQUEST['foreign']) && $_REQUEST['foreign'] === 'true';
+
+ // In Drizzle, 'SHOW TABLE STATUS' will show status only for the tables
+ // which are currently in the table cache. Hence we have to use 'SHOW TABLES'
+ // and manually retrieve table engine values.
+ if ($foreign && !PMA_DRIZZLE) {
+ $query = 'SHOW TABLE STATUS FROM '
+ . PMA_Util::backquote($_REQUEST['foreignDb']);
+ $tables_rs = $this->dbi->query(
+ $query,
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+
+ while ($row = $this->dbi->fetchArray($tables_rs)) {
+ if (isset($row['Engine'])
+ && /*overload*/ mb_strtoupper($row['Engine']) == $this->tbl_storage_engine
+ ) {
+ $tables[] = htmlspecialchars($row['Name']);
+ }
+ }
+ } else {
+ $query = 'SHOW TABLES FROM '
+ . PMA_Util::backquote($_REQUEST['foreignDb']);
+ $tables_rs = $this->dbi->query(
+ $query,
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+ while ($row = $this->dbi->fetchArray($tables_rs)) {
+ if ($foreign && PMA_DRIZZLE) {
+ $engine = /*overload*/
+ mb_strtoupper(
+ $GLOBALS['dbi']->getTable(
+ $_REQUEST['foreignDb'],
+ $row[0]
+ )->getStatusInfo('Engine')
+ );
+ if (isset($engine) && $engine == $this->tbl_storage_engine) {
+ $tables[] = htmlspecialchars($row[0]);
+ }
+ } else {
+ $tables[] = htmlspecialchars($row[0]);
+ }
+ }
+ }
+ $this->response->addJSON('tables', $tables);
+ }
+}
diff --git a/libraries/controllers/TableSearchController.class.php b/libraries/controllers/TableSearchController.class.php
new file mode 100644
index 0000000000..12de6d2367
--- /dev/null
+++ b/libraries/controllers/TableSearchController.class.php
@@ -0,0 +1,1225 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\Controllers\Table\TableSearchController
+ *
+ * @package PMA\Controllers\Table
+ */
+
+namespace PMA\Controllers\Table;
+
+use PMA\Template;
+use PMA\Controllers\TableController;
+use PMA_DatabaseInterface;
+use PMA_Util;
+
+require_once 'libraries/Template.class.php';
+require_once 'libraries/mysql_charsets.inc.php';
+require_once 'libraries/sql.lib.php';
+require_once 'libraries/bookmark.lib.php';
+require_once 'libraries/controllers/TableController.class.php';
+
+/**
+ * Class TableSearchController
+ *
+ * @package PhpMyAdmin
+ */
+class TableSearchController extends TableController
+{
+ /**
+ * Normal search or Zoom search
+ *
+ * @access private
+ * @var string
+ */
+ private $_searchType;
+ /**
+ * Names of columns
+ *
+ * @access private
+ * @var array
+ */
+ private $_columnNames;
+ /**
+ * Types of columns
+ *
+ * @access private
+ * @var array
+ */
+ private $_columnTypes;
+ /**
+ * Collations of columns
+ *
+ * @access private
+ * @var array
+ */
+ private $_columnCollations;
+ /**
+ * Null Flags of columns
+ *
+ * @access private
+ * @var array
+ */
+ private $_columnNullFlags;
+ /**
+ * Whether a geometry column is present
+ *
+ * @access private
+ * @var boolean
+ */
+ private $_geomColumnFlag;
+ /**
+ * Foreign Keys
+ *
+ * @access private
+ * @var array
+ */
+ private $_foreigners;
+ /**
+ * Connection charset
+ *
+ * @access private
+ * @var string
+ */
+ private $_connectionCharSet;
+
+ protected $url_query;
+
+ /**
+ * Constructor
+ *
+ * @param string $searchType Search type
+ * @param string $url_query URL query
+ */
+ public function __construct($searchType, $url_query)
+ {
+ parent::__construct();
+
+ $this->url_query = $url_query;
+ $this->_searchType = $searchType;
+ $this->_columnNames = array();
+ $this->_columnNullFlags = array();
+ $this->_columnTypes = array();
+ $this->_columnCollations = array();
+ $this->_geomColumnFlag = false;
+ $this->_foreigners = array();
+ // Loads table's information
+ $this->_loadTableInfo();
+ $this->_connectionCharSet = $this->dbi->fetchValue(
+ "SELECT @@character_set_connection"
+ );
+ }
+
+ /**
+ * Gets all the columns of a table along with their types, collations
+ * and whether null or not.
+ *
+ * @return void
+ */
+ private function _loadTableInfo()
+ {
+ // Gets the list and number of columns
+ $columns = $this->dbi->getColumns(
+ $this->db, $this->table, null, true
+ );
+ // Get details about the geometry functions
+ $geom_types = PMA_Util::getGISDatatypes();
+
+ foreach ($columns as $row) {
+ // set column name
+ $this->_columnNames[] = $row['Field'];
+
+ $type = $row['Type'];
+ // check whether table contains geometric columns
+ if (in_array($type, $geom_types)) {
+ $this->_geomColumnFlag = true;
+ }
+ // reformat mysql query output
+ if (strncasecmp($type, 'set', 3) == 0
+ || strncasecmp($type, 'enum', 4) == 0
+ ) {
+ $type = str_replace(',', ', ', $type);
+ } else {
+ // strip the "BINARY" attribute, except if we find "BINARY(" because
+ // this would be a BINARY or VARBINARY column type
+ if (! preg_match('@BINARY[\(]@i', $type)) {
+ $type = preg_replace('@BINARY@i', '', $type);
+ }
+ $type = preg_replace('@ZEROFILL@i', '', $type);
+ $type = preg_replace('@UNSIGNED@i', '', $type);
+ $type = /*overload*/mb_strtolower($type);
+ }
+ if (empty($type)) {
+ $type = '&nbsp;';
+ }
+ $this->_columnTypes[] = $type;
+ $this->_columnNullFlags[] = $row['Null'];
+ $this->_columnCollations[]
+ = ! empty($row['Collation']) && $row['Collation'] != 'NULL'
+ ? $row['Collation']
+ : '';
+ } // end for
+
+ // Retrieve foreign keys
+ $this->_foreigners = PMA_getForeigners($this->db, $this->table);
+ }
+
+ /**
+ * Index action
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ switch ($this->_searchType) {
+ case 'replace':
+ if (isset($_POST['find'])) {
+ $this->findAction();
+
+ return;
+ }
+ $this->response
+ ->getHeader()
+ ->getScripts()
+ ->addFile('tbl_find_replace.js');
+
+ // Show secondary level of tabs
+ $this->response->addHTML(
+ Template::get('secondary_tabs')
+ ->render(
+ array(
+ 'url_params' => array(
+ 'db' => $this->db,
+ 'table' => $this->table,
+ ),
+ 'sub_tabs' => $this->_getSubTabs(),
+ )
+ )
+ );
+
+ if (isset($_POST['replace'])) {
+ $this->replaceAction();
+ }
+
+ if (!isset($goto)) {
+ $goto = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ );
+ }
+ // Defines the url to return to in case of error in the next sql
+ // statement
+ $params = array('db' => $this->db, 'table' => $this->table);
+ $err_url = $goto . '?' . PMA_URL_getCommon($params);
+ // Displays the find and replace form
+ $this->response->addHTML(
+ Template::get('table/search/selection_form')
+ ->render(
+ array(
+ 'searchType' => $this->_searchType,
+ 'db' => $this->db,
+ 'table' => $this->table,
+ 'goto' => $goto,
+ 'self' => $this,
+ 'geomColumnFlag' => $this->_geomColumnFlag,
+ 'columnNames' => $this->_columnNames,
+ 'columnTypes' => $this->_columnTypes,
+ 'columnCollations' => $this->_columnCollations,
+ 'dataLabel' => null,
+ )
+ )
+ );
+ break;
+
+ case 'normal':
+ $this->response->getHeader()
+ ->getScripts()
+ ->addFiles(
+ array(
+ 'makegrid.js',
+ 'sql.js',
+ 'tbl_select.js',
+ 'tbl_change.js',
+ 'jquery/jquery-ui-timepicker-addon.js',
+ 'jquery/jquery.uitablefilter.js',
+ 'gis_data_editor.js',
+ )
+ );
+
+ if (isset($_REQUEST['range_search'])) {
+ $this->rangeSearchAction();
+
+ return;
+ }
+
+ /**
+ * No selection criteria received -> display the selection form
+ */
+ if (!isset($_POST['columnsToDisplay'])
+ && !isset($_POST['displayAllColumns'])
+ ) {
+ $this->displaySelectionFormAction();
+ } else {
+ $this->doSelectionAction();
+ }
+ break;
+
+ case 'zoom':
+ $this->response->getHeader()
+ ->getScripts()
+ ->addFiles(
+ array(
+ 'makegrid.js',
+ 'sql.js',
+ 'jqplot/jquery.jqplot.js',
+ 'jqplot/plugins/jqplot.canvasTextRenderer.js',
+ 'jqplot/plugins/jqplot.canvasAxisLabelRenderer.js',
+ 'jqplot/plugins/jqplot.dateAxisRenderer.js',
+ 'jqplot/plugins/jqplot.highlighter.js',
+ 'jqplot/plugins/jqplot.cursor.js',
+ 'canvg/canvg.js',
+ 'jquery/jquery-ui-timepicker-addon.js',
+ 'tbl_zoom_plot_jqplot.js',
+ 'tbl_change.js',
+ )
+ );
+
+ /**
+ * Handle AJAX request for data row on point select
+ *
+ * @var post_params Object containing parameters for the POST request
+ */
+ if (isset($_REQUEST['get_data_row'])
+ && $_REQUEST['get_data_row'] == true
+ ) {
+ $this->getDataRowAction();
+
+ return;
+ }
+ /**
+ * Handle AJAX request for changing field information
+ * (value,collation,operators,field values) in input form
+ *
+ * @var post_params Object containing parameters for the POST request
+ */
+ if (isset($_REQUEST['change_tbl_info'])
+ && $_REQUEST['change_tbl_info'] == true
+ ) {
+ $this->changeTableInfoAction();
+
+ return;
+ }
+
+ $this->url_query .= '&amp;goto=tbl_select.php&amp;back=tbl_select.php';
+
+ // Gets tables information
+ include_once './libraries/tbl_info.inc.php';
+
+ if (!isset($goto)) {
+ $goto = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ );
+ }
+ // Defines the url to return to in case of error in the next sql
+ // statement
+ $err_url = $goto . PMA_URL_getCommon(
+ array('db' => $this->db, 'table' => $this->table)
+ );
+
+ //Set default datalabel if not selected
+ if (!isset($_POST['zoom_submit']) || $_POST['dataLabel'] == '') {
+ $dataLabel = PMA_getDisplayField($this->db, $this->table);
+ } else {
+ $dataLabel = $_POST['dataLabel'];
+ }
+
+ // Displays the zoom search form
+ $this->response->addHTML(
+ Template::get('secondary_tabs')
+ ->render(
+ array(
+ 'url_params' => array(
+ 'db' => $this->db,
+ 'table' => $this->table,
+ ),
+ 'sub_tabs' => $this->_getSubTabs(),
+ )
+ )
+ );
+ $this->response->addHTML(
+ Template::get('table/search/selection_form')
+ ->render(
+ array(
+ 'searchType' => $this->_searchType,
+ 'db' => $this->db,
+ 'table' => $this->table,
+ 'goto' => $goto,
+ 'self' => $this,
+ 'geomColumnFlag' => $this->_geomColumnFlag,
+ 'columnNames' => $this->_columnNames,
+ 'columnTypes' => $this->_columnTypes,
+ 'columnCollations' => $this->_columnCollations,
+ 'dataLabel' => $dataLabel,
+ )
+ )
+ );
+
+ /*
+ * Handle the input criteria and generate the query result
+ * Form for displaying query results
+ */
+ if (isset($_POST['zoom_submit'])
+ && $_POST['criteriaColumnNames'][0] != 'pma_null'
+ && $_POST['criteriaColumnNames'][1] != 'pma_null'
+ && $_POST['criteriaColumnNames'][0] != $_POST['criteriaColumnNames'][1]
+ ) {
+ $this->zoomSubmitAction($dataLabel, $goto);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Zoom submit action
+ *
+ * @param string $dataLabel Data label
+ * @param string $goto Goto
+ *
+ * @return void
+ */
+ public function zoomSubmitAction($dataLabel, $goto)
+ {
+ //Query generation part
+ $sql_query = $this->_buildSqlQuery();
+ $sql_query .= ' LIMIT ' . $_POST['maxPlotLimit'];
+
+ //Query execution part
+ $result = $this->dbi->query(
+ $sql_query . ";", null, PMA_DatabaseInterface::QUERY_STORE
+ );
+ $fields_meta = $this->dbi->getFieldsMeta($result);
+ $data = array();
+ while ($row = $this->dbi->fetchAssoc($result)) {
+ //Need a row with indexes as 0,1,2 for the getUniqueCondition
+ // hence using a temporary array
+ $tmpRow = array();
+ foreach ($row as $val) {
+ $tmpRow[] = $val;
+ }
+ //Get unique condition on each row (will be needed for row update)
+ $uniqueCondition = PMA_Util::getUniqueCondition(
+ $result, // handle
+ count($this->_columnNames), // fields_cnt
+ $fields_meta, // fields_meta
+ $tmpRow, // row
+ true, // force_unique
+ false, // restrict_to_table
+ null // analyzed_sql_results
+ );
+ //Append it to row array as where_clause
+ $row['where_clause'] = $uniqueCondition[0];
+
+ $tmpData = array(
+ $_POST['criteriaColumnNames'][0] =>
+ $row[$_POST['criteriaColumnNames'][0]],
+ $_POST['criteriaColumnNames'][1] =>
+ $row[$_POST['criteriaColumnNames'][1]],
+ 'where_clause' => $uniqueCondition[0]
+ );
+ $tmpData[$dataLabel] = ($dataLabel) ? $row[$dataLabel] : '';
+ $data[] = $tmpData;
+ }
+ unset($tmpData);
+
+ //Displays form for point data and scatter plot
+ $titles = array(
+ 'Browse' => PMA_Util::getIcon(
+ 'b_browse.png',
+ __('Browse foreign values')
+ )
+ );
+ $this->response->addHTML(
+ Template::get('table/search/zoom_result_form')
+ ->render(
+ array(
+ '_db' => $this->db,
+ '_table' => $this->table,
+ '_columnNames' => $this->_columnNames,
+ '_foreigners' => $this->_foreigners,
+ '_columnNullFlags' => $this->_columnNullFlags,
+ '_columnTypes' => $this->_columnTypes,
+ 'titles' => $titles,
+ 'goto' => $goto,
+ 'data' => $data,
+ )
+ )
+ );
+ }
+
+ /**
+ * Change table info action
+ *
+ * @return void
+ */
+ public function changeTableInfoAction()
+ {
+ $field = $_REQUEST['field'];
+ if ($field == 'pma_null') {
+ $this->response->addJSON('field_type', '');
+ $this->response->addJSON('field_collation', '');
+ $this->response->addJSON('field_operators', '');
+ $this->response->addJSON('field_value', '');
+ return;
+ }
+ $key = array_search($field, $this->_columnNames);
+ $properties = $this->getColumnProperties($_REQUEST['it'], $key);
+ $this->response->addJSON(
+ 'field_type', htmlspecialchars($properties['type'])
+ );
+ $this->response->addJSON('field_collation', $properties['collation']);
+ $this->response->addJSON('field_operators', $properties['func']);
+ $this->response->addJSON('field_value', $properties['value']);
+ }
+
+ /**
+ * Get data row action
+ *
+ * @return void
+ */
+ public function getDataRowAction()
+ {
+ $extra_data = array();
+ $row_info_query = 'SELECT * FROM `' . $_REQUEST['db'] . '`.`'
+ . $_REQUEST['table'] . '` WHERE ' . $_REQUEST['where_clause'];
+ $result = $this->dbi->query(
+ $row_info_query . ";", null, PMA_DatabaseInterface::QUERY_STORE
+ );
+ $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') {
+ $row[$col] = PMA_Util::printableBitValue(
+ $val, $fields_meta[$i]->length
+ );
+ }
+ $i++;
+ }
+ $extra_data['row_info'] = $row;
+ }
+ $this->response->addJSON($extra_data);
+ }
+
+ /**
+ * Do selection action
+ *
+ * @return void
+ */
+ public function doSelectionAction()
+ {
+ /**
+ * Selection criteria have been submitted -> do the work
+ */
+ $sql_query = $this->_buildSqlQuery();
+
+ /**
+ * Add this to ensure following procedures included running correctly.
+ */
+ $db = $this->db;
+ $table = $this->table;
+ /**
+ * Parse and analyze the query
+ */
+ include_once 'libraries/parse_analyze.inc.php';
+
+ PMA_executeQueryAndSendQueryResponse(
+ $analyzed_sql_results, // analyzed_sql_results
+ false, // is_gotofile
+ $this->db, // db
+ $this->table, // table
+ null, // find_real_end
+ null, // sql_query_for_bookmark
+ null, // extra_data
+ null, // message_to_show
+ null, // message
+ null, // sql_data
+ $GLOBALS['goto'], // goto
+ $GLOBALS['pmaThemeImage'], // pmaThemeImage
+ null, // disp_query
+ null, // disp_message
+ null, // query_type
+ $sql_query, // sql_query
+ null, // selectedTables
+ null // complete_query
+ );
+ }
+
+ /**
+ * Display selection form action
+ *
+ * @return void
+ */
+ public function displaySelectionFormAction()
+ {
+ //$err_url = 'tbl_select.php' . $err_url;
+ $this->url_query .= '&amp;goto=tbl_select.php&amp;back=tbl_select.php';
+
+ include_once 'libraries/tbl_info.inc.php';
+ if (! isset($goto)) {
+ $goto = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ );
+ }
+ // Defines the url to return to in case of error in the next sql statement
+ $err_url = $goto . PMA_URL_getCommon(
+ array('db' => $this->db, 'table' => $this->table)
+ );
+ // Displays the table search form
+ $this->response->addHTML(
+ Template::get('secondary_tabs')
+ ->render(
+ array(
+ 'url_params' => array(
+ 'db' => $this->db,
+ 'table' => $this->table,
+ ),
+ 'sub_tabs' => $this->_getSubTabs(),
+ )
+ )
+ );
+ $this->response->addHTML(
+ Template::get('table/search/selection_form')
+ ->render(
+ array(
+ 'searchType' => $this->_searchType,
+ 'db' => $this->db,
+ 'table' => $this->table,
+ 'goto' => $goto,
+ 'self' => $this,
+ 'geomColumnFlag' => $this->_geomColumnFlag,
+ 'columnNames' => $this->_columnNames,
+ 'columnTypes' => $this->_columnTypes,
+ 'columnCollations' => $this->_columnCollations,
+ 'dataLabel' => null,
+ )
+ )
+ );
+ }
+
+ /**
+ * Range search action
+ *
+ * @return void
+ */
+ public function rangeSearchAction()
+ {
+ $min_max = $this->getColumnMinMax($_REQUEST['column']);
+ $this->response->addJSON('column_data', $min_max);
+ }
+
+ /**
+ * Find action
+ *
+ * @return void
+ */
+ public function findAction()
+ {
+ $preview = $this->getReplacePreview(
+ $_POST['columnIndex'],
+ $_POST['find'],
+ $_POST['replaceWith'],
+ $_POST['useRegex'],
+ $this->_connectionCharSet
+ );
+ $this->response->addJSON('preview', $preview);
+ }
+
+ /**
+ * Replace action
+ *
+ * @return void
+ */
+ public function replaceAction()
+ {
+ $this->replace(
+ $_POST['columnIndex'],
+ $_POST['findString'],
+ $_POST['replaceWith'],
+ $_POST['useRegex'],
+ $this->_connectionCharSet
+ );
+ $this->response->addHTML(
+ PMA_Util::getMessage(
+ __('Your SQL query has been executed successfully.'),
+ null, 'success'
+ )
+ );
+ }
+
+ /**
+ * Returns HTML for previewing strings found and their replacements
+ *
+ * @param int $columnIndex index of the column
+ * @param string $find string to find in the column
+ * @param string $replaceWith string to replace with
+ * @param boolean $useRegex to use Regex replace or not
+ * @param string $charSet character set of the connection
+ *
+ * @return string HTML for previewing strings found and their replacements
+ */
+ function getReplacePreview(
+ $columnIndex, $find, $replaceWith, $useRegex, $charSet
+ ) {
+ $column = $this->_columnNames[$columnIndex];
+ if ($useRegex) {
+ $result = $this->_getRegexReplaceRows(
+ $columnIndex, $find, $replaceWith, $charSet
+ );
+ } else {
+ $sql_query = "SELECT "
+ . PMA_Util::backquote($column) . ","
+ . " REPLACE("
+ . PMA_Util::backquote($column) . ", '" . $find . "', '"
+ . $replaceWith
+ . "'),"
+ . " COUNT(*)"
+ . " FROM " . PMA_Util::backquote($this->db)
+ . "." . PMA_Util::backquote($this->table)
+ . " WHERE " . PMA_Util::backquote($column)
+ . " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
+ // change the collation of the 2nd operand to a case sensitive
+ // binary collation to make sure that the comparison
+ // is case sensitive
+ $sql_query .= " GROUP BY " . PMA_Util::backquote($column)
+ . " ORDER BY " . PMA_Util::backquote($column) . " ASC";
+
+ $result = $this->dbi->fetchResult($sql_query, 0);
+ }
+
+ return Template::get('table/search/replace_preview')->render(
+ array(
+ 'db' => $this->db,
+ 'table' => $this->table,
+ 'columnIndex' => $columnIndex,
+ 'find' => $find,
+ 'replaceWith' => $replaceWith,
+ 'useRegex' => $useRegex,
+ 'result' => $result
+ )
+ );
+ }
+
+ /**
+ * Finds and returns Regex pattern and their replacements
+ *
+ * @param int $columnIndex index of the column
+ * @param string $find string to find in the column
+ * @param string $replaceWith string to replace with
+ * @param string $charSet character set of the connection
+ *
+ * @return array Array containing original values, replaced values and count
+ */
+ private function _getRegexReplaceRows(
+ $columnIndex, $find, $replaceWith, $charSet
+ ) {
+ $column = $this->_columnNames[$columnIndex];
+ $sql_query = "SELECT "
+ . PMA_Util::backquote($column) . ","
+ . " 1," // to add an extra column that will have replaced value
+ . " COUNT(*)"
+ . " FROM " . PMA_Util::backquote($this->db)
+ . "." . PMA_Util::backquote($this->table)
+ . " WHERE " . PMA_Util::backquote($column)
+ . " RLIKE '" . PMA_Util::sqlAddSlashes($find) . "' COLLATE "
+ . $charSet . "_bin"; // here we
+ // change the collation of the 2nd operand to a case sensitive
+ // binary collation to make sure that the comparison is case sensitive
+ $sql_query .= " GROUP BY " . PMA_Util::backquote($column)
+ . " ORDER BY " . PMA_Util::backquote($column) . " ASC";
+
+ $result = $this->dbi->fetchResult($sql_query, 0);
+
+ if (is_array($result)) {
+ foreach ($result as $index=>$row) {
+ $result[$index][1] = preg_replace(
+ "/" . $find . "/",
+ $replaceWith,
+ $row[0]
+ );
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Replaces a given string in a column with a give replacement
+ *
+ * @param int $columnIndex index of the column
+ * @param string $find string to find in the column
+ * @param string $replaceWith string to replace with
+ * @param boolean $useRegex to use Regex replace or not
+ * @param string $charSet character set of the connection
+ *
+ * @return void
+ */
+ public function replace($columnIndex, $find, $replaceWith, $useRegex,
+ $charSet
+ ) {
+ $column = $this->_columnNames[$columnIndex];
+ if ($useRegex) {
+ $toReplace = $this->_getRegexReplaceRows(
+ $columnIndex, $find, $replaceWith, $charSet
+ );
+ $sql_query = "UPDATE " . PMA_Util::backquote($this->table)
+ . " SET " . PMA_Util::backquote($column) . " = CASE";
+ if (is_array($toReplace)) {
+ foreach ($toReplace as $row) {
+ $sql_query .= "\n WHEN " . PMA_Util::backquote($column)
+ . " = '" . PMA_Util::sqlAddSlashes($row[0])
+ . "' THEN '" . PMA_Util::sqlAddSlashes($row[1]) . "'";
+ }
+ }
+ $sql_query .= " END"
+ . " WHERE " . PMA_Util::backquote($column)
+ . " RLIKE '" . PMA_Util::sqlAddSlashes($find) . "' COLLATE "
+ . $charSet . "_bin"; // here we
+ // change the collation of the 2nd operand to a case sensitive
+ // binary collation to make sure that the comparison
+ // is case sensitive
+ } else {
+ $sql_query = "UPDATE " . PMA_Util::backquote($this->table)
+ . " SET " . PMA_Util::backquote($column) . " ="
+ . " REPLACE("
+ . PMA_Util::backquote($column) . ", '" . $find . "', '"
+ . $replaceWith
+ . "')"
+ . " WHERE " . PMA_Util::backquote($column)
+ . " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
+ // change the collation of the 2nd operand to a case sensitive
+ // binary collation to make sure that the comparison
+ // is case sensitive
+ }
+ $this->dbi->query(
+ $sql_query, null, PMA_DatabaseInterface::QUERY_STORE
+ );
+ $GLOBALS['sql_query'] = $sql_query;
+ }
+
+ /**
+ * Finds minimum and maximum value of a given column.
+ *
+ * @param string $column Column name
+ *
+ * @return array
+ */
+ public function getColumnMinMax($column)
+ {
+ $sql_query = 'SELECT MIN(' . PMA_Util::backquote($column) . ') AS `min`, '
+ . 'MAX(' . PMA_Util::backquote($column) . ') AS `max` '
+ . 'FROM ' . PMA_Util::backquote($this->db) . '.'
+ . PMA_Util::backquote($this->table);
+
+ $result = $this->dbi->fetchSingleRow($sql_query);
+
+ return $result;
+ }
+
+ /**
+ * Returns an array with necessary configurations to create
+ * sub-tabs in the table_select page.
+ *
+ * @return array Array containing configuration (icon, text, link, id, args)
+ * of sub-tabs
+ */
+ private function _getSubTabs()
+ {
+ $subtabs = array();
+ $subtabs['search']['icon'] = 'b_search.png';
+ $subtabs['search']['text'] = __('Table search');
+ $subtabs['search']['link'] = 'tbl_select.php';
+ $subtabs['search']['id'] = 'tbl_search_id';
+ $subtabs['search']['args']['pos'] = 0;
+
+ $subtabs['zoom']['icon'] = 'b_select.png';
+ $subtabs['zoom']['link'] = 'tbl_zoom_select.php';
+ $subtabs['zoom']['text'] = __('Zoom search');
+ $subtabs['zoom']['id'] = 'zoom_search_id';
+
+ $subtabs['replace']['icon'] = 'b_find_replace.png';
+ $subtabs['replace']['link'] = 'tbl_find_replace.php';
+ $subtabs['replace']['text'] = __('Find and replace');
+ $subtabs['replace']['id'] = 'find_replace_id';
+
+ return $subtabs;
+ }
+
+ /**
+ * Builds the sql search query from the post parameters
+ *
+ * @return string the generated SQL query
+ */
+ private function _buildSqlQuery()
+ {
+ $sql_query = 'SELECT ';
+
+ // If only distinct values are needed
+ $is_distinct = (isset($_POST['distinct'])) ? 'true' : 'false';
+ if ($is_distinct == 'true') {
+ $sql_query .= 'DISTINCT ';
+ }
+
+ // if all column names were selected to display, we do a 'SELECT *'
+ // (more efficient and this helps prevent a problem in IE
+ // if one of the rows is edited and we come back to the Select results)
+ if (isset($_POST['zoom_submit']) || ! empty($_POST['displayAllColumns'])) {
+ $sql_query .= '* ';
+ } else {
+ $sql_query .= implode(
+ ', ',
+ PMA_Util::backquote($_POST['columnsToDisplay'])
+ );
+ } // end if
+
+ $sql_query .= ' FROM '
+ . PMA_Util::backquote($_POST['table']);
+ $whereClause = $this->_generateWhereClause();
+ $sql_query .= $whereClause;
+
+ // if the search results are to be ordered
+ if (isset($_POST['orderByColumn']) && $_POST['orderByColumn'] != '--nil--') {
+ $sql_query .= ' ORDER BY '
+ . PMA_Util::backquote($_POST['orderByColumn'])
+ . ' ' . $_POST['order'];
+ } // end if
+ return $sql_query;
+ }
+
+ /**
+ * Provides a column's type, collation, operators list, and criteria value
+ * to display in table search form
+ *
+ * @param integer $search_index Row number in table search form
+ * @param integer $column_index Column index in ColumnNames array
+ *
+ * @return array Array containing column's properties
+ */
+ public function getColumnProperties($search_index, $column_index)
+ {
+ $selected_operator = (isset($_POST['criteriaColumnOperators'])
+ ? $_POST['criteriaColumnOperators'][$search_index] : '');
+ $entered_value = (isset($_POST['criteriaValues'])
+ ? $_POST['criteriaValues'] : '');
+ $titles = array(
+ 'Browse' => PMA_Util::getIcon(
+ 'b_browse.png', __('Browse foreign values')
+ )
+ );
+ //Gets column's type and collation
+ $type = $this->_columnTypes[$column_index];
+ $collation = $this->_columnCollations[$column_index];
+ //Gets column's comparison operators depending on column type
+ $func = Template::get('table/search/column_comparison_operators')->render(
+ array(
+ 'search_index' => $search_index,
+ 'columnTypes' => $this->_columnTypes,
+ 'column_index' => $column_index,
+ 'columnNullFlags' => $this->_columnNullFlags,
+ 'selected_operator' => $selected_operator
+ )
+ );
+ //Gets link to browse foreign data(if any) and criteria inputbox
+ $foreignData = PMA_getForeignData(
+ $this->_foreigners, $this->_columnNames[$column_index], false, '', ''
+ );
+ $value = Template::get('table/search/input_box')->render(
+ array(
+ 'str' => '',
+ 'column_type' => (string) $type,
+ 'column_id' => 'fieldID_',
+ 'in_zoom_search_edit' => false,
+ '_foreigners' => $this->_foreigners,
+ 'column_name' => $this->_columnNames[$column_index],
+ 'foreignData' => $foreignData,
+ 'table' => $this->table,
+ 'column_index' => $search_index,
+ 'foreignMaxLimit' => $GLOBALS['cfg']['ForeignKeyMaxLimit'],
+ 'criteriaValues' => $entered_value,
+ 'db' => $this->db,
+ 'titles' => $titles,
+ 'in_fbs' => true
+ )
+ );
+ return array(
+ 'type' => $type,
+ 'collation' => $collation,
+ 'func' => $func,
+ 'value' => $value
+ );
+ }
+
+ /**
+ * Generates the where clause for the SQL search query to be executed
+ *
+ * @return string the generated where clause
+ */
+ private function _generateWhereClause()
+ {
+ if (isset($_POST['customWhereClause'])
+ && trim($_POST['customWhereClause']) != ''
+ ) {
+ return ' WHERE ' . $_POST['customWhereClause'];
+ }
+
+ // If there are no search criteria set or no unary criteria operators,
+ // return
+ if (! isset($_POST['criteriaValues'])
+ && ! isset($_POST['criteriaColumnOperators'])
+ && ! isset($_POST['geom_func'])
+ ) {
+ return '';
+ }
+
+ // else continue to form the where clause from column criteria values
+ $fullWhereClause = array();
+ reset($_POST['criteriaColumnOperators']);
+ while (list($column_index, $operator) = each(
+ $_POST['criteriaColumnOperators']
+ )) {
+
+ $unaryFlag = $GLOBALS['PMA_Types']->isUnaryOperator($operator);
+ $tmp_geom_func = isset($_POST['geom_func'][$column_index])
+ ? $_POST['geom_func'][$column_index] : null;
+
+ $whereClause = $this->_getWhereClause(
+ $_POST['criteriaValues'][$column_index],
+ $_POST['criteriaColumnNames'][$column_index],
+ $_POST['criteriaColumnTypes'][$column_index],
+ $operator,
+ $unaryFlag,
+ $tmp_geom_func
+ );
+
+ if ($whereClause) {
+ $fullWhereClause[] = $whereClause;
+ }
+ } // end while
+
+ if (!empty($fullWhereClause)) {
+ return ' WHERE ' . implode(' AND ', $fullWhereClause);
+ }
+ return '';
+ }
+
+ /**
+ * Return the where clause in case column's type is ENUM.
+ *
+ * @param mixed $criteriaValues Search criteria input
+ * @param string $func_type Search function/operator
+ *
+ * @return string part of where clause.
+ */
+ private function _getEnumWhereClause($criteriaValues, $func_type)
+ {
+ if (! is_array($criteriaValues)) {
+ $criteriaValues = explode(',', $criteriaValues);
+ }
+ $enum_selected_count = count($criteriaValues);
+ if ($func_type == '=' && $enum_selected_count > 1) {
+ $func_type = 'IN';
+ $parens_open = '(';
+ $parens_close = ')';
+
+ } elseif ($func_type == '!=' && $enum_selected_count > 1) {
+ $func_type = 'NOT IN';
+ $parens_open = '(';
+ $parens_close = ')';
+
+ } else {
+ $parens_open = '';
+ $parens_close = '';
+ }
+ $enum_where = '\''
+ . PMA_Util::sqlAddSlashes($criteriaValues[0]) . '\'';
+ for ($e = 1; $e < $enum_selected_count; $e++) {
+ $enum_where .= ', \''
+ . PMA_Util::sqlAddSlashes($criteriaValues[$e]) . '\'';
+ }
+
+ return ' ' . $func_type . ' ' . $parens_open
+ . $enum_where . $parens_close;
+ }
+
+ /**
+ * Return the where clause for a geometrical column.
+ *
+ * @param mixed $criteriaValues Search criteria input
+ * @param string $names Name of the column on which search is submitted
+ * @param string $func_type Search function/operator
+ * @param string $types Type of the field
+ * @param bool $geom_func Whether geometry functions should be applied
+ *
+ * @return string part of where clause.
+ */
+ private function _getGeomWhereClause($criteriaValues, $names,
+ $func_type, $types, $geom_func = null
+ ) {
+ $geom_unary_functions = array(
+ 'IsEmpty' => 1,
+ 'IsSimple' => 1,
+ 'IsRing' => 1,
+ 'IsClosed' => 1,
+ );
+ $where = '';
+
+ // Get details about the geometry functions
+ $geom_funcs = PMA_Util::getGISFunctions($types, true, false);
+
+ // If the function takes multiple parameters
+ if ($geom_funcs[$geom_func]['params'] > 1) {
+ // create gis data from the criteria input
+ $gis_data = PMA_Util::createGISData($criteriaValues);
+ $where = $geom_func . '(' . PMA_Util::backquote($names)
+ . ', ' . $gis_data . ')';
+ return $where;
+ }
+
+ // New output type is the output type of the function being applied
+ $type = $geom_funcs[$geom_func]['type'];
+ $geom_function_applied = $geom_func
+ . '(' . PMA_Util::backquote($names) . ')';
+
+ // If the where clause is something like 'IsEmpty(`spatial_col_name`)'
+ if (isset($geom_unary_functions[$geom_func])
+ && trim($criteriaValues) == ''
+ ) {
+ $where = $geom_function_applied;
+
+ } elseif (in_array($type, PMA_Util::getGISDatatypes())
+ && ! empty($criteriaValues)
+ ) {
+ // create gis data from the criteria input
+ $gis_data = PMA_Util::createGISData($criteriaValues);
+ $where = $geom_function_applied . " " . $func_type . " " . $gis_data;
+
+ } elseif (/*overload*/mb_strlen($criteriaValues) > 0) {
+ $where = $geom_function_applied . " "
+ . $func_type . " '" . $criteriaValues . "'";
+ }
+ return $where;
+ }
+
+ /**
+ * Return the where clause for query generation based on the inputs provided.
+ *
+ * @param mixed $criteriaValues Search criteria input
+ * @param string $names Name of the column on which search is submitted
+ * @param string $types Type of the field
+ * @param string $func_type Search function/operator
+ * @param bool $unaryFlag Whether operator unary or not
+ * @param bool $geom_func Whether geometry functions should be applied
+ *
+ * @return string generated where clause.
+ */
+ private function _getWhereClause($criteriaValues, $names, $types,
+ $func_type, $unaryFlag, $geom_func = null
+ ) {
+ // If geometry function is set
+ if (! empty($geom_func)) {
+ return $this->_getGeomWhereClause(
+ $criteriaValues, $names, $func_type, $types, $geom_func
+ );
+ }
+
+ $backquoted_name = PMA_Util::backquote($names);
+ $where = '';
+ if ($unaryFlag) {
+ $where = $backquoted_name . ' ' . $func_type;
+
+ } elseif (strncasecmp($types, 'enum', 4) == 0 && ! empty($criteriaValues)) {
+ $where = $backquoted_name;
+ $where .= $this->_getEnumWhereClause($criteriaValues, $func_type);
+
+ } elseif ($criteriaValues != '') {
+ // For these types we quote the value. Even if it's another type
+ // (like INT), for a LIKE we always quote the value. MySQL converts
+ // strings to numbers and numbers to strings as necessary
+ // during the comparison
+ if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types)
+ || /*overload*/mb_strpos(' ' . $func_type, 'LIKE')
+ ) {
+ $quot = '\'';
+ } else {
+ $quot = '';
+ }
+
+ // LIKE %...%
+ if ($func_type == 'LIKE %...%') {
+ $func_type = 'LIKE';
+ $criteriaValues = '%' . $criteriaValues . '%';
+ }
+ if ($func_type == 'REGEXP ^...$') {
+ $func_type = 'REGEXP';
+ $criteriaValues = '^' . $criteriaValues . '$';
+ }
+
+ if ('IN (...)' != $func_type
+ && 'NOT IN (...)' != $func_type
+ && 'BETWEEN' != $func_type
+ && 'NOT BETWEEN' != $func_type
+ ) {
+ if ($func_type == 'LIKE %...%' || $func_type == 'LIKE') {
+ $where = $backquoted_name . ' ' . $func_type . ' ' . $quot
+ . PMA_Util::sqlAddSlashes($criteriaValues, true) . $quot;
+ } else {
+ $where = $backquoted_name . ' ' . $func_type . ' ' . $quot
+ . PMA_Util::sqlAddSlashes($criteriaValues) . $quot;
+ }
+ return $where;
+ }
+ $func_type = str_replace(' (...)', '', $func_type);
+
+ //Don't explode if this is already an array
+ //(Case for (NOT) IN/BETWEEN.)
+ if (is_array($criteriaValues)) {
+ $values = $criteriaValues;
+ } else {
+ $values = explode(',', $criteriaValues);
+ }
+ // quote values one by one
+ $emptyKey = false;
+ foreach ($values as $key => &$value) {
+ if ('' === $value) {
+ $emptyKey = $key;
+ $value = 'NULL';
+ continue;
+ }
+ $value = $quot . PMA_Util::sqlAddSlashes(trim($value))
+ . $quot;
+ }
+
+ if ('BETWEEN' == $func_type || 'NOT BETWEEN' == $func_type) {
+ $where = $backquoted_name . ' ' . $func_type . ' '
+ . (isset($values[0]) ? $values[0] : '')
+ . ' AND ' . (isset($values[1]) ? $values[1] : '');
+ } else { //[NOT] IN
+ if (false !== $emptyKey) {
+ unset($values[$emptyKey]);
+ }
+ $wheres = array();
+ if (!empty($values)) {
+ $wheres[] = $backquoted_name . ' ' . $func_type
+ . ' (' . implode(',', $values) . ')';
+ }
+ if (false !== $emptyKey) {
+ $wheres[] = $backquoted_name . ' IS NULL';
+ }
+ $where = implode(' OR ', $wheres);
+ if (1 < count($wheres)) {
+ $where = '(' . $where . ')';
+ }
+ }
+ } // end if
+
+ return $where;
+ }
+}
diff --git a/libraries/controllers/TableStructureController.class.php b/libraries/controllers/TableStructureController.class.php
new file mode 100644
index 0000000000..c91415302f
--- /dev/null
+++ b/libraries/controllers/TableStructureController.class.php
@@ -0,0 +1,1252 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+
+/**
+ * Holds the PMA\TableStructureController
+ *
+ * @package PMA
+ */
+
+namespace PMA\Controllers;
+
+use PMA\Template;
+use PMA_Index;
+use PMA_Partition;
+use PMA_Table;
+use PMA_Message;
+use PMA_PageSettings;
+use PMA_Util;
+use PMA\Util;
+use SqlParser;
+
+require_once 'libraries/Index.class.php';
+require_once 'libraries/Partition.class.php';
+require_once 'libraries/mysql_charsets.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+require_once 'libraries/transformations.lib.php';
+require_once 'libraries/Template.class.php';
+require_once 'libraries/util.lib.php';
+require_once 'libraries/controllers/TableController.class.php';
+
+/**
+ * Handles table structure logic
+ *
+ * @package PhpMyAdmin
+ */
+class TableStructureController extends TableController
+{
+ /**
+ * @var PMA_Table The table object
+ */
+ protected $_table_obj;
+ /**
+ * @var string The URL query string
+ */
+ protected $_url_query;
+ /**
+ * @var bool DB is information_schema
+ */
+ protected $_db_is_system_schema;
+ /**
+ * @var bool Table is a view
+ */
+ protected $_tbl_is_view;
+ /**
+ * @var string Table storage engine
+ */
+ protected $_tbl_storage_engine;
+ /**
+ * @var int Number of rows
+ */
+ protected $_table_info_num_rows;
+ /**
+ * @var string Table collation
+ */
+ protected $_tbl_collation;
+ /**
+ * @var array Show table info
+ */
+ protected $_showtable;
+
+ /**
+ * TableStructureController constructor
+ *
+ * @param string $type Indicate the db_structure or tbl_structure
+ * @param string $db DB name
+ * @param string $table Table name
+ * @param string $url_query URL query
+ * @param int $num_tables Number of tables
+ * @param int $pos Current position in the list
+ * @param bool $db_is_system_schema DB is information_schema
+ * @param int $total_num_tables Number of tables
+ * @param array $tables Tables in the DB
+ * @param bool $is_show_stats Whether stats show or not
+ * @param bool $tbl_is_view Table is a view
+ * @param string $tbl_storage_engine Table storage engine
+ * @param int $table_info_num_rows Number of rows
+ * @param string $tbl_collation Table collation
+ * @param array $showtable Show table info
+ */
+ public function __construct(
+ $type, $db, $table, $url_query, $num_tables, $pos, $db_is_system_schema,
+ $total_num_tables, $tables, $is_show_stats, $tbl_is_view,
+ $tbl_storage_engine, $table_info_num_rows, $tbl_collation, $showtable
+ ) {
+ parent::__construct();
+
+ $this->_db_is_system_schema = $db_is_system_schema;
+ $this->_url_query = $url_query;
+ $this->_tbl_is_view = $tbl_is_view;
+ $this->_tbl_storage_engine = $tbl_storage_engine;
+ $this->_table_info_num_rows = $table_info_num_rows;
+ $this->_tbl_collation = $tbl_collation;
+ $this->_showtable = $showtable;
+ $this->table_obj = $this->dbi->getTable($this->db, $this->table);
+ }
+
+ /**
+ * Index action
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ PMA_PageSettings::showGroup('TableStructure');
+
+ /**
+ * Function implementations for this script
+ */
+ include_once 'libraries/check_user_privileges.lib.php';
+ include_once 'libraries/index.lib.php';
+ include_once 'libraries/sql.lib.php';
+ include_once 'libraries/bookmark.lib.php';
+
+ $this->response->getHeader()->getScripts()->addFiles(
+ array(
+ 'tbl_structure.js',
+ 'indexes.js'
+ )
+ );
+
+ /**
+ * Handle column moving
+ */
+ if (isset($_REQUEST['move_columns'])
+ && is_array($_REQUEST['move_columns'])
+ && $this->response->isAjax()
+ ) {
+ $this->moveColumns();
+ return;
+ }
+
+ /**
+ * handle MySQL reserved words columns check
+ */
+ if (isset($_REQUEST['reserved_word_check'])) {
+ if ($GLOBALS['cfg']['ReservedWordDisableWarning'] === false) {
+ $columns_names = $_REQUEST['field_name'];
+ $reserved_keywords_names = array();
+ foreach ($columns_names as $column) {
+ if (SqlParser\Context::isKeyword(trim($column), true)) {
+ $reserved_keywords_names[] = trim($column);
+ }
+ }
+ if (SqlParser\Context::isKeyword(trim($this->table), true)) {
+ $reserved_keywords_names[] = trim($this->table);
+ }
+ if (count($reserved_keywords_names) == 0) {
+ $this->response->isSuccess(false);
+ }
+ $this->response->addJSON(
+ 'message', sprintf(
+ _ngettext(
+ 'The name \'%s\' is a MySQL reserved keyword.',
+ 'The names \'%s\' are MySQL reserved keywords.',
+ count($reserved_keywords_names)
+ ),
+ implode(',', $reserved_keywords_names)
+ )
+ );
+ } else {
+ $this->response->isSuccess(false);
+ }
+ return;
+ }
+ /**
+ * A click on Change has been made for one column
+ */
+ if (isset($_REQUEST['change_column'])) {
+ $this->displayHtmlForColumnChange(null, 'tbl_structure.php');
+ return;
+ }
+
+ /**
+ * handle multiple field commands if required
+ *
+ * submit_mult_*_x comes from IE if <input type="img" ...> is used
+ */
+ $submit_mult = $this->getMultipleFieldCommandType();
+
+ if (! empty($submit_mult)) {
+ if (isset($_REQUEST['selected_fld'])) {
+ if ($submit_mult == 'browse') {
+ // browsing the table displaying only selected columns
+ $this->displayTableBrowseForSelectedColumns(
+ $GLOBALS['goto'], $GLOBALS['pmaThemeImage']
+ );
+ } else {
+ // handle multiple field commands
+ // handle confirmation of deleting multiple columns
+ $action = 'tbl_structure.php';
+ $GLOBALS['selected'] = $_REQUEST['selected_fld'];
+ list(
+ $what_ret, $query_type_ret, $is_unset_submit_mult,
+ $mult_btn_ret, $centralColsError
+ )
+ = $this->getDataForSubmitMult(
+ $submit_mult, $_REQUEST['selected_fld'], $action
+ );
+ //update the existing variables
+ // todo: refactor mult_submits.inc.php such as
+ // below globals are not needed anymore
+ if (isset($what_ret)) {
+ $GLOBALS['what'] = $what_ret;
+ global $what;
+ }
+ if (isset($query_type_ret)) {
+ $GLOBALS['query_type'] = $query_type_ret;
+ global $query_type;
+ }
+ if ($is_unset_submit_mult) {
+ unset($submit_mult);
+ }
+ if (isset($mult_btn_ret)) {
+ $GLOBALS['mult_btn'] = $mult_btn_ret;
+ global $mult_btn;
+ }
+ include 'libraries/mult_submits.inc.php';
+ /**
+ * if $submit_mult == 'change', execution will have stopped
+ * at this point
+ */
+ if (empty($message)) {
+ $message = PMA_Message::success();
+ }
+ $this->response->addHTML(
+ PMA_Util::getMessage($message, $sql_query)
+ );
+ }
+ } else {
+ $this->response->isSuccess(false);
+ $this->response->addJSON('message', __('No column selected.'));
+ }
+ }
+
+ // display secondary level tabs if necessary
+ $engine = $this->table_obj->getStatusInfo('ENGINE');
+ $this->response->addHTML(
+ Template::get('table/secondary_tabs')->render(
+ array(
+ 'url_params' => array(
+ 'db' => $this->db,
+ 'table' => $this->table
+ ),
+ 'engine' => $engine
+ )
+ )
+ );
+ $this->response->addHTML('<div id="structure_content">');
+
+ /**
+ * Modifications have been submitted -> updates the table
+ */
+ if (isset($_REQUEST['do_save_data'])) {
+ $regenerate = $this->updateColumns();
+ if ($regenerate) {
+ // This happens when updating failed
+ // @todo: do something appropriate
+ } else {
+ // continue to show the table's structure
+ unset($_REQUEST['selected']);
+ }
+ }
+
+ /**
+ * Adding indexes
+ */
+ if (isset($_REQUEST['add_key'])
+ || isset($_REQUEST['partition_maintenance'])
+ ) {
+ //todo: set some variables for sql.php include, to be eliminated
+ //after refactoring sql.php
+ $db = $this->db;
+ $table = $this->table;
+ $cfg = $GLOBALS['cfg'];
+ $is_superuser = $GLOBALS['dbi']->isSuperuser();
+ $pmaThemeImage = $GLOBALS['pmaThemeImage'];
+ include 'sql.php';
+ $GLOBALS['reload'] = true;
+ }
+
+ /**
+ * Gets the relation settings
+ */
+ $cfgRelation = PMA_getRelationsParam();
+
+ /**
+ * Runs common work
+ */
+ // set db, table references, for require_once that follows
+ // got to be eliminated in long run
+ $db = &$this->db;
+ $table = &$this->table;
+ include_once 'libraries/tbl_common.inc.php';
+ $this->_url_query = $url_query
+ . '&amp;goto=tbl_structure.php&amp;back=tbl_structure.php';
+ $url_params['goto'] = 'tbl_structure.php';
+ $url_params['back'] = 'tbl_structure.php';
+
+ /**
+ * Gets tables information
+ */
+ include_once 'libraries/tbl_info.inc.php';
+
+ include_once 'libraries/Index.class.php';
+
+ // 2. Gets table keys and retains them
+ // @todo should be: $server->db($db)->table($table)->primary()
+ $primary = PMA_Index::getPrimary($this->table, $this->db);
+ $columns_with_index = $this->dbi
+ ->getTable($this->db, $this->table)
+ ->getColumnsWithIndex(
+ PMA_Index::UNIQUE | PMA_Index::INDEX | PMA_Index::SPATIAL
+ | PMA_Index::FULLTEXT
+ );
+ $columns_with_unique_index = $this->dbi
+ ->getTable($this->db, $this->table)
+ ->getColumnsWithIndex(PMA_Index::UNIQUE);
+
+ // 3. Get fields
+ $fields = (array)$this->dbi->getColumns(
+ $this->db, $this->table, null, true
+ );
+
+ // Get more complete field information
+ // For now, this is done just for MySQL 4.1.2+ new TIMESTAMP options
+ // but later, if the analyser returns more information, it
+ // could be executed for any MySQL version and replace
+ // the info given by SHOW FULL COLUMNS FROM.
+ //
+ // We also need this to correctly learn if a TIMESTAMP is NOT NULL, since
+ // SHOW FULL COLUMNS or INFORMATION_SCHEMA incorrectly says NULL
+ // and SHOW CREATE TABLE says NOT NULL (tested
+ // in MySQL 4.0.25 and 5.0.21, http://bugs.mysql.com/20910).
+
+ $show_create_table = $this->table_obj->showCreate();
+ $parser = new SqlParser\Parser($show_create_table);
+
+ /**
+ * @var CreateStatement $stmt
+ */
+ $stmt = $parser->statements[0];
+
+ $create_table_fields = SqlParser\Utils\Table::getFields($stmt);
+
+ //display table structure
+ $this->response->addHTML(
+ $this->displayStructure(
+ $cfgRelation, $columns_with_unique_index, $url_params, $primary,
+ $fields, $columns_with_index, $create_table_fields
+ )
+ );
+
+ $this->response->addHTML('</div>');
+ }
+
+ /**
+ * Moves columns in the table's structure based on $_REQUEST
+ *
+ * @return void
+ */
+ protected function moveColumns()
+ {
+ $this->dbi->selectDb($this->db);
+
+ /*
+ * load the definitions for all columns
+ */
+ $columns = $this->dbi->getColumnsFull($this->db, $this->table);
+ $column_names = array_keys($columns);
+ $changes = array();
+
+ // move columns from first to last
+ for ($i = 0, $l = count($_REQUEST['move_columns']); $i < $l; $i++) {
+ $column = $_REQUEST['move_columns'][$i];
+ // is this column already correctly placed?
+ if ($column_names[$i] == $column) {
+ continue;
+ }
+
+ // it is not, let's move it to index $i
+ $data = $columns[$column];
+ $extracted_columnspec = PMA_Util::extractColumnSpec($data['Type']);
+ if (isset($data['Extra'])
+ && $data['Extra'] == 'on update CURRENT_TIMESTAMP'
+ ) {
+ $extracted_columnspec['attribute'] = $data['Extra'];
+ unset($data['Extra']);
+ }
+ $current_timestamp = ($data['Type'] == 'timestamp'
+ || $data['Type'] == 'datetime')
+ && $data['Default'] == 'CURRENT_TIMESTAMP';
+
+ if ($data['Null'] === 'YES' && $data['Default'] === null) {
+ $default_type = 'NULL';
+ } elseif ($current_timestamp) {
+ $default_type = 'CURRENT_TIMESTAMP';
+ } elseif ($data['Default'] === null) {
+ $default_type = 'NONE';
+ } else {
+ $default_type = 'USER_DEFINED';
+ }
+
+ $virtual = array(
+ 'VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED'
+ );
+ $data['Virtuality'] = '';
+ $data['Expression'] = '';
+ if (isset($data['Extra']) && in_array($data['Extra'], $virtual)) {
+ $data['Virtuality'] = str_replace(' GENERATED', '', $data['Extra']);
+ $expressions = $this->table->getColumnGenerationExpression($column);
+ $data['Expression'] = $expressions[$column];
+ }
+
+ $changes[] = 'CHANGE ' . PMA_Table::generateAlter(
+ $column,
+ $column,
+ /*overload*/mb_strtoupper($extracted_columnspec['type']),
+ $extracted_columnspec['spec_in_brackets'],
+ $extracted_columnspec['attribute'],
+ isset($data['Collation']) ? $data['Collation'] : '',
+ $data['Null'] === 'YES' ? 'NULL' : 'NOT NULL',
+ $default_type,
+ $current_timestamp ? '' : $data['Default'],
+ isset($data['Extra']) && $data['Extra'] !== '' ? $data['Extra']
+ : false,
+ isset($data['COLUMN_COMMENT']) && $data['COLUMN_COMMENT'] !== ''
+ ? $data['COLUMN_COMMENT'] : false,
+ $data['Virtuality'],
+ $data['Expression'],
+ $i === 0 ? '-first' : $column_names[$i - 1]
+ );
+ // update current column_names array, first delete old position
+ for ($j = 0, $ll = count($column_names); $j < $ll; $j++) {
+ if ($column_names[$j] == $column) {
+ unset($column_names[$j]);
+ }
+ }
+ // insert moved column
+ array_splice($column_names, $i, 0, $column);
+ }
+ if (empty($changes)) { // should never happen
+ $this->response->isSuccess(false);
+ return;
+ }
+ // move columns
+ $this->dbi->tryQuery(
+ sprintf(
+ 'ALTER TABLE %s %s',
+ PMA_Util::backquote($this->table),
+ implode(', ', $changes)
+ )
+ );
+ $tmp_error = $this->dbi->getError();
+ if ($tmp_error) {
+ $this->response->isSuccess(false);
+ $this->response->addJSON('message', PMA_Message::error($tmp_error));
+ } else {
+ $message = PMA_Message::success(
+ __('The columns have been moved successfully.')
+ );
+ $this->response->addJSON('message', $message);
+ $this->response->addJSON('columns', $column_names);
+ }
+ }
+
+ /**
+ * Displays HTML for changing one or more columns
+ *
+ * @param array $selected the selected columns
+ * @param string $action target script to call
+ *
+ * @return boolean $regenerate true if error occurred
+ *
+ */
+ protected function displayHtmlForColumnChange($selected, $action)
+ {
+ // $selected comes from mult_submits.inc.php
+ if (empty($selected)) {
+ $selected[] = $_REQUEST['field'];
+ $selected_cnt = 1;
+ } else { // from a multiple submit
+ $selected_cnt = count($selected);
+ }
+
+ /**
+ * @todo optimize in case of multiple fields to modify
+ */
+ $fields_meta = array();
+ for ($i = 0; $i < $selected_cnt; $i++) {
+ $fields_meta[] = $this->dbi->getColumns(
+ $this->db, $this->table, $selected[$i], true
+ );
+ }
+ $num_fields = count($fields_meta);
+ // set these globals because tbl_columns_definition_form.inc.php
+ // verifies them
+ // @todo: refactor tbl_columns_definition_form.inc.php so that it uses
+ // protected function params
+ $GLOBALS['action'] = $action;
+ $GLOBALS['num_fields'] = $num_fields;
+
+ /**
+ * Form for changing properties.
+ */
+ include_once 'libraries/check_user_privileges.lib.php';
+ include 'libraries/tbl_columns_definition_form.inc.php';
+ }
+
+ /**
+ * Function to get the type of command for multiple field handling
+ *
+ * @return string
+ */
+ protected function getMultipleFieldCommandType()
+ {
+ $types = array(
+ 'change', 'drop', 'primary',
+ 'index', 'unique', 'spatial',
+ 'fulltext', 'browse'
+ );
+
+ foreach ($types as $type) {
+ if (isset($_REQUEST['submit_mult_' . $type . '_x'])) {
+ return $type;
+ }
+ }
+
+ if (isset($_REQUEST['submit_mult'])) {
+ return $_REQUEST['submit_mult'];
+ } elseif (isset($_REQUEST['mult_btn'])
+ && $_REQUEST['mult_btn'] == __('Yes')
+ ) {
+ if (isset($_REQUEST['selected'])) {
+ $_REQUEST['selected_fld'] = $_REQUEST['selected'];
+ }
+ return 'row_delete';
+ }
+
+ return null;
+ }
+
+ /**
+ * Function to display table browse for selected columns
+ *
+ * @param string $goto goto page url
+ * @param string $pmaThemeImage URI of the pma theme image
+ *
+ * @return void
+ */
+ protected function displayTableBrowseForSelectedColumns($goto, $pmaThemeImage)
+ {
+ $GLOBALS['active_page'] = 'sql.php';
+ $fields = array();
+ foreach ($_REQUEST['selected_fld'] as $sval) {
+ $fields[] = PMA_Util::backquote($sval);
+ }
+ $sql_query = sprintf(
+ 'SELECT %s FROM %s.%s',
+ implode(', ', $fields),
+ PMA_Util::backquote($this->db),
+ PMA_Util::backquote($this->table)
+ );
+
+ // Parse and analyze the query
+ // @todo Refactor parse_analyze.inc to protected function
+ $db = &$this->db;
+ include_once 'libraries/parse_analyze.inc.php';
+
+ include_once 'libraries/sql.lib.php';
+
+ $this->response->addHTML(
+ PMA_executeQueryAndGetQueryResponse(
+ isset($analyzed_sql_results) ? $analyzed_sql_results : '',
+ false, // is_gotofile
+ $this->db, // db
+ $this->table, // table
+ null, // find_real_end
+ null, // sql_query_for_bookmark
+ null, // extra_data
+ null, // message_to_show
+ null, // message
+ null, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ null, // disp_query
+ null, // disp_message
+ null, // query_type
+ $sql_query, // sql_query
+ null, // selectedTables
+ null // complete_query
+ )
+ );
+ }
+
+ /**
+ * Update the table's structure based on $_REQUEST
+ *
+ * @return boolean $regenerate true if error occurred
+ *
+ */
+ protected function updateColumns()
+ {
+ $err_url = 'tbl_structure.php' . PMA_URL_getCommon(
+ array(
+ 'db' => $this->db, 'table' => $this->table
+ )
+ );
+ $regenerate = false;
+ $field_cnt = count($_REQUEST['field_name']);
+ $changes = array();
+ $adjust_privileges = array();
+
+ for ($i = 0; $i < $field_cnt; $i++) {
+ if (!$this->columnNeedsAlterTable($i)) {
+ continue;
+ }
+
+ $changes[] = 'CHANGE ' . PMA_Table::generateAlter(
+ Util\get($_REQUEST, "field_orig.${i}", ''),
+ $_REQUEST['field_name'][$i],
+ $_REQUEST['field_type'][$i],
+ $_REQUEST['field_length'][$i],
+ $_REQUEST['field_attribute'][$i],
+ Util\get($_REQUEST, "field_collation.${i}", ''),
+ Util\get($_REQUEST, "field_null.${i}", 'NOT NULL'),
+ $_REQUEST['field_default_type'][$i],
+ $_REQUEST['field_default_value'][$i],
+ Util\get($_REQUEST, "field_extra.${i}", false),
+ Util\get($_REQUEST, "field_comments.${i}", ''),
+ Util\get($_REQUEST, "field_virtuality.${i}", ''),
+ Util\get($_REQUEST, "field_expression.${i}", ''),
+ Util\get($_REQUEST, "field_move_to.${i}", '')
+ );
+
+ // find the remembered sort expression
+ $sorted_col = $this->table_obj->getUiProp(
+ PMA_Table::PROP_SORTED_COLUMN
+ );
+ // if the old column name is part of the remembered sort expression
+ if (/*overload*/mb_strpos(
+ $sorted_col,
+ PMA_Util::backquote($_REQUEST['field_orig'][$i])
+ ) !== false) {
+ // delete the whole remembered sort expression
+ $this->table_obj->removeUiProp(PMA_Table::PROP_SORTED_COLUMN);
+ }
+
+ if (isset($_REQUEST['field_adjust_privileges'][$i])
+ && ! empty($_REQUEST['field_adjust_privileges'][$i])
+ && $_REQUEST['field_orig'][$i] != $_REQUEST['field_name'][$i]
+ ) {
+ $adjust_privileges[$_REQUEST['field_orig'][$i]]
+ = $_REQUEST['field_name'][$i];
+ }
+ } // end for
+
+ if (count($changes) > 0 || isset($_REQUEST['preview_sql'])) {
+ // Builds the primary keys statements and updates the table
+ $key_query = '';
+ /**
+ * this is a little bit more complex
+ *
+ * @todo if someone selects A_I when altering a column we need to check:
+ * - no other column with A_I
+ * - the column has an index, if not create one
+ *
+ */
+
+ // To allow replication, we first select the db to use
+ // and then run queries on this db.
+ if (!$this->dbi->selectDb($this->db)) {
+ PMA_Util::mysqlDie(
+ $this->dbi->getError(),
+ 'USE ' . PMA_Util::backquote($this->db) . ';',
+ false,
+ $err_url
+ );
+ }
+ $sql_query = 'ALTER TABLE ' . PMA_Util::backquote($this->table) . ' ';
+ $sql_query .= implode(', ', $changes) . $key_query;
+ $sql_query .= ';';
+
+ // If there is a request for SQL previewing.
+ if (isset($_REQUEST['preview_sql'])) {
+ PMA_previewSQL(count($changes) > 0 ? $sql_query : '');
+ }
+
+ $changedToBlob = array();
+ // While changing the Column Collation
+ // First change to BLOB
+ for ($i = 0; $i < $field_cnt; $i++ ) {
+ if (isset($_REQUEST['field_collation'][$i])
+ && isset($_REQUEST['field_collation_orig'][$i])
+ && $_REQUEST['field_collation'][$i] !== $_REQUEST['field_collation_orig'][$i]
+ ) {
+ $secondary_query = 'ALTER TABLE ' . PMA_Util::backquote(
+ $this->table
+ )
+ . ' CHANGE ' . PMA_Util::backquote(
+ $_REQUEST['field_orig'][$i]
+ )
+ . ' ' . PMA_Util::backquote($_REQUEST['field_orig'][$i])
+ . ' BLOB;';
+ $this->dbi->query($secondary_query);
+ $changedToBlob[$i] = true;
+ } else {
+ $changedToBlob[$i] = false;
+ }
+ }
+
+ // Then make the requested changes
+ $result = $this->dbi->tryQuery($sql_query);
+
+ if ($result !== false) {
+ $changed_privileges = $this->adjustColumnPrivileges(
+ $adjust_privileges
+ );
+
+ if ($changed_privileges) {
+ $message = PMA_Message::success(
+ __(
+ 'Table %1$s has been altered successfully. Privileges ' .
+ 'have been adjusted.'
+ )
+ );
+ } else {
+ $message = PMA_Message::success(
+ __('Table %1$s has been altered successfully.')
+ );
+ }
+ $message->addParam($this->table);
+
+ $this->response->addHTML(
+ PMA_Util::getMessage($message, $sql_query, 'success')
+ );
+ } else {
+ // An error happened while inserting/updating a table definition
+
+ // Save the Original Error
+ $orig_error = $this->dbi->getError();
+ $changes_revert = array();
+
+ // Change back to Orignal Collation and data type
+ for ($i = 0; $i < $field_cnt; $i++) {
+ if ($changedToBlob[$i]) {
+ $changes_revert[] = 'CHANGE ' . PMA_Table::generateAlter(
+ Util\get($_REQUEST, "field_orig.${i}", ''),
+ $_REQUEST['field_name'][$i],
+ $_REQUEST['field_type_orig'][$i],
+ $_REQUEST['field_length_orig'][$i],
+ $_REQUEST['field_attribute_orig'][$i],
+ Util\get($_REQUEST, "field_collation_orig.${i}", ''),
+ Util\get($_REQUEST, "field_null_orig.${i}", 'NOT NULL'),
+ $_REQUEST['field_default_type_orig'][$i],
+ $_REQUEST['field_default_value_orig'][$i],
+ Util\get($_REQUEST, "field_extra_orig.${i}", false),
+ Util\get($_REQUEST, "field_comments_orig.${i}", ''),
+ Util\get($_REQUEST, "field_move_to_orig.${i}", '')
+ );
+ }
+ }
+
+ $revert_query = 'ALTER TABLE ' . PMA_Util::backquote($this->table)
+ . ' ';
+ $revert_query .= implode(', ', $changes_revert) . '';
+ $revert_query .= ';';
+
+ // Column reverted back to original
+ $this->dbi->query($revert_query);
+
+ $this->response->isSuccess(false);
+ $this->response->addJSON(
+ 'message',
+ PMA_Message::rawError(
+ __('Query error') . ':<br />' . $orig_error
+ )
+ );
+ $regenerate = true;
+ }
+ }
+
+ // update field names in relation
+ if (isset($_REQUEST['field_orig']) && is_array($_REQUEST['field_orig'])) {
+ foreach ($_REQUEST['field_orig'] as $fieldindex => $fieldcontent) {
+ if ($_REQUEST['field_name'][$fieldindex] != $fieldcontent) {
+ PMA_REL_renameField(
+ $this->db, $this->table, $fieldcontent,
+ $_REQUEST['field_name'][$fieldindex]
+ );
+ }
+ }
+ }
+
+ // update mime types
+ if (isset($_REQUEST['field_mimetype'])
+ && is_array($_REQUEST['field_mimetype'])
+ && $GLOBALS['cfg']['BrowseMIME']
+ ) {
+ foreach ($_REQUEST['field_mimetype'] as $fieldindex => $mimetype) {
+ if (isset($_REQUEST['field_name'][$fieldindex])
+ && /*overload*/mb_strlen(
+ $_REQUEST['field_name'][$fieldindex]
+ )
+ ) {
+ PMA_setMIME(
+ $this->db, $this->table,
+ $_REQUEST['field_name'][$fieldindex],
+ $mimetype,
+ $_REQUEST['field_transformation'][$fieldindex],
+ $_REQUEST['field_transformation_options'][$fieldindex],
+ $_REQUEST['field_input_transformation'][$fieldindex],
+ $_REQUEST['field_input_transformation_options'][$fieldindex]
+ );
+ }
+ }
+ }
+ return $regenerate;
+ }
+
+ /**
+ * Adjusts the Privileges for all the columns whose names have changed
+ *
+ * @param array $adjust_privileges assoc array of old col names mapped to new
+ * cols
+ *
+ * @return boolean $changed boolean whether at least one column privileges
+ * adjusted
+ */
+ protected function adjustColumnPrivileges($adjust_privileges)
+ {
+ $changed = false;
+
+ if ((!defined('PMA_DRIZZLE') || !PMA_DRIZZLE)
+ && Util\get($GLOBALS, 'col_priv', false)
+ && Util\get($GLOBALS, 'flush_priv', false)
+ ) {
+ $this->dbi->selectDb('mysql');
+
+ // For Column specific privileges
+ foreach ($adjust_privileges as $oldCol => $newCol) {
+
+ $this->dbi->query(
+ sprintf(
+ 'UPDATE %s SET Column_name = "%s"
+ WHERE Db = "%s"
+ AND Table_name = "%s"
+ AND Column_name = "%s";',
+ PMA_Util::backquote('columns_priv'),
+ $newCol, $this->db, $this->table, $oldCol
+ )
+ );
+
+ // i.e. if atleast one column privileges adjusted
+ $changed = true;
+ }
+
+ if ($changed) {
+ // Finally FLUSH the new privileges
+ $this->dbi->query("FLUSH PRIVILEGES;");
+ }
+ }
+
+ return $changed;
+ }
+
+ /**
+ * Verifies if some elements of a column have changed
+ *
+ * @param integer $i column index in the request
+ *
+ * @return boolean $alterTableNeeded true if we need to generate ALTER TABLE
+ *
+ */
+ protected function columnNeedsAlterTable($i)
+ {
+ // these two fields are checkboxes so might not be part of the
+ // request; therefore we define them to avoid notices below
+ if (! isset($_REQUEST['field_null'][$i])) {
+ $_REQUEST['field_null'][$i] = 'NO';
+ }
+ if (! isset($_REQUEST['field_extra'][$i])) {
+ $_REQUEST['field_extra'][$i] = '';
+ }
+
+ // field_name does not follow the convention (corresponds to field_orig)
+ $fields = array(
+ 'field_attribute', 'field_collation', 'field_comments',
+ 'field_default_value', 'field_default_type', 'field_extra',
+ 'field_length', 'field_name', 'field_null', 'field_type'
+ );
+ foreach ($fields as $field) {
+ if ($_REQUEST[$field][$i] != $_REQUEST[$field . '_orig'][$i]) {
+ return true;
+ }
+ }
+ return !empty($_REQUEST['field_move_to'][$i]);
+ }
+
+ /**
+ * Displays the table structure ('show table' works correct since 3.23.03)
+ *
+ * @param array $cfgRelation current relation parameters
+ * @param array $columns_with_unique_index Columns with unique index
+ * @param mixed $url_params Contains an associative
+ * array with url params
+ * @param PMA_Index|false $primary_index primary index or false if
+ * no one exists
+ * @param array $fields Fields
+ * @param array $columns_with_index Columns with index
+ * @param array $create_table_fields Fields of the table.
+ *
+ * @return string
+ */
+ protected function displayStructure(
+ $cfgRelation, $columns_with_unique_index, $url_params, $primary_index,
+ $fields, $columns_with_index, $create_table_fields
+ ) {
+ /* TABLE INFORMATION */
+ $HideStructureActions = '';
+ if ($GLOBALS['cfg']['HideStructureActions'] === true) {
+ $HideStructureActions .= ' HideStructureActions';
+ }
+
+ // prepare comments
+ $comments_map = array();
+ $mime_map = array();
+
+ if ($GLOBALS['cfg']['ShowPropertyComments']) {
+ include_once 'libraries/transformations.lib.php';
+ $comments_map = PMA_getComments($this->db, $this->table);
+ if ($cfgRelation['mimework'] && $GLOBALS['cfg']['BrowseMIME']) {
+ $mime_map = PMA_getMIME($this->db, $this->table, true);
+ }
+ }
+ include_once 'libraries/central_columns.lib.php';
+ $central_list = PMA_getCentralColumnsFromTable($this->db, $this->table);
+ $columns_list = array();
+
+ $titles = array(
+ 'Change' => PMA_Util::getIcon('b_edit.png', __('Change')),
+ 'Drop' => PMA_Util::getIcon('b_drop.png', __('Drop')),
+ 'NoDrop' => PMA_Util::getIcon('b_drop.png', __('Drop')),
+ 'Primary' => PMA_Util::getIcon('b_primary.png', __('Primary')),
+ 'Index' => PMA_Util::getIcon('b_index.png', __('Index')),
+ 'Unique' => PMA_Util::getIcon('b_unique.png', __('Unique')),
+ 'Spatial' => PMA_Util::getIcon('b_spatial.png', __('Spatial')),
+ 'IdxFulltext' => PMA_Util::getIcon('b_ftext.png', __('Fulltext')),
+ 'NoPrimary' => PMA_Util::getIcon('bd_primary.png', __('Primary')),
+ 'NoIndex' => PMA_Util::getIcon('bd_index.png', __('Index')),
+ 'NoUnique' => PMA_Util::getIcon('bd_unique.png', __('Unique')),
+ 'NoSpatial' => PMA_Util::getIcon('bd_spatial.png', __('Spatial')),
+ 'NoIdxFulltext' => PMA_Util::getIcon('bd_ftext.png', __('Fulltext')),
+ 'DistinctValues' => PMA_Util::getIcon(
+ 'b_browse.png',
+ __('Distinct values')
+ ),
+ );
+
+ /**
+ * Work on the table
+ */
+ if ($this->_tbl_is_view) {
+ $item = $this->dbi->fetchSingleRow(
+ sprintf(
+ "SELECT `VIEW_DEFINITION`, `CHECK_OPTION`, `DEFINER`,
+ `SECURITY_TYPE`
+ FROM `INFORMATION_SCHEMA`.`VIEWS`
+ WHERE TABLE_SCHEMA='%s'
+ AND TABLE_NAME='%s';",
+ PMA_Util::sqlAddSlashes($this->db),
+ PMA_Util::sqlAddSlashes($this->table)
+ )
+ );
+
+ $createView = $this->dbi->getTable($this->db, $this->table)
+ ->showCreate();
+ // get algorithm from $createView of the form
+ // CREATE ALGORITHM=<ALGORITHM> DE...
+ $parts = explode(" ", substr($createView, 17));
+ $item['ALGORITHM'] = $parts[0];
+
+ $view = array(
+ 'operation' => 'alter',
+ 'definer' => $item['DEFINER'],
+ 'sql_security' => $item['SECURITY_TYPE'],
+ 'name' => $this->table,
+ 'as' => $item['VIEW_DEFINITION'],
+ 'with' => $item['CHECK_OPTION'],
+ 'algorithm' => $item['ALGORITHM'],
+ );
+
+ $edit_view_url = 'view_create.php'
+ . PMA_URL_getCommon($url_params) . '&amp;'
+ . implode(
+ '&amp;',
+ array_map(
+ function ($key, $val) {
+ return 'view[' . urlencode($key) . ']=' . urlencode(
+ $val
+ );
+ },
+ array_keys($view), $view
+ )
+ );
+ }
+
+ /**
+ * Displays Space usage and row statistics
+ */
+ // BEGIN - Calc Table Space
+ // Get valid statistics whatever is the table type
+ if ($GLOBALS['cfg']['ShowStats']) {
+ //get table stats in HTML format
+ $tablestats = $this->getTableStats();
+ //returning the response in JSON format to be used by Ajax
+ $this->response->addJSON('tableStat', $tablestats);
+ }
+ // END - Calc Table Space
+
+ return Template::get('table/structure/display_structure')->render(
+ array(
+ 'HideStructureActions' => $HideStructureActions,
+ 'db' => $this->db,
+ 'table' => $this->table,
+ 'db_is_system_schema' => $this->_db_is_system_schema,
+ 'tbl_is_view' => $this->_tbl_is_view,
+ 'mime_map' => $mime_map,
+ 'url_query' => $this->_url_query,
+ 'titles' => $titles,
+ 'tbl_storage_engine' => $this->_tbl_storage_engine,
+ 'primary' => $primary_index,
+ 'columns_with_unique_index' => $columns_with_unique_index,
+ 'edit_view_url' => isset($edit_view_url) ? $edit_view_url : null,
+ 'columns_list' => $columns_list,
+ 'tablestats' => isset($tablestats) ? $tablestats : null,
+ 'fields' => $fields,
+ 'columns_with_index' => $columns_with_index,
+ 'central_list' => $central_list,
+ 'create_table_fields' => $create_table_fields,
+ 'comments_map' => $comments_map
+ )
+ );
+ }
+
+ /**
+ * Get HTML snippet for display table statistics
+ *
+ * @return string $html_output
+ */
+ protected function getTableStats()
+ {
+ if (empty($this->_showtable)) {
+ $this->_showtable = $this->dbi->getTable(
+ $this->db, $this->table
+ )->getStatusInfo(null, true);
+ }
+
+ if (empty($this->_showtable['Data_length'])) {
+ $this->_showtable['Data_length'] = 0;
+ }
+ if (empty($this->_showtable['Index_length'])) {
+ $this->_showtable['Index_length'] = 0;
+ }
+
+ $is_innodb = (isset($this->_showtable['Type'])
+ && $this->_showtable['Type'] == 'InnoDB');
+
+ $mergetable = $this->table_obj->isMerge();
+
+ // this is to display for example 261.2 MiB instead of 268k KiB
+ $max_digits = 3;
+ $decimals = 1;
+ list($data_size, $data_unit) = PMA_Util::formatByteDown(
+ $this->_showtable['Data_length'], $max_digits, $decimals
+ );
+ if ($mergetable == false) {
+ list($index_size, $index_unit) = PMA_Util::formatByteDown(
+ $this->_showtable['Index_length'], $max_digits, $decimals
+ );
+ }
+ // InnoDB returns a huge value in Data_free, do not use it
+ if (! $is_innodb && isset($this->_showtable['Data_free'])
+ && $this->_showtable['Data_free'] > 0
+ ) {
+ list($free_size, $free_unit) = PMA_Util::formatByteDown(
+ $this->_showtable['Data_free'], $max_digits, $decimals
+ );
+ list($effect_size, $effect_unit) = PMA_Util::formatByteDown(
+ $this->_showtable['Data_length']
+ + $this->_showtable['Index_length']
+ - $this->_showtable['Data_free'],
+ $max_digits, $decimals
+ );
+ } else {
+ list($effect_size, $effect_unit) = PMA_Util::formatByteDown(
+ $this->_showtable['Data_length']
+ + $this->_showtable['Index_length'],
+ $max_digits, $decimals
+ );
+ }
+ list($tot_size, $tot_unit) = PMA_Util::formatByteDown(
+ $this->_showtable['Data_length'] + $this->_showtable['Index_length'],
+ $max_digits, $decimals
+ );
+ if ($this->_table_info_num_rows > 0) {
+ list($avg_size, $avg_unit) = PMA_Util::formatByteDown(
+ ($this->_showtable['Data_length']
+ + $this->_showtable['Index_length'])
+ / $this->_showtable['Rows'],
+ 6,
+ 1
+ );
+ } else {
+ $avg_size = $avg_unit = '';
+ }
+
+ return Template::get('table/structure/display_table_stats')->render(
+ array(
+ 'showtable' => $this->_showtable,
+ 'table_info_num_rows' => $this->_table_info_num_rows,
+ 'tbl_is_view' => $this->_tbl_is_view,
+ 'db_is_system_schema' => $this->_db_is_system_schema,
+ 'tbl_storage_engine' => $this->_tbl_storage_engine,
+ 'url_query' => $this->_url_query,
+ 'tbl_collation' => $this->_tbl_collation,
+ 'is_innodb' => $is_innodb,
+ 'mergetable' => $mergetable,
+ 'avg_size' => isset($avg_size) ? $avg_size : null,
+ 'avg_unit' => isset($avg_unit) ? $avg_unit : null,
+ 'data_size' => $data_size,
+ 'data_unit' => $data_unit,
+ 'index_size' => isset($index_size) ? $index_size : null,
+ 'index_unit' => isset($index_unit) ? $index_unit : null,
+ 'free_size' => isset($free_size) ? $free_size : null,
+ 'free_unit' => isset($free_unit) ? $free_unit : null,
+ 'effect_size' => $effect_size,
+ 'effect_unit' => $effect_unit,
+ 'tot_size' => $tot_size,
+ 'tot_unit' => $tot_unit
+ )
+ );
+ }
+
+ /**
+ * Gets table primary key
+ *
+ * @return string
+ */
+ protected function getKeyForTablePrimary()
+ {
+ $this->dbi->selectDb($this->db);
+ $result = $this->dbi->query(
+ 'SHOW KEYS FROM ' . PMA_Util::backquote($this->table) . ';'
+ );
+ $primary = '';
+ while ($row = $this->dbi->fetchAssoc($result)) {
+ // Backups the list of primary keys
+ if ($row['Key_name'] == 'PRIMARY') {
+ $primary .= $row['Column_name'] . ', ';
+ }
+ } // end while
+ $this->dbi->freeResult($result);
+
+ return $primary;
+ }
+
+ /**
+ * Get List of information for Submit Mult
+ *
+ * @param string $submit_mult mult_submit type
+ * @param array $selected the selected columns
+ * @param string $action action type
+ *
+ * @return array
+ */
+ protected function getDataForSubmitMult($submit_mult, $selected, $action)
+ {
+ $what = null;
+ $query_type = null;
+ $is_unset_submit_mult = false;
+ $mult_btn = null;
+ $centralColsError = null;
+ switch ($submit_mult) {
+ case 'drop':
+ $what = 'drop_fld';
+ break;
+ case 'primary':
+ // Gets table primary key
+ $primary = $this->getKeyForTablePrimary();
+ if (empty($primary)) {
+ // no primary key, so we can safely create new
+ $is_unset_submit_mult = true;
+ $query_type = 'primary_fld';
+ $mult_btn = __('Yes');
+ } else {
+ // primary key exists, so lets as user
+ $what = 'primary_fld';
+ }
+ break;
+ case 'index':
+ $is_unset_submit_mult = true;
+ $query_type = 'index_fld';
+ $mult_btn = __('Yes');
+ break;
+ case 'unique':
+ $is_unset_submit_mult = true;
+ $query_type = 'unique_fld';
+ $mult_btn = __('Yes');
+ break;
+ case 'spatial':
+ $is_unset_submit_mult = true;
+ $query_type = 'spatial_fld';
+ $mult_btn = __('Yes');
+ break;
+ case 'ftext':
+ $is_unset_submit_mult = true;
+ $query_type = 'fulltext_fld';
+ $mult_btn = __('Yes');
+ break;
+ case 'add_to_central_columns':
+ include_once 'libraries/central_columns.lib.php';
+ $centralColsError = PMA_syncUniqueColumns($selected, false);
+ break;
+ case 'remove_from_central_columns':
+ include_once 'libraries/central_columns.lib.php';
+ $centralColsError = PMA_deleteColumnsFromList($selected, false);
+ break;
+ case 'change':
+ $this->displayHtmlForColumnChange($selected, $action);
+ // execution stops here but PMA_Response correctly finishes
+ // the rendering
+ exit;
+ case 'browse':
+ // this should already be handled by tbl_structure.php
+ }
+
+ return array(
+ $what, $query_type, $is_unset_submit_mult, $mult_btn,
+ $centralColsError
+ );
+ }
+}
diff --git a/libraries/core.lib.php b/libraries/core.lib.php
index a31f29dbe9..3877548c34 100644
--- a/libraries/core.lib.php
+++ b/libraries/core.lib.php
@@ -590,26 +590,10 @@ function PMA_sendHeaderLocation($uri, $use_refresh = false)
include_once './libraries/js_escape.lib.php';
PMA_Response::getInstance()->disable();
- echo '<html><head><title>- - -</title>' . "\n";
- echo '<meta http-equiv="expires" content="0">' . "\n";
- echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
- echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
- echo '<meta http-equiv="Refresh" content="0;url='
- . htmlspecialchars($uri) . '">' . "\n";
- echo '<script type="text/javascript">' . "\n";
- echo '//<![CDATA[' . "\n";
- echo 'setTimeout("window.location = unescape(\'"'
- . PMA_escapeJsString($uri) . '"\')", 2000);' . "\n";
- echo '//]]>' . "\n";
- echo '</script>' . "\n";
- echo '</head>' . "\n";
- echo '<body>' . "\n";
- echo '<script type="text/javascript">' . "\n";
- echo '//<![CDATA[' . "\n";
- echo 'document.write(\'<p><a href="' . htmlspecialchars($uri) . '">'
- . __('Go') . '</a></p>\');' . "\n";
- echo '//]]>' . "\n";
- echo '</script></body></html>' . "\n";
+ include_once './libraries/Template.class.php';
+
+ echo PMA\Template::get('header_location')
+ ->render(array('uri' => $uri));
return;
}
@@ -791,7 +775,7 @@ function PMA_arrayRemove($path, &$array)
break;
}
$depth++;
- $path[$depth] =& $path[$depth-1][$key];
+ $path[$depth] =& $path[$depth - 1][$key];
}
// if element found, remove it
if ($found) {
@@ -859,8 +843,10 @@ function PMA_isAllowedDomain($url)
'docs.phpmyadmin.net',
/* mysql.com domains */
'dev.mysql.com','bugs.mysql.com',
- /* drizzle.com domains */
+ /* drizzle.org domains */
'www.drizzle.org',
+ /* mariadb domains */
+ 'mariadb.org',
/* php.net domains */
'php.net',
/* Github domains*/
@@ -1012,4 +998,3 @@ function PMA_setGlobalDbOrTable($param)
$GLOBALS['url_params'][$param] = $GLOBALS[$param];
}
}
-?>
diff --git a/libraries/create_addfield.lib.php b/libraries/create_addfield.lib.php
index 756f7c24ba..89598e1c2d 100644
--- a/libraries/create_addfield.lib.php
+++ b/libraries/create_addfield.lib.php
@@ -22,10 +22,11 @@ function PMA_getIndexedColumns()
$field_index = json_decode($_REQUEST['indexes'], true);
$field_unique = json_decode($_REQUEST['unique_indexes'], true);
$field_fulltext = json_decode($_REQUEST['fulltext_indexes'], true);
+ $field_spatial = json_decode($_REQUEST['spatial_indexes'], true);
return array(
$field_cnt, $field_primary, $field_index, $field_unique,
- $field_fulltext
+ $field_fulltext, $field_spatial
);
}
@@ -71,6 +72,12 @@ function PMA_buildColumnCreationStatement(
: false,
isset($_REQUEST['field_comments'][$i])
? $_REQUEST['field_comments'][$i]
+ : '',
+ isset($_REQUEST['field_virtuality'][$i])
+ ? $_REQUEST['field_virtuality'][$i]
+ : '',
+ isset($_REQUEST['field_expression'][$i])
+ ? $_REQUEST['field_expression'][$i]
: ''
);
@@ -94,18 +101,18 @@ function PMA_setColumnCreationStatementSuffix($current_field_num,
$is_create_tbl = true
) {
// no suffix is needed if request is a table creation
- $sql_suffix = " ";
+ $sql_suffix = ' ';
if ($is_create_tbl) {
return $sql_suffix;
}
- if ($_REQUEST['field_where'] == 'last') {
+ if ((string) $_REQUEST['field_where'] === 'last') {
return $sql_suffix;
}
// Only the first field can be added somewhere other than at the end
- if ($current_field_num == 0) {
- if ($_REQUEST['field_where'] == 'first') {
+ if ((int) $current_field_num === 0) {
+ if ((string) $_REQUEST['field_where'] === 'first') {
$sql_suffix .= ' FIRST';
} else {
$sql_suffix .= ' AFTER '
@@ -242,7 +249,7 @@ function PMA_getColumnCreationStatements($is_create_tbl = true)
{
$sql_statement = "";
list($field_cnt, $field_primary, $field_index,
- $field_unique, $field_fulltext
+ $field_unique, $field_fulltext, $field_spatial
) = PMA_getIndexedColumns();
$definitions = PMA_buildColumnCreationStatement(
$field_cnt, $is_create_tbl
@@ -271,6 +278,11 @@ function PMA_getColumnCreationStatements($is_create_tbl = true)
$definitions, $is_create_tbl, $field_fulltext, "FULLTEXT"
);
+ // Builds the SPATIAL statements
+ $definitions = PMA_mergeIndexStatements(
+ $definitions, $is_create_tbl, $field_spatial, "SPATIAL"
+ );
+
if (count($definitions)) {
$sql_statement = implode(', ', $definitions);
}
@@ -377,4 +389,3 @@ function PMA_tryColumnCreationQuery($db, $table, $err_url)
}
return array($GLOBALS['dbi']->tryQuery($sql_query) , $sql_query);
}
-?>
diff --git a/libraries/data_dictionary_relations.lib.php b/libraries/data_dictionary_relations.lib.php
index 99a0526da3..974de8c6a4 100644
--- a/libraries/data_dictionary_relations.lib.php
+++ b/libraries/data_dictionary_relations.lib.php
@@ -164,4 +164,3 @@ $GLOBALS['data_dictionary_relations'] = array(
)
);
-?>
diff --git a/libraries/database_interface.inc.php b/libraries/database_interface.inc.php
index 562428448c..52968bb093 100644
--- a/libraries/database_interface.inc.php
+++ b/libraries/database_interface.inc.php
@@ -10,7 +10,8 @@ if (! defined('PHPMYADMIN')) {
exit;
}
-require_once './libraries/DatabaseInterface.class.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/DatabaseInterface.class.php';
if (defined('TESTSUITE')) {
/**
@@ -23,6 +24,7 @@ if (defined('TESTSUITE')) {
/**
* First check for the mysqli extension, as it's the one recommended
* for the MySQL server's version that we support
+ * (if PHP 7+, it's the only one supported)
*/
$extension = 'mysqli';
if (! PMA_DatabaseInterface::checkDbExtension($extension)) {
@@ -34,25 +36,34 @@ if (defined('TESTSUITE')) {
'[/a]'
);
- $extension = 'mysql';
- if (! PMA_DatabaseInterface::checkDbExtension($extension)) {
- // warn about both extensions missing and exit
+ if (PMA_PHP_INT_VERSION < 70000) {
+ $extension = 'mysql';
+ if (! PMA_DatabaseInterface::checkDbExtension($extension)) {
+ // warn about both extensions missing and exit
+ PMA_warnMissingExtension(
+ 'mysqli|mysql',
+ true,
+ $doclink
+ );
+ } elseif (empty($_SESSION['mysqlwarning'])) {
+ trigger_error(
+ __(
+ 'You are using the mysql extension which is deprecated in '
+ . 'phpMyAdmin. Please consider installing the mysqli '
+ . 'extension.'
+ ) . ' ' . $doclink,
+ E_USER_WARNING
+ );
+ // tell the user just once per session
+ $_SESSION['mysqlwarning'] = true;
+ }
+ } else {
+ // mysql extension is not part of PHP 7+, so warn and exit
PMA_warnMissingExtension(
- 'mysqli|mysql',
+ 'mysqli',
true,
$doclink
);
- } elseif (empty($_SESSION['mysqlwarning'])) {
- trigger_error(
- __(
- 'You are using the mysql extension which is deprecated in '
- . 'phpMyAdmin. Please consider installing the mysqli '
- . 'extension.'
- ) . ' ' . $doclink,
- E_USER_WARNING
- );
- // tell the user just once per session
- $_SESSION['mysqlwarning'] = true;
}
}
@@ -71,4 +82,7 @@ if (defined('TESTSUITE')) {
}
}
$GLOBALS['dbi'] = new PMA_DatabaseInterface($extension);
-?>
+
+$container = \PMA\DI\Container::getDefaultContainer();
+$container->set('PMA_DatabaseInterface', $GLOBALS['dbi']);
+$container->alias('dbi', 'PMA_DatabaseInterface');
diff --git a/libraries/db_common.inc.php b/libraries/db_common.inc.php
index bf40fc028c..2cfc9c091f 100644
--- a/libraries/db_common.inc.php
+++ b/libraries/db_common.inc.php
@@ -16,6 +16,9 @@ require_once './libraries/bookmark.lib.php';
PMA_Util::checkParameters(array('db'));
+global $cfg;
+global $db;
+
$is_show_stats = $cfg['ShowStats'];
$db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($db);
@@ -27,7 +30,10 @@ if ($db_is_system_schema) {
* Defines the urls to return to in case of error in a sql statement
*/
$err_url_0 = 'index.php' . PMA_URL_getCommon();
-$err_url = $cfg['DefaultTabDatabase']
+
+$err_url = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+)
. PMA_URL_getCommon(array('db' => $db));
/** @var PMA_String $pmaString */
@@ -89,7 +95,7 @@ if (isset($_REQUEST['submitcollation'])
* db charset change action on db_operations.php. If this causes a bug on
* other pages, we might have to move this to a different location.
*/
- if ( $GLOBALS['is_ajax_request'] == true) {
+ if ($GLOBALS['is_ajax_request'] == true) {
$response = PMA_Response::getInstance();
$response->isSuccess($message->isSuccess());
$response->addJSON('message', $message);
@@ -102,4 +108,3 @@ if (isset($_REQUEST['submitcollation'])
*/
$url_query = PMA_URL_getCommon(array('db' => $db));
-?>
diff --git a/libraries/db_designer.lib.php b/libraries/db_designer.lib.php
index 8cf7fcacd2..4ca11c017e 100644
--- a/libraries/db_designer.lib.php
+++ b/libraries/db_designer.lib.php
@@ -10,6 +10,7 @@ if (! defined('PHPMYADMIN')) {
}
require_once 'libraries/relation.lib.php';
+require_once 'libraries/Template.class.php';
/**
* Function to get html to display a page selector
@@ -21,17 +22,13 @@ require_once 'libraries/relation.lib.php';
*/
function PMA_getHtmlForPageSelector($cfgRelation, $db)
{
- $html = '<select name="selected_page" id="selected_page">';
- $html .= '<option value="0">-- ' . __('Select page') . ' --</option>';
- if ($cfgRelation['pdfwork']) {
- $pages = PMA_getPageIdsAndNames($db);
- foreach ($pages as $nr => $desc) {
- $html .= '<option value="' . $nr . '">';
- $html .= htmlspecialchars($desc) . '</option>';
- }
- }
- $html .= '</select>';
- return $html;
+ return PMA\Template::get('database/designer/page_selector')
+ ->render(
+ array(
+ 'db' => $db,
+ 'cfgRelation' => $cfgRelation
+ )
+ );
}
/**
@@ -44,23 +41,13 @@ function PMA_getHtmlForPageSelector($cfgRelation, $db)
*/
function PMA_getHtmlForEditOrDeletePages($db, $operation)
{
- $cfgRelation = PMA_getRelationsParam();
- $html = '<form action="db_designer.php" method="post"'
- . ' name="edit_delete_pages" id="edit_delete_pages" class="ajax">';
- $html .= PMA_URL_getHiddenInputs($db);
- $html .= '<fieldset id="page_edit_delete_options">';
- $html .= '<input type="hidden" name="operation" value="' . $operation . '" />';
- $html .= '<label for="selected_page">';
- if ($operation == 'editPage') {
- $html .= __("Page to open");
- } else {
- $html .= __("Page to delete");
- }
- $html .= ': </label>';
- $html .= PMA_getHtmlForPageSelector($cfgRelation, $db);
- $html .= '</fieldset>';
- $html .= '</form>';
- return $html;
+ return PMA\Template::get('database/designer/edit_delete_pages')
+ ->render(
+ array(
+ 'db' => $db,
+ 'operation' => $operation
+ )
+ );
}
/**
@@ -72,43 +59,12 @@ function PMA_getHtmlForEditOrDeletePages($db, $operation)
*/
function PMA_getHtmlForPageSaveAs($db)
{
- $cfgRelation = PMA_getRelationsParam();
- $choices = array(
- 'same' => __('Save to selected page'),
- 'new' => __('Create a page and save to it')
- );
-
- $html = '<form action="db_designer.php" method="post"'
- . ' name="save_as_pages" id="save_as_pages" class="ajax">';
- $html .= PMA_URL_getHiddenInputs($db);
- $html .= '<fieldset id="page_save_as_options">';
- $html .= '<table><tbody>';
-
- $html .= '<tr>';
- $html .= '<td>';
- $html .= '<input type="hidden" name="operation" value="savePage" />';
- $html .= PMA_getHtmlForPageSelector($cfgRelation, $db);
- $html .= '</td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td>';
- $html .= PMA_Util::getRadioFields('save_page', $choices, 'same', true);
- $html .= '</td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td>';
- $html .= '<label for="selected_value">' . __('New page name') . '</label>';
- $html .= '<input type="text" name="selected_value" id="selected_value" />';
- $html .= '</td>';
- $html .= '</tr>';
-
- $html .= '</tbody></table>';
- $html .= '</fieldset>';
- $html .= '</form>';
-
- return $html;
+ return PMA\Template::get('database/designer/page_save_as')
+ ->render(
+ array(
+ 'db' => $db
+ )
+ );
}
/**
@@ -125,7 +81,7 @@ function PMA_getPageIdsAndNames($db)
. PMA_Util::backquote($cfgRelation['db']) . "."
. PMA_Util::backquote($cfgRelation['pdf_pages'])
. " WHERE db_name = '" . PMA_Util::sqlAddSlashes($db) . "'"
- . " ORDER BY `page_nr`";
+ . " ORDER BY `page_descr`";
$page_rs = PMA_queryAsControlUser(
$page_query, false, PMA_DatabaseInterface::QUERY_STORE
);
@@ -148,6 +104,7 @@ function PMA_getPageIdsAndNames($db)
function PMA_getHtmlForSchemaExport($db, $page)
{
/* Scan for schema plugins */
+ /* @var $export_list SchemaPlugin[] */
$export_list = PMA_getPlugins(
"schema",
'libraries/plugins/schema/',
@@ -161,22 +118,14 @@ function PMA_getHtmlForSchemaExport($db, $page)
)->getDisplay();
}
- $htmlString = '<form method="post" action="schema_export.php"'
- . ' class="disableAjax" id="id_export_pages">';
- $htmlString .= '<fieldset>';
- $htmlString .= PMA_URL_getHiddenInputs($db);
- $htmlString .= '<label>' . __('Select Export Relational Type')
- . '</label><br />';
- $htmlString .= PMA_pluginGetChoice(
- 'Schema', 'export_type', $export_list, 'format'
- );
- $htmlString .= '<input type="hidden" name="page_number"'
- . ' value="' . htmlspecialchars($page) . '" />';
- $htmlString .= PMA_pluginGetOptions('Schema', $export_list);
- $htmlString .= '</fieldset>';
- $htmlString .= '</form>';
-
- return $htmlString;
+ return PMA\Template::get('database/designer/schema_export')
+ ->render(
+ array(
+ 'db' => $db,
+ 'page' => $page,
+ 'export_list' => $export_list
+ )
+ );
}
/**
@@ -192,34 +141,15 @@ function PMA_getHtmlForSchemaExport($db, $page)
function PMA_getHtmlForJSFields(
$script_tables, $script_contr, $script_display_field, $display_page
) {
- $cfgRelation = PMA_getRelationsParam();
-
- $html = '<div id="script_server" class="hide">';
- $html .= htmlspecialchars($GLOBALS['server']);
- $html .= '</div>';
- $html .= '<div id="script_db" class="hide">';
- $html .= htmlspecialchars($_GET['db']);
- $html .= '</div>';
- $html .= '<div id="script_token" class="hide">';
- $html .= htmlspecialchars($_GET['token']);
- $html .= '</div>';
- $html .= '<div id="script_tables" class="hide">';
- $html .= htmlspecialchars(json_encode($script_tables));
- $html .= '</div>';
- $html .= '<div id="script_contr" class="hide">';
- $html .= htmlspecialchars(json_encode($script_contr));
- $html .= '</div>';
- $html .= '<div id="script_display_field" class="hide">';
- $html .= htmlspecialchars(json_encode($script_display_field));
- $html .= '</div>';
- $html .= '<div id="script_display_page" class="hide">';
- $html .= htmlspecialchars($display_page);
- $html .= '</div>';
- $html .= '<div id="pmd_tables_enabled" class="hide">';
- $html .= htmlspecialchars($cfgRelation['pdfwork']);
- $html .= '</div>';
-
- return $html;
+ return PMA\Template::get('database/designer/js_fields')
+ ->render(
+ array(
+ 'script_tables' => $script_tables,
+ 'script_contr' => $script_contr,
+ 'script_display_field' => $script_display_field,
+ 'display_page' => $display_page
+ )
+ );
}
/**
@@ -227,204 +157,109 @@ function PMA_getHtmlForJSFields(
*
* @param boolean $visualBuilder whether this is visual query builder
* @param string $selected_page name of the selected page
+ * @param array $params_array array with class name for various buttons on side
+ * menu
*
* @return string html
*/
-function PMA_getDesignerPageMenu($visualBuilder, $selected_page)
+function PMA_getDesignerPageMenu($visualBuilder, $selected_page, $params_array)
{
- $iconClass = '';
- $textClass = 'hidable hide';
-
- $html = '';
-
- if (!$visualBuilder) {
- $html .= '<div id="name-panel" style="overflow:hidden">';
- $html .= '<span id="page_name" style="border:none">';
- $html .= ($selected_page == null
- ? __("Untitled")
- : htmlspecialchars($selected_page));
- $html .= '</span>';
- $html .= '<span id="saved_state" style="border:none;width:5px">';
- $html .= ($selected_page == null ? '*' : '') . '</span>';
- $html .= '</div>';
- }
-
- $html .= '<div class="pmd_header side-menu" id="side_menu">';
-
- $html .= '<a class="M_butt" id="key_Show_left_menu" href="#" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Show/Hide tables list') . '" alt="v" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow2_m.png') . '" '
- . 'data-down="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow2_m.png') . '" '
- . 'data-up="' . $_SESSION['PMA_Theme']->getImgPath('pmd/uparrow2_m.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Show/Hide tables list') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" id="toggleFullscreen" class="M_butt" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('View in fullscreen') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/viewInFullscreen.png') . '" '
- . 'data-enter="' . $_SESSION['PMA_Theme']->getImgPath('pmd/viewInFullscreen.png') . '" '
- . 'data-exit="' . $_SESSION['PMA_Theme']->getImgPath('pmd/exitFullscreen.png') . '" />';
- $html .= '<span class="' . $textClass . '" data-exit="' . __('Exit fullscreen');
- $html .= '" data-enter="' . __('View in fullscreen') . '">' . __('View in fullscreen') . '</span>';
- $html .= '</a>';
+ return PMA\Template::get('database/designer/side_menu')
+ ->render(
+ array(
+ 'visualBuilder' => $visualBuilder,
+ 'selected_page' => $selected_page,
+ 'params_array' => $params_array
+ )
+ );
+}
- if (! $visualBuilder) {
+/**
+ * Returns array of stored values of Designer Settings
+ *
+ * @return array stored values
+ */
+function PMA_getSideMenuParamsArray()
+{
+ $params = array();
- $html .= '<a id="newPage" href="#" ';
- $html .= 'class="M_butt" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('New page') . '"alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/page_add.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('New page') . '</span>';
- $html .= '</a>';
+ $cfgRelation = PMA_getRelationsParam();
- $html .= '<a href="#" id="editPage" ';
- $html .= 'class="M_butt ajax" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Open page') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/page_edit.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Open page') . '</span>';
- $html .= '</a>';
+ if ($GLOBALS['cfgRelation']['designersettingswork']) {
- $html .= '<a href="#" id="savePos" ';
- $html .= 'class="M_butt" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Save position') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/save.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Save position') . '</span>';
- $html .= '</a>';
+ $query = 'SELECT `settings_data` FROM '
+ . PMA_Util::backquote($cfgRelation['db']) . '.'
+ . PMA_Util::backquote($cfgRelation['designer_settings'])
+ . ' WHERE ' . PMA_Util::backquote('username') . ' = "'
+ . $GLOBALS['cfg']['Server']['user'] . '";';
- $html .= '<a href="#" id="SaveAs" ';
- $html .= 'class="M_butt ajax" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Save positions as') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/save_as.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Save positions as') . '</span>';
- $html .= '</a>';
+ $result = $GLOBALS['dbi']->fetchSingleRow($query);
- $html .= '<a href="#" id="delPages" ';
- $html .= 'class="M_butt ajax" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Delete pages') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/page_delete.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Delete pages') . '</span>';
- $html .= '</a>';
+ $params = json_decode($result['settings_data'], true);
}
- $html .= '<a href="#" id="StartTableNew" ';
- $html .= 'class="M_butt" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Create table') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/table.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Create table') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" class="M_butt" ';
- $html .= 'id="rel_button" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Create relation') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/relation.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Create relation') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" ';
- $html .= 'class="M_butt" id="display_field_button" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Choose column to display') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/display_field.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Choose column to display') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" id="reloadPage" class="M_butt" ';
- $html .= 'target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Reload') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/reload.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Reload') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="' . PMA_Util::getDocuLink('faq', 'faq6-31') . '" ';
- $html .= 'target="documentation" class="M_butt" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Help') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/help.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Help') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" ';
- $html .= 'class="M_butt" id="angular_direct_button" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Angular links') . ' / ' . __('Direct links') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/ang_direct.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Angular links') . ' / ' . __('Direct links') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" class="M_butt" ';
- $html .= 'id="grid_button" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Snap to grid') . '" alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/grid.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Snap to grid') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" class="M_butt" target="_self" id="key_SB_all">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Small/Big All') . '" alt="v" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow1.png') .'" '
- . 'data-right="' . $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow1.png') .'" '
- . 'data-down="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow1.png') .'"" />';
- $html .= '<span class="' . $textClass . '">' . __('Small/Big All') . '</span>';
- $html .= '</a>';
-
- $html .= '<a href="#" id="SmallTabInvert" ';
- $html .= 'class="M_butt" target="_self" >';
- $html .= '<img class="' . $iconClass . '" title="' . __('Toggle small/big') . '" alt="key" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/bottom.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Toggle small/big') . '</span>';
- $html .= '</a>';
+ return $params;
+}
- $html .= '<a href="#" id="relLineInvert" ';
- $html .= 'class="M_butt" target="_self" >';
- $html .= '<img class="' . $iconClass . '" title="' . __('Toggle relation lines') . '" alt="key" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/toggle_lines.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Toggle relation lines') . '</span>';
- $html .= '</a>';
+/**
+ * Returns class names for various buttons on Designer Side Menu
+ *
+ * @return array class names of various buttons
+ */
+function PMA_returnClassNamesFromMenuButtons()
+{
+ $classes_array = array();
+ $params_array = PMA_getSideMenuParamsArray();
- if (! $visualBuilder) {
+ if (isset($params_array['angular_direct'])
+ && $params_array['angular_direct'] == 'angular'
+ ) {
+ $classes_array['angular_direct'] = 'M_butt_Selected_down';
+ } else {
+ $classes_array['angular_direct'] = 'M_butt';
+ }
- $html .= '<a href="#" id="exportPages" ';
- $html .= 'class="M_butt" target="_self" >';
- $html .= '<img class="' . $iconClass . '" title="' . __('Export schema') . '" alt="key" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/export.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Export schema') . '</span>';
- $html .= '</a>';
+ if (isset($params_array['snap_to_grid'])
+ && $params_array['snap_to_grid'] == 'on'
+ ) {
+ $classes_array['snap_to_grid'] = 'M_butt_Selected_down';
+ } else {
+ $classes_array['snap_to_grid'] = 'M_butt';
+ }
+ if (isset($params_array['pin_text'])
+ && $params_array['pin_text'] == 'true'
+ ) {
+ $classes_array['pin_text'] = 'M_butt_Selected_down';
} else {
- $html .= '<a class="M_butt" href="#" onclick="build_query(\'SQL Query on Database\', 0)" ';
- $html .= 'onmousedown="return false;" class="M_butt" target="_self">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Build Query') . '" alt="key" ';
- $html .= 'width="20" height="20" src="';
- $html .= $_SESSION['PMA_Theme']->getImgPath('pmd/query_builder.png')
- . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Build Query') . '</span>';
- $html .= '</a>';
+ $classes_array['pin_text'] = 'M_butt';
}
- $html .= '<a href="#" class="M_butt" target="_self" id="key_Left_Right">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Move Menu') . '" alt=">"';
- $html .= ' data-right="' . $_SESSION['PMA_Theme']->getImgPath('pmd/2leftarrow_m.png');
- $html .= '" src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/2rightarrow_m.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Move Menu') . '</span>';
- $html .= '</a>';
+ if (isset($params_array['relation_lines'])
+ && $params_array['relation_lines'] == 'false'
+ ) {
+ $classes_array['relation_lines'] = 'M_butt_Selected_down';
+ } else {
+ $classes_array['relation_lines'] = 'M_butt';
+ }
- $html .= '<a href="#" class="M_butt" target="_self" id="pin_Text">';
- $html .= '<img class="' . $iconClass . '" title="' . __('Pin text') . '" alt=">"';
- $html .= ' data-right="' . $_SESSION['PMA_Theme']->getImgPath('pmd/anchor.png');
- $html .= '" src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/anchor.png') . '" />';
- $html .= '<span class="' . $textClass . '">' . __('Pin text') . '</span>';
- $html .= '</a>';
+ if (isset($params_array['small_big_all'])
+ && $params_array['small_big_all'] == 'v'
+ ) {
+ $classes_array['small_big_all'] = 'M_butt_Selected_down';
+ } else {
+ $classes_array['small_big_all'] = 'M_butt';
+ }
- $html .= '</div>';
+ if (isset($params_array['side_menu'])
+ && $params_array['side_menu'] == 'true'
+ ) {
+ $classes_array['side_menu'] = 'M_butt_Selected_down';
+ } else {
+ $classes_array['side_menu'] = 'M_butt';
+ }
- return $html;
+ return $classes_array;
}
/**
@@ -434,12 +269,7 @@ function PMA_getDesignerPageMenu($visualBuilder, $selected_page)
*/
function PMA_getHTMLCanvas()
{
- $html = '<div id="osn_tab">';
- $html .= '<canvas class="pmd" id="canvas" width="100" height="100" ';
- $html .= '></canvas>';
- $html .= '</div>';
-
- return $html;
+ return PMA\Template::get('database/designer/canvas')->render();
}
/**
@@ -452,88 +282,13 @@ function PMA_getHTMLCanvas()
*/
function PMA_getHTMLTableList($tab_pos, $display_page)
{
- $html = '<div id="layer_menu" style="display:none;">';
-
- $html .= '<div class="center">';
-
- $html .= '<a href="#" class="M_butt" target="_self" ';
- $html .= '>';
- $html .= '<img title="' . __('Hide/Show all') . '" alt="v" id="key_HS_all" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow1.png') . '" '
- . 'data-down="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow1.png') . '" '
- . 'data-right="' . $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow1.png') . '" />';
- $html .= '</a>';
-
- $html .= '<a href="#" class="M_butt" target="_self" ';
- $html .= '>';
- $html .= '<img alt="v" id="key_HS" ';
- $html .= 'title="' . __('Hide/Show Tables with no relation') . '"';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow2.png') . '" '
- . 'data-down="' . $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow2.png') . '" '
- . 'data-right="' . $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow2.png') . '" />';
- $html .= '</a>';
-
- $html .= '</div>';
-
- $html .= '<div id="id_scroll_tab" class="scroll_tab">';
-
- $html .= '<table width="100%" style="padding-left: 3px;">';
-
- $name_cnt = count($GLOBALS['PMD']['TABLE_NAME']);
- for ($i = 0; $i < $name_cnt; $i++) {
-
- $html .= '<tr>';
-
- $html .= '<td title="' . __('Structure') . '" width="1px" ';
- $html .= 'onmouseover="this.className=\'L_butt2_2\'" ';
- $html .= 'onmouseout="this.className=\'L_butt2_1\'" class="L_butt2_1">';
- $html .= '<img alt="" ';
- $html .= 'table_name="' . $GLOBALS['PMD_URL']['TABLE_NAME_SMALL'][$i] . '"'
- . ' class="scroll_tab_struct" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/exec.png')
- . '"/>';
- $html .= '</td>';
-
- $html .= '<td width="1px">';
- $html .= '<input class="scroll_tab_checkbox" ';
- $html .= 'title="' . __('Hide') . '" ';
- $html .= 'id="check_vis_' . $GLOBALS['PMD_URL']["TABLE_NAME"][$i] . '" ';
- $html .= 'style="margin:0px;" type="checkbox" ';
- $html .= 'value="' . $GLOBALS['PMD_URL']["TABLE_NAME"][$i] . '"';
-
- if ((isset($tab_pos[$GLOBALS['PMD']["TABLE_NAME"][$i]])
- && $tab_pos[$GLOBALS['PMD']["TABLE_NAME"][$i]]["H"])
- || $display_page == -1
- ) {
- $html .= 'checked="checked"';
- }
- $html .= '/></td>';
-
- $html .= '<td class="pmd_Tabs" ';
- $html .= 'onmouseover="this.className=\'pmd_Tabs2\'" ';
- $html .= 'onmouseout="this.className=\'pmd_Tabs\'" ';
- $html .= 'pmd_url_table_name="'
- . $GLOBALS['PMD_URL']['TABLE_NAME'][$i] . '">';
- $html .= $GLOBALS['PMD_OUT']["TABLE_NAME"][$i];
- $html .= '</td>';
-
- $html .= '</tr>';
- }
-
- $html .= '</table>';
- $html .= '</div>'; // end id_scroll_tab
-
- $html .= '<div class="center">' . __('Number of tables:')
- . ' ' . $name_cnt . '</div>';
- $html .= '<div id="layer_menu_sizer" onmousedown="layer_menu_cur_click=1">';
- $html .= '<div class="floatleft">';
- $html .= '<img class="icon" data-right="' . $_SESSION['PMA_Theme']->getImgPath('pmd/resizeright.png');
- $html .= '" src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/resize.png') . '"/></div>';
- $html .= '</div>';
-
- $html .= '</div>'; // end layer_menu
-
- return $html;
+ return PMA\Template::get('database/designer/table_list')
+ ->render(
+ array(
+ 'tab_pos' => $tab_pos,
+ 'display_page' => $display_page
+ )
+ );
}
/**
@@ -550,222 +305,16 @@ function PMA_getHTMLTableList($tab_pos, $display_page)
function PMA_getDatabaseTables(
$tab_pos, $display_page, $tab_column, $tables_all_keys, $tables_pk_or_unique_keys
) {
- $html = '';
- for ($i = 0; $i < count($GLOBALS['PMD']["TABLE_NAME"]); $i++) {
- $t_n = $GLOBALS['PMD']["TABLE_NAME"][$i];
- $t_n_url = $GLOBALS['PMD_URL']["TABLE_NAME"][$i];
-
- $html .= '<input name="t_x[' . $t_n_url . ']" type="hidden" id="t_x_'
- . $t_n_url . '_" />';
- $html .= '<input name="t_y[' . $t_n_url . ']" type="hidden" id="t_y_'
- . $t_n_url . '_" />';
- $html .= '<input name="t_v[' . $t_n_url . ']" type="hidden" id="t_v_'
- . $t_n_url . '_" />';
- $html .= '<input name="t_h[' . $t_n_url . ']" type="hidden" id="t_h_'
- . $t_n_url . '_" />';
-
- $html .= '<table id="' . $t_n_url . '" cellpadding="0" cellspacing="0" ';
- $html .= 'class="pmd_tab" style="position:absolute;';
- $html .= 'left:';
- $html .= (isset($tab_pos[$t_n]) ? $tab_pos[$t_n]["X"] : rand(20, 700))
- . 'px;';
- $html .= 'top:';
- $html .= (isset($tab_pos[$t_n]) ? $tab_pos[$t_n]["Y"] : rand(20, 550))
- . 'px;';
- $html .= 'display:';
- $html .= (isset($tab_pos[$t_n]) || $display_page == -1) ? 'block;' : 'none;';
- $html .= 'z-index: 1;">';
-
- $html .= '<thead>';
- $html .= '<tr class="header">';
-
- if (isset($_REQUEST['query'])) {
- $html .= '<td class="select_all">';
- $html .= '<input class="select_all_1" type="checkbox" '
- . 'style="margin: 0px;" ';
- $html .= 'value="select_all_' . htmlspecialchars($t_n_url) . '" ';
- $html .= 'id="select_all_' . htmlspecialchars($t_n_url) . '" ';
- $html .= 'title="select all" pmd_url_table_name="'
- . htmlspecialchars($t_n_url) . '" ';
- $html .= 'pmd_out_owner="'
- . htmlspecialchars($GLOBALS['PMD_OUT']['OWNER'][$i]) . '">';
- $html .= '</td>';
- }
-
- $html .= '<td class="small_tab" ';
- $html .= 'id="id_hide_tbody_' . $t_n_url . '" ';
- $html .= 'table_name="' . htmlspecialchars($t_n_url)
- . '" onmouseover="this.className=\'small_tab2\';" ';
- $html .= 'onmouseout="this.className=\'small_tab\';" ';
- $html .= '>';
-
- // no space allowed here, between tags and content !!!
- // JavaScript function does require this
- if (! isset($tab_pos[$t_n]) || ! empty($tab_pos[$t_n]["V"])) {
- $html .= 'v';
- } else {
- $html .= '&gt;';
- }
-
- $html .= '</td>';
-
- $html .= '<td class="small_tab_pref small_tab_pref_1" ';
- $html .= 'table_name_small="' . $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i]
- . '" onmouseover="this.className='
- . '\'small_tab_pref2 small_tab_pref_1\';" ';
- $html .= 'onmouseout="this.className=\'small_tab_pref small_tab_pref_1\';" ';
- $html .= '>';
- $html .= '<img alt="" ';
- $html .= 'src="' . $_SESSION['PMA_Theme']->getImgPath('pmd/exec_small.png')
- . '" />';
- $html .= '</td>';
-
- $html .= '<td id="id_zag_' . htmlspecialchars($t_n_url)
- . '" class="tab_zag nowrap tab_zag_noquery" ';
- $html .= 'onmousedown="cur_click=document.getElementById(\''
- . $t_n_url . '\');" ';
- $html .= 'table_name="' . htmlspecialchars($t_n_url) . ''
- . '" query_set="' . (isset($_REQUEST['query']) ? 1 : 0 ) . '" ';
- $html .= '>';
- $html .= '<span class="owner">';
- $html .= $GLOBALS['PMD_OUT']["OWNER"][$i] . '.';
- $html .= '</span>';
- $html .= $GLOBALS['PMD_OUT']['TABLE_NAME_SMALL'][$i];
- $html .= '</td>';
-
- if (isset($_REQUEST['query'])) {
- $html .= '<td class="tab_zag tab_zag_query" ';
- $html .= 'id="id_zag_' . htmlspecialchars($t_n_url) . '_2" ';
- $html .= 'table_name="' . htmlspecialchars($t_n_url) . '" ';
- $html .= 'onmousedown="cur_click=document.getElementById(\''
- . htmlspecialchars($t_n_url) . '\');" ';
- $html .= '>';
- }
-
- $html .= '</tr>';
- $html .= '</thead>';
-
- $html .= '<tbody id="id_tbody_' . $t_n_url . '" ';
- if (isset($tab_pos[$t_n]) && empty($tab_pos[$t_n]["V"])) {
- $html .= 'style="display: none;"';
- }
- $html .= '>';
- $display_field = PMA_getDisplayField(
- $_GET['db'],
- $GLOBALS['PMD']["TABLE_NAME_SMALL"][$i]
+ return PMA\Template::get('database/designer/database_tables')
+ ->render(
+ array(
+ 'tab_pos' => $tab_pos,
+ 'display_page' => $display_page,
+ 'tab_column' => $tab_column,
+ 'tables_all_keys' => $tables_all_keys,
+ 'tables_pk_or_unique_keys' => $tables_pk_or_unique_keys
+ )
);
- for (
- $j = 0, $id_cnt = count($tab_column[$t_n]["COLUMN_ID"]);
- $j < $id_cnt;
- $j++
- ) {
- $html .= '<tr id="id_tr_'
- . $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i] . '.'
- . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . '" ';
-
- if ($display_field == $tab_column[$t_n]["COLUMN_NAME"][$j]) {
- $html .= 'class="tab_field_3" ';
- } else {
- $html .= 'class="tab_field" ';
- }
-
- $html .= 'onmouseover="old_class = this.className; ';
- $html .= 'this.className = \'tab_field_2\';" ';
- $html .= 'onmouseout="this.className = old_class;" ';
- $html .= 'click_field_param="';
- $html .= $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i] . ',';
- $html .= urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . ',';
-
- $tmpColumn = $t_n . "." . $tab_column[$t_n]["COLUMN_NAME"][$j];
-
- if (!PMA_Util::isForeignKeySupported($GLOBALS['PMD']['TABLE_TYPE'][$i])
- ) {
- $html .= (isset($tables_pk_or_unique_keys[$tmpColumn]) ? 1 : 0);
- } else {
- // if foreign keys are supported, it's not necessary that the
- // index is a primary key
- $html .= (isset($tables_all_keys[$tmpColumn]) ? 1 : 0);
- }
- $html .= '"';
- $html .= '>';
-
- if (isset($_REQUEST['query'])) {
- $html .= '<td class="select_all">';
- $html .= '<input class="select_all_store_col" value="'
- . htmlspecialchars($t_n_url)
- . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . '"';
- $html .= 'type="checkbox" id="select_' . htmlspecialchars($t_n_url)
- . '._' . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . '" ';
- $html .= 'style="margin: 0px;" title="select_'
- . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . '" ';
- $html .= 'store_column_param="'
- . urlencode($GLOBALS['PMD_OUT']["TABLE_NAME_SMALL"][$i]) . ','
- . htmlspecialchars($GLOBALS['PMD_OUT']["OWNER"][$i]) . ','
- . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . '"></td>';
- }
-
- $html .= '<td width="10px" colspan="3"';
- $html .= 'id="' . $t_n_url . '.'
- . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]) . '">';
- $html .= '<div class="nowrap">';
-
- if (isset($tables_pk_or_unique_keys[$t_n . "." . $tab_column[$t_n]["COLUMN_NAME"][$j]])) {
-
- $html .= '<img src="'
- . $_SESSION['PMA_Theme']->getImgPath('pmd/FieldKey_small.png')
- . '" alt="*" />';
- } else {
-
- $image = 'pmd/Field_small';
- if (strstr($tab_column[$t_n]["TYPE"][$j], 'char')
- || strstr($tab_column[$t_n]["TYPE"][$j], 'text')
- ) {
- $image .= '_char';
- } elseif (strstr($tab_column[$t_n]["TYPE"][$j], 'int')
- || strstr($tab_column[$t_n]["TYPE"][$j], 'float')
- || strstr($tab_column[$t_n]["TYPE"][$j], 'double')
- || strstr($tab_column[$t_n]["TYPE"][$j], 'decimal')
- ) {
- $image .= '_int';
- } elseif (strstr($tab_column[$t_n]["TYPE"][$j], 'date')
- || strstr($tab_column[$t_n]["TYPE"][$j], 'time')
- || strstr($tab_column[$t_n]["TYPE"][$j], 'year')
- ) {
- $image .= '_date';
- }
- $image .= '.png';
-
- $html .= '<img src="'
- . $_SESSION['PMA_Theme']->getImgPath($image) . '" alt="*" />';
- }
-
- $html .= htmlspecialchars(
- $tab_column[$t_n]["COLUMN_NAME"][$j] . " : "
- . $tab_column[$t_n]["TYPE"][$j],
- ENT_QUOTES
- );
- $html .= "</div>\n</td>\n";
-
- if (isset($_REQUEST['query'])) {
- $html .= '<td class="small_tab_pref small_tab_pref_click_opt" ';
- $html .= 'onmouseover="this.className='
- . '\'small_tab_pref2 small_tab_pref_click_opt\';" ';
- $html .= 'onmouseout="this.className='
- . '\'small_tab_pref small_tab_pref_click_opt\';" ';
- $html .= 'Click_option_param="pmd_optionse,'
- . urlencode($tab_column[$t_n]['COLUMN_NAME'][$j]) . ','
- . $GLOBALS['PMD_OUT']['TABLE_NAME_SMALL'][$i] . '" >';
- $html .= '<img src="'
- . $_SESSION['PMA_Theme']->getImgPath('pmd/exec_small.png')
- . '" title="options" alt="" /></td> ';
- }
- $html .= "</tr>";
- }
- $html .= "</tbody>";
- $html .= "</table>";
- }
-
- return $html;
}
/**
@@ -775,79 +324,7 @@ function PMA_getDatabaseTables(
*/
function PMA_getNewRelationPanel()
{
- $html = '<table id="layer_new_relation" style="display:none;" ';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%" ></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="168" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<strong>' . __('Create relation') . '</strong>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody id="foreign_relation">';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap"><strong>FOREIGN KEY</strong>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">on delete</td>';
- $html .= '<td width="102"><select name="on_delete" id="on_delete">';
- $html .= '<option value="nix" selected="selected">--</option>';
- $html .= '<option value="CASCADE">CASCADE</option>';
- $html .= '<option value="SET NULL">SET NULL</option>';
- $html .= '<option value="NO ACTION">NO ACTION</option>';
- $html .= '<option value="RESTRICT">RESTRICT</option>';
- $html .= '</select>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="nowrap">on update</td>';
- $html .= '<td><select name="on_update" id="on_update">';
- $html .= '<option value="nix" selected="selected">--</option>';
- $html .= '<option value="CASCADE">CASCADE</option>';
- $html .= '<option value="SET NULL">SET NULL</option>';
- $html .= '<option value="NO ACTION">NO ACTION</option>';
- $html .= '<option value="RESTRICT">RESTRICT</option>';
- $html .= '</select>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<input type="button" id="ok_new_rel_panel" class="butt" '
- . 'name="Button" ';
- $html .= 'value="' . __('OK') . '" />';
- $html .= '<input type="button" id="cancel_new_rel_panel" '
- . 'class="butt" name="Button" ';
- $html .= 'value="' . __('Cancel') . '" ';
- $html .= '/>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
- $html .= '</td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/new_relation_panel')->render();
}
/**
@@ -857,44 +334,7 @@ function PMA_getNewRelationPanel()
*/
function PMA_getDeleteRelationPanel()
{
- $html = '<table id="layer_upd_relation" style="display:none;" ';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%"></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="100%" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<tr>';
- $html .= '<td colspan="3" class="center nowrap">';
- $html .= '<strong>' . __('Delete relation') . '</strong>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td colspan="3" class="center nowrap">';
- $html .= '<input id="del_button" name="Button" type="button" class="butt" ';
- $html .= 'value="' . __('Delete') . '" />';
- $html .= '<input id="cancel_button" type="button" class="butt" name="Button" ';
- $html .= 'value="' . __('Cancel') . '" ';
- $html .= '/>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</table></td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/delete_relation_panel')->render();
}
/**
@@ -904,143 +344,7 @@ function PMA_getDeleteRelationPanel()
*/
function PMA_getOptionsPanel()
{
- $html = '<table id="pmd_optionse" style="display:none;" ';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
-
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%" ></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="168" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<td colspan="2" rowspan="2" id="option_col_name" ';
- $html .= 'class="center nowrap">';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody id="where">';
- $html .= '<tr><td class="center nowrap"><b>WHERE</b></td></tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Relation operator') . '</td>';
- $html .= '<td width="102"><select name="rel_opt" id="rel_opt">';
- $html .= '<option value="--" selected="selected"> -- </option>';
- $html .= '<option value="="> = </option>';
- $html .= '<option value="&gt;"> &gt; </option>';
- $html .= '<option value="&lt;"> &lt; </option>';
- $html .= '<option value="&gt;="> &gt;= </option>';
- $html .= '<option value="&lt;="> &lt;= </option>';
- $html .= '<option value="NOT"> NOT </option>';
- $html .= '<option value="IN"> IN </option>';
- $html .= '<option value="EXCEPT">' . __('Except') . '</option>';
- $html .= '<option value="NOT IN"> NOT IN </option>';
- $html .= '</select>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="nowrap">' . __('Value') . '<br />' . __('subquery');
- $html .= '</td>';
- $html .= '<td><textarea id="Query" value="" cols="18"></textarea>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="center nowrap"><b>' . __('Rename to') . '</b></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('New name') . '</td>';
- $html .= '<td width="102"><input type="text" value="" id="new_name"/></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="center nowrap"><b>' . __('Aggregate') . '</b></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Operator') . '</td>';
- $html .= '<td width="102"><select name="operator" id="operator">';
- $html .= '<option value="---" selected="selected">---</option>';
- $html .= '<option value="sum" > SUM </option>';
- $html .= '<option value="min"> MIN </option>';
- $html .= '<option value="max"> MAX </option>';
- $html .= '<option value="avg"> AVG </option>';
- $html .= '<option value="count"> COUNT </option>';
- $html .= '</select>';
- $html .= '</td></tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="center nowrap"><b>GROUP BY</b></td>';
- $html .= '<td><input type="checkbox" value="groupby" id="groupby"/></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="center nowrap"><b>ORDER BY</b></td>';
- $html .= '<td><input type="checkbox" value="orderby" id="orderby"/></td>';
- $html .= '</tr>';
- $html .= '<tr><td class="center nowrap"><b>HAVING</b></td></tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Operator') . '</td>';
- $html .= '<td width="102"><select name="h_operator" id="h_operator">';
- $html .= '<option value="---" selected="selected">---</option>';
- $html .= '<option value="None" >' . __('None') . '</option>';
- $html .= '<option value="sum" > SUM </option>';
- $html .= '<option value="min"> MIN </option>';
- $html .= '<option value="max"> MAX </option>';
- $html .= '<option value="avg"> AVG </option>';
- $html .= '<option value="count"> COUNT </option>';
- $html .= '</select>';
- $html .= '</td></tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Relation operator') . '</td>';
- $html .= '<td width="102"><select name="h_rel_opt" id="h_rel_opt">';
- $html .= '<option value="--" selected="selected"> -- </option>';
- $html .= '<option value="="> = </option>';
- $html .= '<option value="&gt;"> &gt; </option>';
- $html .= '<option value="&lt;"> &lt; </option>';
- $html .= '<option value="&gt;="> &gt;= </option>';
- $html .= '<option value="&lt;="> &lt;= </option>';
- $html .= '<option value="NOT"> NOT </option>';
- $html .= '<option value="IN"> IN </option>';
- $html .= '<option value="EXCEPT">' . __('Except') . '</option>';
- $html .= '<option value="NOT IN"> NOT IN </option>';
- $html .= '</select>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">';
- $html .= __('Value') . '<br/>';
- $html .= __('subquery');
- $html .= '</td>';
- $html .= '<td width="102">';
- $html .= '<textarea id="having" value="" cols="18"></textarea>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<input type="button" id="ok_add_object" class="butt" name="Button" ';
- $html .= 'value="' . __('OK') . '" />';
- $html .= '<input type="button" id="cancel_close_option" class="butt" ';
- $html .= 'name="Button" value="' . __('Cancel') . '" ';
- $html .= '/>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
- $html .= '</td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/options_panel')->render();
}
/**
@@ -1050,60 +354,7 @@ function PMA_getOptionsPanel()
*/
function PMA_getRenameToPanel()
{
- $html = '<table id="query_rename_to" style="display:none;" ';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
-
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%" ></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="168" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<strong>' . __('Rename to') . '</strong>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody id="rename_to">';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('New name') . '</td>';
- $html .= '<td width="102">';
- $html .= '<input type="text" value="" id="e_rename"/>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<input type="button" id="ok_edit_rename" class="butt" name="Button" ';
- $html .= 'value="' . __('OK') . '" />';
- $html .= '<input type="button" class="butt" name="Button" ';
- $html .= 'value="' . __('Cancel') . '" ';
- $html .= 'onclick="document.getElementById(\'query_rename_to\').style.display'
- . ' = \'none\';" />';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
- $html .= '</td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/rename_to_panel')->render();
}
/**
@@ -1113,86 +364,7 @@ function PMA_getRenameToPanel()
*/
function PMA_getHavingQueryPanel()
{
- $html = '<table id="query_having" style="display:none;" ';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%" ></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="168" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap"><strong>HAVING</strong></td>';
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody id="rename_to">';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Operator') . '</td>';
- $html .= '<td width="102"><select name="hoperator" id="hoperator">';
- $html .= '<option value="---" selected="selected">---</option>';
- $html .= '<option value="None" > None </option>';
- $html .= '<option value="sum" > SUM </option>';
- $html .= '<option value="min"> MIN </option>';
- $html .= '<option value="max"> MAX </option>';
- $html .= '<option value="avg"> AVG </option>';
- $html .= '<option value="count"> COUNT </option>';
- $html .= '</select>';
- $html .= '</td></tr>';
- $html .= '<tr>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Operator') . '</td>';
- $html .= '<td width="102"><select name="hrel_opt" id="hrel_opt">';
- $html .= '<option value="--" selected="selected"> -- </option>';
- $html .= '<option value="="> = </option>';
- $html .= '<option value="&gt;"> &gt; </option>';
- $html .= '<option value="&lt;"> &lt; </option>';
- $html .= '<option value="&gt;="> &gt;= </option>';
- $html .= '<option value="&lt;="> &lt;= </option>';
- $html .= '<option value="NOT"> NOT </option>';
- $html .= '<option value="IN"> IN </option>';
- $html .= '<option value="EXCEPT">' . __('Except') . '</option>';
- $html .= '<option value="NOT IN"> NOT IN </option>';
- $html .= '</select>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="nowrap">' . __('Value') . ' <br />' . __('subquery');
- $html .= '</td>';
- $html .= '<td><textarea id="hQuery" value="" cols="18"></textarea>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<input type="button" id="ok_edit_having" class="butt" name="Button" ';
- $html .= 'value="' . __('OK') . '" />';
- $html .= '<input type="button" class="butt" name="Button" ';
- $html .= 'value="' . __('Cancel') . '" ';
- $html .= 'onclick="document.getElementById(\'query_having\').style.display'
- . ' = \'none\';" />';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
- $html .= '</td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/having_query_panel')->render();
}
/**
@@ -1202,66 +374,7 @@ function PMA_getHavingQueryPanel()
*/
function PMA_getAggregateQueryPanel()
{
- $html = '<table id="query_Aggregate" style="display:none;"';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
-
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%" ></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="168" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<strong>' . __('Aggregate') . '</strong>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Operator') . '</td>';
- $html .= '<td width="102">';
- $html .= '<select name="operator" id="e_operator">';
- $html .= '<option value="---" selected="selected">---</option>';
- $html .= '<option value="sum" > SUM </option>';
- $html .= '<option value="min"> MIN </option>';
- $html .= '<option value="max"> MAX </option>';
- $html .= '<option value="avg"> AVG </option>';
- $html .= '<option value="count"> COUNT </option>';
- $html .= '</select>';
- $html .= '</td></tr>';
- $html .= '</tbody>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<input type="button" id="ok_edit_Aggr" class="butt" name="Button" ';
- $html .= 'value="' . __('OK') . '" />';
- $html .= '<input type="button" class="butt" name="Button"';
- $html .= 'value="' . __('Cancel') . '" ';
- $html .= 'onclick="document.getElementById(\'query_Aggregate\').style.display'
- . ' = \'none\';" />';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
- $html .= '</td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/aggregate_query_panel')->render();
}
/**
@@ -1271,75 +384,7 @@ function PMA_getAggregateQueryPanel()
*/
function PMA_getWhereQueryPanel()
{
- $html = '<table id="query_where" style="display:none;"';
- $html .= 'width="5%" cellpadding="0" cellspacing="0">';
- $html .= '<tbody>';
-
- $html .= '<tr>';
- $html .= '<td class="frams1" width="10px"></td>';
- $html .= '<td class="frams5" width="99%" ></td>';
- $html .= '<td class="frams2" width="10px"><div class="bor"></div></td>';
- $html .= '</tr>';
-
- $html .= '<tr>';
- $html .= '<td class="frams8"></td>';
- $html .= '<td class="input_tab">';
- $html .= '<table width="168" class="center" cellpadding="2" cellspacing="0">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap"><strong>WHERE</strong></td>';
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody id="rename_to">';
- $html .= '<tr>';
- $html .= '<td width="58" class="nowrap">' . __('Operator') . '</td>';
- $html .= '<td width="102"><select name="erel_opt" id="erel_opt">';
- $html .= '<option value="--" selected="selected"> -- </option>';
- $html .= '<option value="=" > = </option>';
- $html .= '<option value="&gt;"> &gt; </option>';
- $html .= '<option value="&lt;"> &lt; </option>';
- $html .= '<option value="&gt;="> &gt;= </option>';
- $html .= '<option value="&lt;="> &lt;= </option>';
- $html .= '<option value="NOT"> NOT </option>';
- $html .= '<option value="IN"> IN </option>';
- $html .= '<option value="EXCEPT">' . __('Except') . '</option>';
- $html .= '<option value="NOT IN"> NOT IN </option>';
- $html .= '</select>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="nowrap">' . __('Value') . '<br />' . __('subquery');
- $html .= '</td>';
- $html .= '<td><textarea id="eQuery" value="" cols="18"></textarea>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '<tbody>';
- $html .= '<tr>';
- $html .= '<td colspan="2" class="center nowrap">';
- $html .= '<input type="button" id="ok_edit_where" class="butt" name="Button" ';
- $html .= 'value="' . __('OK') . '" />';
- $html .= '<input type="button" class="butt" name="Button" ';
- $html .= 'value="' . __('Cancel') . '" ';
- $html .= 'onclick="document.getElementById(\'query_where\').style.display'
- . ' = \'none\'" />';
- $html .= '</td>';
- $html .= '</tr>';
-
- $html .= '</tbody>';
- $html .= '</table>';
- $html .= '</td>';
- $html .= '<td class="frams6"></td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td class="frams4"><div class="bor"></div></td>';
- $html .= '<td class="frams7"></td>';
- $html .= '<td class="frams3"></td>';
- $html .= '</tr>';
- $html .= '</tbody>';
- $html .= '</table>';
-
- return $html;
+ return PMA\Template::get('database/designer/where_query_panel')->render();
}
/**
@@ -1349,49 +394,5 @@ function PMA_getWhereQueryPanel()
*/
function PMA_getQueryDetails()
{
- $html = '<div class="panel">';
- $html .= '<div style="clear:both;"></div>';
- $html .= '<div id="ab"></div>';
- $html .= '<div style="clear:both;"></div>';
- $html .= '</div>';
- $html .= '<a class="trigger" href="#">' . __('Active options') . '</a>';
- $html .= '<div id="filter"></div>';
- $html .= '<div id="box">';
- $html .= '<span id="boxtitle"></span>';
- $html .= '<form method="post" action="db_qbe.php">';
- $html .= '<textarea cols="80" name="sql_query" id="textSqlquery"'
- . ' rows="15"></textarea><div id="tblfooter">';
- $html .= ' <input type="submit" name="submit_sql" class="btn" />';
- $html .= ' <input type="button" name="cancel" value="'
- . __('Cancel') . '" onclick="closebox()" class="btn" />';
- $html .= PMA_URL_getHiddenInputs($_GET['db']);
- $html .= '</div></p>';
- $html .= '</form></div>';
-
- return $html;
-}
-
-/**
- * Return HTML to fetch some images eagerly.
- *
- * @return string html
- */
-function PMA_getCacheImages()
-{
- $html = '<img src="';
- $html .= $_SESSION['PMA_Theme']->getImgPath('pmd/2leftarrow_m.png');
- $html .= '" width="0" height="0" alt="" />';
- $html .= '<img src="';
- $html .= $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow1.png');
- $html .= '" width="0" height="0" alt="" />';
- $html .= '<img src="';
- $html .= $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow2.png');
- $html .= '" width="0" height="0" alt="" />';
- $html .= '<img src="';
- $html .= $_SESSION['PMA_Theme']->getImgPath('pmd/uparrow2_m.png');
- $html .= '" width="0" height="0" alt="" />';
- $html .= '<div id="PMA_disable_floating_menubar"></div>';
-
- return $html;
+ return PMA\Template::get('database/designer/query_details')->render();
}
-?>
diff --git a/libraries/db_info.inc.php b/libraries/db_info.inc.php
deleted file mode 100644
index 4640152c69..0000000000
--- a/libraries/db_info.inc.php
+++ /dev/null
@@ -1,248 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Gets the list of the table in the current db and information about these
- * tables if possible
- *
- * fills tooltip arrays and provides $tables, $num_tables, $is_show_stats
- * and $db_is_system_schema
- *
- * speedup view on locked tables
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * limits for table list
- */
-if (! isset($_SESSION['tmpval']['table_limit_offset'])
- || $_SESSION['tmpval']['table_limit_offset_db'] != $db
-) {
- $_SESSION['tmpval']['table_limit_offset'] = 0;
- $_SESSION['tmpval']['table_limit_offset_db'] = $db;
-}
-if (isset($_REQUEST['pos'])) {
- $_SESSION['tmpval']['table_limit_offset'] = (int) $_REQUEST['pos'];
-}
-$pos = $_SESSION['tmpval']['table_limit_offset'];
-
-PMA_Util::checkParameters(array('db'));
-
-/**
- * @global bool whether to display extended stats
- */
-$is_show_stats = $cfg['ShowStats'];
-
-/**
- * @global bool whether selected db is information_schema
- */
-$db_is_system_schema = false;
-
-if ($GLOBALS['dbi']->isSystemSchema($db)) {
- $is_show_stats = false;
- $db_is_system_schema = true;
-}
-
-/**
- * @global array information about tables in db
- */
-$tables = array();
-
-$tooltip_truename = array();
-$tooltip_aliasname = array();
-
-// Special speedup for newer MySQL Versions (in 4.0 format changed)
-if (true === $cfg['SkipLockedTables'] && ! PMA_DRIZZLE) {
- $db_info_result = $GLOBALS['dbi']->query(
- 'SHOW OPEN TABLES FROM ' . PMA_Util::backquote($db) . ';'
- );
-
- // Blending out tables in use
- if ($db_info_result && $GLOBALS['dbi']->numRows($db_info_result) > 0) {
- while ($tmp = $GLOBALS['dbi']->fetchAssoc($db_info_result)) {
- // if in use, memorize table name
- if ($tmp['In_use'] > 0) {
- $sot_cache[$tmp['Table']] = true;
- }
- }
- $GLOBALS['dbi']->freeResult($db_info_result);
-
- if (isset($sot_cache)) {
- $db_info_result = false;
-
- $tblGroupSql = "";
- $whereAdded = false;
- if (PMA_isValid($_REQUEST['tbl_group'])) {
- $group = PMA_Util::escapeMysqlWildcards($_REQUEST['tbl_group']);
- $groupWithSeparator = PMA_Util::escapeMysqlWildcards(
- $_REQUEST['tbl_group']
- . $GLOBALS['cfg']['NavigationTreeTableSeparator']
- );
- $tblGroupSql .= " WHERE ("
- . PMA_Util::backquote('Tables_in_' . $db)
- . " LIKE '" . $groupWithSeparator . "%'"
- . " OR "
- . PMA_Util::backquote('Tables_in_' . $db)
- . " LIKE '" . $group . "')";
- $whereAdded = true;
- }
- if (PMA_isValid($_REQUEST['tbl_type'], array('table', 'view'))) {
- $tblGroupSql .= $whereAdded ? " AND" : " WHERE";
- if ($_REQUEST['tbl_type'] == 'view') {
- $tblGroupSql .= " `Table_type` != 'BASE TABLE'";
- } else {
- $tblGroupSql .= " `Table_type` = 'BASE TABLE'";
- }
- }
- $db_info_result = $GLOBALS['dbi']->query(
- 'SHOW FULL TABLES FROM ' . PMA_Util::backquote($db) . $tblGroupSql,
- null, PMA_DatabaseInterface::QUERY_STORE
- );
- unset($tblGroupSql, $whereAdded);
-
- if ($db_info_result && $GLOBALS['dbi']->numRows($db_info_result) > 0) {
- while ($tmp = $GLOBALS['dbi']->fetchRow($db_info_result)) {
- if (! isset($sot_cache[$tmp[0]])) {
- $sts_result = $GLOBALS['dbi']->query(
- "SHOW TABLE STATUS FROM " . PMA_Util::backquote($db)
- . " LIKE '" . PMA_Util::sqlAddSlashes($tmp[0], true)
- . "';"
- );
- $sts_tmp = $GLOBALS['dbi']->fetchAssoc($sts_result);
- $GLOBALS['dbi']->freeResult($sts_result);
- unset($sts_result);
-
- $tableArray = $GLOBALS['dbi']->copyTableProperties(
- array($sts_tmp), $db
- );
- $tables[$sts_tmp['Name']] = $tableArray[0];
- } else { // table in use
- $tables[$tmp[0]] = array(
- 'TABLE_NAME' => $tmp[0],
- 'ENGINE' => '',
- 'TABLE_TYPE' => '',
- 'TABLE_ROWS' => 0,
- );
- }
- }
- if ($GLOBALS['cfg']['NaturalOrder']) {
- uksort($tables, 'strnatcasecmp');
- }
-
- $sot_ready = true;
- } elseif ($db_info_result) {
- $GLOBALS['dbi']->freeResult($db_info_result);
- }
- unset($sot_cache);
- }
- unset($tmp);
- } elseif ($db_info_result) {
- $GLOBALS['dbi']->freeResult($db_info_result);
- }
-}
-
-if (! isset($sot_ready)) {
-
- // Set some sorting defaults
- $sort = 'Name';
- $sort_order = 'ASC';
-
- if (isset($_REQUEST['sort'])) {
- $sortable_name_mappings = array(
- 'table' => 'Name',
- 'records' => 'Rows',
- 'type' => 'Engine',
- 'collation' => 'Collation',
- 'size' => 'Data_length',
- 'overhead' => 'Data_free',
- 'creation' => 'Create_time',
- 'last_update' => 'Update_time',
- 'last_check' => 'Check_time'
- );
-
- // Make sure the sort type is implemented
- if (isset($sortable_name_mappings[$_REQUEST['sort']])) {
- $sort = $sortable_name_mappings[$_REQUEST['sort']];
- if ($_REQUEST['sort_order'] == 'DESC') {
- $sort_order = 'DESC';
- }
- }
- }
-
- $tbl_group = false;
- $groupWithSeparator = false;
- $tbl_type = null;
- $limit_offset = 0;
- $limit_count = false;
- $groupTable = array();
-
- if (! empty($_REQUEST['tbl_group']) || ! empty($_REQUEST['tbl_type'])) {
- if (! empty($_REQUEST['tbl_type'])) {
- // only tables for selected type
- $tbl_type = $_REQUEST['tbl_type'];
- }
- if (! empty($_REQUEST['tbl_group'])) {
- // only tables for selected group
- $tbl_group = $_REQUEST['tbl_group'];
- // include the table with the exact name of the group if such exists
- $groupTable = $GLOBALS['dbi']->getTablesFull(
- $db, $tbl_group, false, null, $limit_offset,
- $limit_count, $sort, $sort_order, $tbl_type
- );
- $groupWithSeparator = $tbl_group
- . $GLOBALS['cfg']['NavigationTreeTableSeparator'];
- }
- } else {
- // all tables in db
- // - get the total number of tables
- // (needed for proper working of the MaxTableList feature)
- $tables = $GLOBALS['dbi']->getTables($db);
- $total_num_tables = count($tables);
- if (isset($sub_part) && $sub_part == '_export') {
- // (don't fetch only a subset if we are coming from db_export.php,
- // because I think it's too risky to display only a subset of the
- // table names when exporting a db)
- /**
- *
- * @todo Page selector for table names?
- */
- } else {
- // fetch the details for a possible limited subset
- $limit_offset = $pos;
- $limit_count = true;
- }
- }
- $tables = array_merge(
- $groupTable,
- $GLOBALS['dbi']->getTablesFull(
- $db, $groupWithSeparator, ($groupWithSeparator != false), null,
- $limit_offset, $limit_count, $sort, $sort_order, $tbl_type
- )
- );
-}
-
-/**
- * @global int count of tables in db
- */
-$num_tables = count($tables);
-// (needed for proper working of the MaxTableList feature)
-if (! isset($total_num_tables)) {
- $total_num_tables = $num_tables;
-}
-
-/**
- * cleanup
- */
-unset($each_table, $db_info_result);
-
-/**
- * If coming from a Show MySQL link on the home page,
- * put something in $sub_part
- */
-if (empty($sub_part)) {
- $sub_part = '_structure';
-}
-?>
diff --git a/libraries/db_printview.lib.php b/libraries/db_printview.lib.php
deleted file mode 100644
index 39e263f16b..0000000000
--- a/libraries/db_printview.lib.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Set of functions related to db printview
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Function to get html for one of the db dates
- *
- * @param string $title the title
- * @param string $date which date to display
- *
- * @return string html content
- */
-function PMA_getHtmlForOneDate($title, $date)
-{
- $html = '<tr>'
- . '<td class="right">' . $title . '</td>'
- . '<td class="right">'
- . PMA_Util::localisedDate(strtotime($date))
- . '</td>'
- . '</tr>';
- return $html;
-}
-?>
diff --git a/libraries/db_table_exists.lib.php b/libraries/db_table_exists.lib.php
index 5f93e57730..b95f227593 100644
--- a/libraries/db_table_exists.lib.php
+++ b/libraries/db_table_exists.lib.php
@@ -57,7 +57,7 @@ if (empty($is_table)
// Not a valid table name -> back to the db_sql.php
if (/*overload*/mb_strlen($table)) {
- $is_table = isset(PMA_Table::$cache[$db][$table]);
+ $is_table = $GLOBALS['dbi']->getCachedTableContent("${db}.${table}", false);
if (! $is_table) {
$_result = $GLOBALS['dbi']->tryQuery(
@@ -103,4 +103,3 @@ if (empty($is_table)
}
}
} // end if (ensures table exists)
-?>
diff --git a/libraries/dbi/DBIDrizzle.class.php b/libraries/dbi/DBIDrizzle.class.php
index 9224dbb85d..3f37e7b3ad 100644
--- a/libraries/dbi/DBIDrizzle.class.php
+++ b/libraries/dbi/DBIDrizzle.class.php
@@ -125,28 +125,27 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
$client_flags |= DRIZZLE_CAPABILITIES_SSL;
}
- if (! $server) {
- $link = @$this->_realConnect(
- $drizzle, $cfg['Server']['host'],
- $server_port, $server_socket, $user,
- $password, false, $client_flags
- );
- // Retry with empty password if we're allowed to
- if ($link == false && isset($cfg['Server']['nopassword'])
- && $cfg['Server']['nopassword'] && ! $is_controluser
- ) {
- $link = @$this->_realConnect(
- $drizzle, $cfg['Server']['host'], $server_port, $server_socket,
- $user, null, false, $client_flags
- );
- }
- } else {
- $link = @$this->_realConnect(
+ if ($server) {
+ return @$this->_realConnect(
$drizzle, $server['host'], $server_port, $server_socket,
$user, $password
);
}
+ $link = @$this->_realConnect(
+ $drizzle, $cfg['Server']['host'], $server_port, $server_socket, $user,
+ $password, false, $client_flags
+ );
+ // Retry with empty password if we're allowed to
+ if ($link == false && isset($cfg['Server']['nopassword'])
+ && $cfg['Server']['nopassword'] && ! $is_controluser
+ ) {
+ $link = @$this->_realConnect(
+ $drizzle, $cfg['Server']['host'], $server_port, $server_socket,
+ $user, null, false, $client_flags
+ );
+ }
+
return $link;
}
@@ -154,7 +153,7 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
* selects given database
*
* @param string $dbname database name to select
- * @param PMA_DrizzleCom $link connection object
+ * @param PMA_DrizzleCon $link connection object
*
* @return bool
*/
@@ -184,10 +183,10 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
/**
* Run the multi query and output the results
*
- * @param object $link connection object
- * @param string $query multi query statement to execute
+ * @param resource $link connection object
+ * @param string $query multi query statement to execute
*
- * @return result collection | boolean(false)
+ * @return array|bool
*/
public function realMultiQuery($link, $query)
{
@@ -260,7 +259,7 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
/**
* Check if there are any more query results from a multi query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return bool false
*/
@@ -276,7 +275,7 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
/**
* Prepare next result from multi_query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return bool false
*/
@@ -381,7 +380,8 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
*/
public function affectedRows($link)
{
- return $link->affectedRows();
+ $affectedRows = $link->affectedRows();
+ return $affectedRows !== false ? $affectedRows : 0;
}
/**
@@ -395,34 +395,6 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
{
// Build an associative array for a type look up
$typeAr = array();
- /*$typeAr[DRIZZLE_COLUMN_TYPE_DECIMAL] = 'real';
- $typeAr[DRIZZLE_COLUMN_TYPE_NEWDECIMAL] = 'real';
- $typeAr[DRIZZLE_COLUMN_TYPE_BIT] = 'int';
- $typeAr[DRIZZLE_COLUMN_TYPE_TINY] = 'int';
- $typeAr[DRIZZLE_COLUMN_TYPE_SHORT] = 'int';
- $typeAr[DRIZZLE_COLUMN_TYPE_LONG] = 'int';
- $typeAr[DRIZZLE_COLUMN_TYPE_FLOAT] = 'real';
- $typeAr[DRIZZLE_COLUMN_TYPE_DOUBLE] = 'real';
- $typeAr[DRIZZLE_COLUMN_TYPE_NULL] = 'null';
- $typeAr[DRIZZLE_COLUMN_TYPE_TIMESTAMP] = 'timestamp';
- $typeAr[DRIZZLE_COLUMN_TYPE_LONGLONG] = 'int';
- $typeAr[DRIZZLE_COLUMN_TYPE_INT24] = 'int';
- $typeAr[DRIZZLE_COLUMN_TYPE_DATE] = 'date';
- $typeAr[DRIZZLE_COLUMN_TYPE_TIME] = 'date';
- $typeAr[DRIZZLE_COLUMN_TYPE_DATETIME] = 'datetime';
- $typeAr[DRIZZLE_COLUMN_TYPE_YEAR] = 'year';
- $typeAr[DRIZZLE_COLUMN_TYPE_NEWDATE] = 'date';
- $typeAr[DRIZZLE_COLUMN_TYPE_ENUM] = 'unknown';
- $typeAr[DRIZZLE_COLUMN_TYPE_SET] = 'unknown';
- $typeAr[DRIZZLE_COLUMN_TYPE_VIRTUAL] = 'unknown';
- $typeAr[DRIZZLE_COLUMN_TYPE_TINY_BLOB] = 'blob';
- $typeAr[DRIZZLE_COLUMN_TYPE_MEDIUM_BLOB] = 'blob';
- $typeAr[DRIZZLE_COLUMN_TYPE_LONG_BLOB] = 'blob';
- $typeAr[DRIZZLE_COLUMN_TYPE_BLOB] = 'blob';
- $typeAr[DRIZZLE_COLUMN_TYPE_VAR_STRING] = 'string';
- $typeAr[DRIZZLE_COLUMN_TYPE_VARCHAR] = 'string';
- $typeAr[DRIZZLE_COLUMN_TYPE_STRING] = 'string';
- $typeAr[DRIZZLE_COLUMN_TYPE_GEOMETRY] = 'geometry';*/
$typeAr[DRIZZLE_COLUMN_TYPE_DRIZZLE_BLOB] = 'blob';
$typeAr[DRIZZLE_COLUMN_TYPE_DRIZZLE_DATE] = 'date';
@@ -580,4 +552,3 @@ class PMA_DBI_Drizzle implements PMA_DBI_Extension
return false;
}
}
-?>
diff --git a/libraries/dbi/DBIDummy.class.php b/libraries/dbi/DBIDummy.class.php
index 5f86921724..d288aa7cbb 100644
--- a/libraries/dbi/DBIDummy.class.php
+++ b/libraries/dbi/DBIDummy.class.php
@@ -26,10 +26,6 @@ $GLOBALS['dummy_queries'] = array(
'result' => array(array('pma_test@localhost')),
),
array(
- 'query' => "SHOW VARIABLES LIKE 'lower_case_table_names'",
- 'result' => array(array('lower_case_table_names', '1'))
- ),
- array(
'query' => 'SELECT 1 FROM mysql.user LIMIT 1',
'result' => array(array('1')),
),
@@ -120,9 +116,9 @@ $GLOBALS['dummy_queries'] = array(
)
),
array(
- 'query' => 'SHOW VARIABLES LIKE \'collation_server\'',
+ 'query' => 'SELECT @@collation_server',
'result' => array(
- array('collation_server', 'utf8_general_ci'),
+ array('utf8_general_ci'),
)
),
array(
@@ -130,6 +126,12 @@ $GLOBALS['dummy_queries'] = array(
'result' => array(),
),
array(
+ 'query' => 'SHOW SESSION VARIABLES LIKE \'FOREIGN_KEY_CHECKS\';',
+ 'result' => array(
+ array('foreign_key_checks', 'ON')
+ ),
+ ),
+ array(
'query' => 'SHOW TABLES FROM `pma_test`;',
'result' => array(
array('table1'),
@@ -262,7 +264,7 @@ $GLOBALS['dummy_queries'] = array(
. ' `CHECKSUM` AS `Checksum`, `CREATE_OPTIONS` AS `Create_options`,'
. ' `TABLE_COMMENT` AS `Comment`'
. ' FROM `information_schema`.`TABLES` t'
- . ' WHERE `TABLE_SCHEMA` IN (\'pma_test\')'
+ . ' WHERE BINARY `TABLE_SCHEMA` IN (\'pma_test\')'
. ' AND t.`TABLE_NAME` = \'table1\' ORDER BY Name ASC',
'columns' => array(
'TABLE_CATALOG', 'TABLE_SCHEMA', 'TABLE_NAME', 'TABLE_TYPE', 'ENGINE',
@@ -422,10 +424,10 @@ $GLOBALS['dummy_queries'] = array(
)
),
array(
- 'query' => 'SHOW VARIABLES LIKE \'collation_database\'',
- 'columns' => array('variable_name', 'variable_value'),
+ 'query' => 'SELECT @@collation_database',
+ 'columns' => array('@@collation_database'),
'result' => array(
- array('foo', 'bar'),
+ array('bar'),
)
),
array(
@@ -524,6 +526,126 @@ $GLOBALS['dummy_queries'] = array(
array(1),
)
),
+ array(
+ 'query' => "SELECT `PARTITION_METHOD` "
+ . "FROM `information_schema`.`PARTITIONS` "
+ . "WHERE `TABLE_SCHEMA` = 'db' AND `TABLE_NAME` = 'table'",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SHOW PLUGINS",
+ 'result' => array(
+ array('Name' => 'partition')
+ )
+ ),
+ array(
+ 'query' => "SHOW FULL TABLES FROM `default` WHERE `Table_type`='BASE TABLE'",
+ 'result' => array(
+ array("test1", "BASE TABLE"),
+ array("test2", "BASE TABLE"),
+ )
+ ),
+ array(
+ 'query' => "SHOW FULL TABLES FROM `default` "
+ . "WHERE `Table_type`!='BASE TABLE'",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SHOW FUNCTION STATUS WHERE `Db`='default'",
+ 'result' => array(array("Name" => "testFunction"))
+ ),
+ array(
+ 'query' => "SHOW PROCEDURE STATUS WHERE `Db`='default'",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SHOW EVENTS FROM `default`",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "FLUSH PRIVILEGES",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`db` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`columns_priv` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`tables_priv` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`procs_priv` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => 'DELETE FROM `mysql`.`db` WHERE `host` = "" '
+ . 'AND `Db` = "" AND `User` = "" LIMIT 1',
+ 'result' => true
+ ),
+ array(
+ 'query' => 'DELETE FROM `mysql`.`columns_priv` WHERE '
+ . '`host` = "" AND `Db` = "" AND `User` = "" LIMIT 1',
+ 'result' => true
+ ),
+ array(
+ 'query' => 'DELETE FROM `mysql`.`tables_priv` WHERE '
+ . '`host` = "" AND `Db` = "" AND `User` = "" AND Table_name = "" '
+ . 'LIMIT 1',
+ 'result' => true
+ ),
+ array(
+ 'query' => 'DELETE FROM `mysql`.`procs_priv` WHERE '
+ . '`host` = "" AND `Db` = "" AND `User` = "" AND `Routine_name` = "" '
+ . 'AND `Routine_type` = "" LIMIT 1',
+ 'result' => true
+ ),
+ array(
+ 'query' => 'SELECT `plugin` FROM `mysql`.`user` WHERE '
+ . '`User` = "pma_username" AND `Host` = "pma_hostname" LIMIT 1',
+ 'result' => array()
+ ),
+ array(
+ 'query' => 'SELECT @@default_authentication_plugin',
+ 'result' => array(array('@@default_authentication_plugin' => 'mysql_native_password'))
+ ),
+ array(
+ 'query' => "SELECT TABLE_NAME FROM information_schema.VIEWS WHERE "
+ . "TABLE_SCHEMA = 'db' AND TABLE_NAME = 'table'",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT *, `TABLE_SCHEMA` AS `Db`, "
+ . "`TABLE_NAME` AS `Name`, `TABLE_TYPE` AS `TABLE_TYPE`, "
+ . "`ENGINE` AS `Engine`, `ENGINE` AS `Type`, "
+ . "`VERSION` AS `Version`, `ROW_FORMAT` AS `Row_format`, "
+ . "`TABLE_ROWS` AS `Rows`, `AVG_ROW_LENGTH` AS `Avg_row_length`, "
+ . "`DATA_LENGTH` AS `Data_length`, "
+ . "`MAX_DATA_LENGTH` AS `Max_data_length`, "
+ . "`INDEX_LENGTH` AS `Index_length`, `DATA_FREE` AS `Data_free`, "
+ . "`AUTO_INCREMENT` AS `Auto_increment`, "
+ . "`CREATE_TIME` AS `Create_time`, "
+ . "`UPDATE_TIME` AS `Update_time`, `CHECK_TIME` AS `Check_time`, "
+ . "`TABLE_COLLATION` AS `Collation`, `CHECKSUM` AS `Checksum`, "
+ . "`CREATE_OPTIONS` AS `Create_options`, "
+ . "`TABLE_COMMENT` AS `Comment` "
+ . "FROM `information_schema`.`TABLES` t "
+ . "WHERE BINARY `TABLE_SCHEMA` IN ('db') "
+ . "AND t.`TABLE_NAME` = 'table' ORDER BY Name ASC",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SHOW TABLE STATUS FROM `db` WHERE `Name` LIKE 'table%'",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT @@have_partitioning;",
+ 'result' => array()
+ )
);
/**
* Current database.
@@ -537,6 +659,9 @@ $GLOBALS['cfg']['DBG']['sql'] = false;
if (! defined('PMA_DRIZZLE')) {
define('PMA_DRIZZLE', 0);
}
+if (! defined('PMA_MARIADB')) {
+ define('PMA_MARIADB', 0);
+}
/**
* Fake database driver for testing purposes
@@ -572,8 +697,8 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* selects given database
*
- * @param string $dbname name of db to select
- * @param object $link mysql link resource
+ * @param string $dbname name of db to select
+ * @param resource $link mysql link resource
*
* @return bool
*/
@@ -586,9 +711,9 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* runs a query and returns the result
*
- * @param string $query query to run
- * @param object $link mysql link resource
- * @param int $options query options
+ * @param string $query query to run
+ * @param resource $link mysql link resource
+ * @param int $options query options
*
* @return mixed
*/
@@ -614,10 +739,10 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* Run the multi query and output the results
*
- * @param object $link connection object
- * @param string $query multi query statement to execute
+ * @param resource $link connection object
+ * @param string $query multi query statement to execute
*
- * @return result collection | boolean(false)
+ * @return array|bool
*/
public function realMultiQuery($link, $query)
{
@@ -627,7 +752,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* returns result data from $result
*
- * @param object $result result MySQL result
+ * @param object $result MySQL result
*
* @return array
*/
@@ -732,7 +857,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* Check if there are any more query results from a multi query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return bool false
*/
@@ -744,7 +869,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* Prepare next result from multi_query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return boolean false
*/
@@ -756,7 +881,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* Store the result returned from multi query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return mixed false when empty results / result set when not empty
*/
@@ -768,7 +893,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* Returns a string representing the type of connection used
*
- * @param object $link mysql link
+ * @param resource $link mysql link
*
* @return string type of connection used
*/
@@ -780,7 +905,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* Returns the version of the MySQL protocol used
*
- * @param object $link mysql link
+ * @param resource $link mysql link
*
* @return integer version of the MySQL protocol used
*/
@@ -802,7 +927,7 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* returns last error message or false if no errors occurred
*
- * @param object $link connection link
+ * @param resource $link connection link
*
* @return string|bool $error or false
*/
@@ -830,8 +955,8 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
/**
* returns the number of rows affected by last query
*
- * @param object $link the mysql object
- * @param bool $get_from_cache whether to retrieve from cache
+ * @param resource $link the mysql object
+ * @param bool $get_from_cache whether to retrieve from cache
*
* @return string|int
*/
@@ -907,4 +1032,3 @@ class PMA_DBI_Dummy implements PMA_DBI_Extension
return '';
}
}
-?>
diff --git a/libraries/dbi/DBIExtension.int.php b/libraries/dbi/DBIExtension.int.php
index 81d94f4a5b..311528d95d 100644
--- a/libraries/dbi/DBIExtension.int.php
+++ b/libraries/dbi/DBIExtension.int.php
@@ -35,8 +35,8 @@ interface PMA_DBI_Extension
/**
* selects given database
*
- * @param string $dbname database name to select
- * @param object $link connection object
+ * @param string $dbname database name to select
+ * @param resource $link connection object
*
* @return boolean
*/
@@ -45,21 +45,21 @@ interface PMA_DBI_Extension
/**
* runs a query and returns the result
*
- * @param string $query query to execute
- * @param object $link connection object
- * @param int $options query options
+ * @param string $query query to execute
+ * @param resource $link connection object
+ * @param int $options query options
*
- * @return object|bool result
+ * @return mixed result
*/
public function realQuery($query, $link, $options);
/**
* Run the multi query and output the results
*
- * @param object $link connection object
- * @param string $query multi query statement to execute
+ * @param resource $link connection object
+ * @param string $query multi query statement to execute
*
- * @return result collection | boolean(false)
+ * @return array|bool
*/
public function realMultiQuery($link, $query);
@@ -112,7 +112,7 @@ interface PMA_DBI_Extension
/**
* Check if there are any more query results from a multi query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return bool true or false
*/
@@ -121,7 +121,7 @@ interface PMA_DBI_Extension
/**
* Prepare next result from multi_query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return bool true or false
*/
@@ -130,7 +130,7 @@ interface PMA_DBI_Extension
/**
* Store the result returned from multi query
*
- * @param object $link mysql link
+ * @param resource $link mysql link
*
* @return mixed false when empty results / result set when not empty
*/
@@ -139,7 +139,7 @@ interface PMA_DBI_Extension
/**
* Returns a string representing the type of connection used
*
- * @param object $link mysql link
+ * @param resource $link mysql link
*
* @return string type of connection used
*/
@@ -148,7 +148,7 @@ interface PMA_DBI_Extension
/**
* Returns the version of the MySQL protocol used
*
- * @param object $link mysql link
+ * @param resource $link mysql link
*
* @return integer version of the MySQL protocol used
*/
@@ -164,7 +164,7 @@ interface PMA_DBI_Extension
/**
* returns last error message or false if no errors occurred
*
- * @param object $link connection link
+ * @param resource $link connection link
*
* @return string|bool $error or false
*/
@@ -182,7 +182,7 @@ interface PMA_DBI_Extension
/**
* returns the number of rows affected by last query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return int
*/
@@ -259,4 +259,3 @@ function PMA_defineClientAPI($version)
);
}
}
-?>
diff --git a/libraries/dbi/DBIMysql.class.php b/libraries/dbi/DBIMysql.class.php
index 43973b28af..cb0b6599c6 100644
--- a/libraries/dbi/DBIMysql.class.php
+++ b/libraries/dbi/DBIMysql.class.php
@@ -260,7 +260,7 @@ class PMA_DBI_Mysql implements PMA_DBI_Extension
/**
* Check if there are any more query results from a multi query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return bool false
*/
@@ -276,7 +276,7 @@ class PMA_DBI_Mysql implements PMA_DBI_Extension
/**
* Prepare next result from multi_query
*
- * @param object $link the connection object
+ * @param resource $link the connection object
*
* @return boolean false
*/
@@ -466,4 +466,3 @@ class PMA_DBI_Mysql implements PMA_DBI_Extension
return false;
}
}
-?>
diff --git a/libraries/dbi/DBIMysqli.class.php b/libraries/dbi/DBIMysqli.class.php
index e1adb4a8e0..43db94c043 100644
--- a/libraries/dbi/DBIMysqli.class.php
+++ b/libraries/dbi/DBIMysqli.class.php
@@ -142,6 +142,9 @@ class PMA_DBI_Mysqli implements PMA_DBI_Extension
global $cfg;
$server_port = $GLOBALS['dbi']->getServerPort($server);
+ if ($server_port === null) {
+ $server_port = 0;
+ }
$server_socket = $GLOBALS['dbi']->getServerSocket($server);
if ($server) {
@@ -617,4 +620,3 @@ class PMA_DBI_Mysqli implements PMA_DBI_Extension
return implode(' ', $flags);
}
}
-?>
diff --git a/libraries/dbi/drizzle-wrappers.lib.php b/libraries/dbi/drizzle-wrappers.lib.php
index 444698cef5..b388bf05f6 100644
--- a/libraries/dbi/drizzle-wrappers.lib.php
+++ b/libraries/dbi/drizzle-wrappers.lib.php
@@ -106,6 +106,11 @@ class PMA_Drizzle extends Drizzle
*
* @package PhpMyAdmin-DBI
* @subpackage Drizzle
+ *
+ * @method string host() Get host
+ * @method int port() Get port
+ * @method int protocolVersion() Get protocol version
+ * @method resource selectDb(string $dbname) Select a DB
*/
class PMA_DrizzleCon
{
diff --git a/libraries/di/AliasItem.class.php b/libraries/di/AliasItem.class.php
new file mode 100644
index 0000000000..77c7c6c908
--- /dev/null
+++ b/libraries/di/AliasItem.class.php
@@ -0,0 +1,49 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\AliasItem class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+require_once 'libraries/di/Item.int.php';
+
+/**
+ * Class AliasItem
+ *
+ * @package PMA\DI
+ */
+class AliasItem implements Item
+{
+
+ /** @var Container */
+ protected $container;
+
+ /** @var string */
+ protected $target;
+
+ /**
+ * Constructor
+ *
+ * @param Container $container Container
+ * @param string $target Target
+ */
+ public function __construct(Container $container, $target)
+ {
+ $this->container = $container;
+ $this->target = $target;
+ }
+
+ /**
+ * Get the target item
+ *
+ * @param array $params Parameters
+ * @return mixed
+ */
+ public function get($params = array())
+ {
+ return $this->container->get($this->target, $params);
+ }
+}
diff --git a/libraries/di/Container.class.php b/libraries/di/Container.class.php
new file mode 100644
index 0000000000..80353bf014
--- /dev/null
+++ b/libraries/di/Container.class.php
@@ -0,0 +1,174 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\Container class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+require_once 'libraries/di/Item.int.php';
+require_once 'libraries/di/AliasItem.class.php';
+require_once 'libraries/di/ValueItem.class.php';
+require_once 'libraries/di/ServiceItem.class.php';
+require_once 'libraries/di/FactoryItem.class.php';
+
+/**
+ * Class Container
+ *
+ * @package PMA\DI
+ */
+class Container
+{
+
+ /**
+ * @var Item[] $content
+ */
+ protected $content = array();
+
+ /**
+ * @var Container
+ */
+ protected static $defaultContainer;
+
+ /**
+ * Create a dependency injection container
+ *
+ * @param Container $base Container
+ */
+ public function __construct(Container $base = null)
+ {
+ if (isset($base)) {
+ $this->content = $base->content;
+ } else {
+ $this->alias('container', 'Container');
+ }
+ $this->set('Container', $this);
+ }
+
+ /**
+ * Get an object with given name and parameters
+ *
+ * @param string $name Name
+ * @param array $params Paramters
+ *
+ * @return mixed
+ */
+ public function get($name, $params = array())
+ {
+ if (isset($this->content[$name])) {
+ return $this->content[$name]->get($params);
+ }
+
+ if (isset($GLOBALS[$name])) {
+ return $GLOBALS[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Remove an object from container
+ *
+ * @param string $name Name
+ *
+ * @return void
+ */
+ public function remove($name)
+ {
+ unset($this->content[$name]);
+ }
+
+ /**
+ * Rename an object in container
+ *
+ * @param string $name Name
+ * @param string $newName New name
+ *
+ * @return void
+ */
+ public function rename($name, $newName)
+ {
+ $this->content[$newName] = $this->content[$name];
+ $this->remove($name);
+ }
+
+ /**
+ * Set values in the container
+ *
+ * @param string|array $name Name
+ * @param mixed $value Value
+ *
+ * @return void
+ */
+ public function set($name, $value = null)
+ {
+ if (is_array($name)) {
+ foreach ($name as $key => $val) {
+ $this->set($key, $val);
+ }
+ return;
+ }
+ $this->content[$name] = new ValueItem($value);
+ }
+
+ /**
+ * Register a service in the container
+ *
+ * @param string $name Name
+ * @param mixed $service Service
+ *
+ * @return void
+ */
+ public function service($name, $service = null)
+ {
+ if (!isset($service)) {
+ $service = $name;
+ }
+ $this->content[$name] = new ServiceItem($this, $service);
+ }
+
+ /**
+ * Register a factory in the container
+ *
+ * @param string $name Name
+ * @param mixed $factory Factory
+ *
+ * @return void
+ */
+ public function factory($name, $factory = null)
+ {
+ if (!isset($factory)) {
+ $factory = $name;
+ }
+ $this->content[$name] = new FactoryItem($this, $factory);
+ }
+
+ /**
+ * Register an alias in the container
+ *
+ * @param string $name Name
+ * @param string $target Target
+ *
+ * @return void
+ */
+ public function alias($name, $target)
+ {
+ // The target may be not defined yet
+ $this->content[$name] = new AliasItem($this, $target);
+ }
+
+ /**
+ * Get the global default container
+ *
+ * @return Container
+ */
+ public static function getDefaultContainer()
+ {
+ if (!isset(static::$defaultContainer)) {
+ static::$defaultContainer = new Container();
+ }
+ return static::$defaultContainer;
+ }
+}
diff --git a/libraries/di/FactoryItem.class.php b/libraries/di/FactoryItem.class.php
new file mode 100644
index 0000000000..aaa275047f
--- /dev/null
+++ b/libraries/di/FactoryItem.class.php
@@ -0,0 +1,43 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\FactoryItem class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+require_once 'libraries/di/ReflectorItem.class.php';
+
+/**
+ * Factory manager
+ *
+ * @package PMA\DI
+ */
+class FactoryItem extends ReflectorItem
+{
+
+ /**
+ * Constructor
+ *
+ * @param Container $container Container
+ * @param mixed $definition Definition
+ */
+ public function __construct(Container $container, $definition)
+ {
+ parent::__construct($container, $definition);
+ }
+
+ /**
+ * Construct an instance
+ *
+ * @param array $params Parameters
+ *
+ * @return mixed
+ */
+ public function get($params = array())
+ {
+ return $this->invoke($params);
+ }
+}
diff --git a/libraries/di/Item.int.php b/libraries/di/Item.int.php
new file mode 100644
index 0000000000..19bd6fea4d
--- /dev/null
+++ b/libraries/di/Item.int.php
@@ -0,0 +1,26 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\Item class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+/**
+ * Interface Item
+ *
+ * @package PMA\DI
+ */
+interface Item
+{
+
+ /**
+ * Get a value from the item
+ *
+ * @param array $params Parameters
+ * @return mixed
+ */
+ public function get($params = array());
+}
diff --git a/libraries/di/ReflectorItem.class.php b/libraries/di/ReflectorItem.class.php
new file mode 100644
index 0000000000..f9ab2b9180
--- /dev/null
+++ b/libraries/di/ReflectorItem.class.php
@@ -0,0 +1,127 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\ReflectorItem class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+require_once 'libraries/di/Item.int.php';
+
+/**
+ * Reflector manager
+ *
+ * @package PMA\DI
+ */
+abstract class ReflectorItem implements Item
+{
+
+ /** @var Container */
+ private $_container;
+
+ /** @var \Reflector */
+ private $_reflector;
+
+ /**
+ * Constructor
+ *
+ * @param Container $container Container
+ * @param mixed $definition Definition
+ */
+ public function __construct(Container $container, $definition)
+ {
+ $this->_container = $container;
+ $this->_reflector = self::_resolveReflector($definition);
+ }
+
+ /**
+ * Invoke the reflector with given parameters
+ *
+ * @param array $params Parameters
+ * @return mixed
+ */
+ protected function invoke($params = array())
+ {
+ $args = array();
+ $reflector = $this->_reflector;
+ if ($reflector instanceof \ReflectionClass) {
+ $constructor = $reflector->getConstructor();
+ if (isset($constructor)) {
+ $args = $this->_resolveArgs(
+ $constructor->getParameters(),
+ $params
+ );
+ }
+ return $reflector->newInstanceArgs($args);
+ }
+ /** @var \ReflectionFunctionAbstract $reflector */
+ $args = $this->_resolveArgs(
+ $reflector->getParameters(),
+ $params
+ );
+ if ($reflector instanceof \ReflectionMethod) {
+ /** @var \ReflectionMethod $reflector */
+ return $reflector->invokeArgs(null, $args);
+ }
+ /** @var \ReflectionFunction $reflector */
+ return $reflector->invokeArgs($args);
+ }
+
+ /**
+ * Getting required arguments with given parameters
+ *
+ * @param \ReflectionParameter[] $required Arguments
+ * @param array $params Parameters
+ *
+*@return array
+ */
+ private function _resolveArgs($required, $params = array())
+ {
+ $args = array();
+ foreach ($required as $param) {
+ $name = $param->getName();
+ $type = $param->getClass();
+ if (isset($type)) {
+ $type = $type->getName();
+ }
+ if (isset($params[$name])) {
+ $args[] = $params[$name];
+ } elseif (is_string($type) && isset($params[$type])) {
+ $args[] = $params[$type];
+ } else {
+ $content = $this->_container->get($name);
+ if (isset($content)) {
+ $args[] = $content;
+ } elseif (is_string($type)) {
+ $args[] = $this->_container->get($type);
+ } else {
+ $args[] = null;
+ }
+ }
+ }
+ return $args;
+ }
+
+ /**
+ * Resolve the reflection
+ *
+ * @param mixed $definition Definition
+ *
+ * @return \Reflector
+ */
+ private static function _resolveReflector($definition)
+ {
+ if (function_exists($definition)) {
+ return new \ReflectionFunction($definition);
+ }
+ if (is_string($definition)) {
+ $definition = explode('::', $definition);
+ }
+ if (!isset($definition[1])) {
+ return new \ReflectionClass($definition[0]);
+ }
+ return new \ReflectionMethod($definition[0], $definition[1]);
+ }
+}
diff --git a/libraries/di/ServiceItem.class.php b/libraries/di/ServiceItem.class.php
new file mode 100644
index 0000000000..7016df4116
--- /dev/null
+++ b/libraries/di/ServiceItem.class.php
@@ -0,0 +1,48 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\ServiceItem class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+require_once 'libraries/di/ReflectorItem.class.php';
+
+/**
+ * Service manager
+ *
+ * @package PMA\DI
+ */
+class ServiceItem extends ReflectorItem
+{
+
+ /** @var mixed */
+ protected $instance;
+
+ /**
+ * Constructor
+ *
+ * @param Container $container Container
+ * @param mixed $definition Definition
+ */
+ public function __construct(Container $container, $definition)
+ {
+ parent::__construct($container, $definition);
+ }
+
+ /**
+ * Get the instance of the service
+ *
+ * @param array $params Parameters
+ * @return mixed
+ */
+ public function get($params = array())
+ {
+ if (!isset($this->instance)) {
+ $this->instance = $this->invoke();
+ }
+ return $this->instance;
+ }
+}
diff --git a/libraries/di/ValueItem.class.php b/libraries/di/ValueItem.class.php
new file mode 100644
index 0000000000..d7c91d1ce9
--- /dev/null
+++ b/libraries/di/ValueItem.class.php
@@ -0,0 +1,44 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PMA\DI\ValueItem class
+ *
+ * @package PMA
+ */
+
+namespace PMA\DI;
+
+require_once 'libraries/di/Item.int.php';
+
+/**
+ * Value manager
+ *
+ * @package PMA\DI
+ */
+class ValueItem implements Item
+{
+
+ /** @var mixed */
+ protected $value;
+
+ /**
+ * Constructor
+ *
+ * @param mixed $value Value
+ */
+ public function __construct($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * Get the value
+ *
+ * @param array $params Parameters
+ * @return mixed
+ */
+ public function get($params = array())
+ {
+ return $this->value;
+ }
+}
diff --git a/libraries/display_change_password.lib.php b/libraries/display_change_password.lib.php
index 54d86c1fef..0b65e3d6b8 100644
--- a/libraries/display_change_password.lib.php
+++ b/libraries/display_change_password.lib.php
@@ -64,7 +64,7 @@ function PMA_getHtmlForChangePassword($username, $hostname)
. '<td>'
. '<input type="radio" name="nopass" value="0" id="nopass_0" '
. 'onclick="document.getElementById(\'text_pma_pw\').focus();" '
- . 'checked="checked " />'
+ . 'checked="checked" />'
. '<label for="nopass_0">' . __('Password:') . '&nbsp;</label>'
. '</td>'
. '<td>'
@@ -77,18 +77,63 @@ function PMA_getHtmlForChangePassword($username, $hostname)
. $chg_evt_handler . '="nopass[1].checked = true" />'
. '</td>'
. '</tr>';
+ $default_auth_plugin = PMA_getCurrentAuthenticationPlugin(
+ 'change', $username, $hostname
+ );
- if (PMA_MYSQL_INT_VERSION < 50705) {
+ // See http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-5.html
+ if (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50705
+ ) {
$html .= '<tr class="vmiddle">'
- . '<td>' . __('Password Hashing:')
+ . '<td>' . __('Password Hashing:') . '</td>'
+ . '<td>'
+ . '<input type="radio" name="pw_hash" id="radio_pw_hash_mysql_native" '
+ . 'value="mysql_native_password"';
+ if ($default_auth_plugin == 'mysql_native_password') {
+ $html .= '" checked="checked"';
+ }
+ $html .= ' />'
+ . '<label for="radio_pw_hash_mysql_native">'
+ . __('MySQL native password')
+ . '</label>'
. '</td>'
+ . '</tr>'
+ . '<tr id="tr_element_before_generate_password">'
+ . '<td>&nbsp;</td>'
+ . '<td>'
+ . '<input type="radio" name="pw_hash" id="radio_pw_hash_sha256" '
+ . 'value="sha256_password"';
+ if ($default_auth_plugin == 'sha256_password') {
+ $html .= '" checked="checked"';
+ }
+ $html .= ' />'
+ . '<label for="radio_pw_hash_sha256">'
+ . __('SHA256 password')
+ . '</label>'
+ . '</td>'
+ . '</tr>';
+ } elseif (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50606
+ ) {
+ $html .= '<tr class="vmiddle" id="tr_element_before_generate_password">'
+ . '<td>' . __('Password Hashing:') . '</td>'
. '<td>'
. '<input type="radio" name="pw_hash" id="radio_pw_hash_new" '
- . 'value="new" checked="checked" />'
- . '<label for="radio_pw_hash_new">MySQL&nbsp;4.1+</label>'
+ . 'value="' . $default_auth_plugin . '" checked="checked" />'
+ . '<label for="radio_pw_hash_new">' . $default_auth_plugin . '</label>'
+ . '</td>'
+ . '</tr>';
+ } else {
+ $html .= '<tr class="vmiddle">'
+ . '<td>' . __('Password Hashing:') . '</td>'
+ . '<td>'
+ . '<input type="radio" name="pw_hash" id="radio_pw_hash_new" '
+ . 'value="mysql_native_password" checked="checked" />'
+ . '<label for="radio_pw_hash_new">mysql_native_password</label>'
. '</td>'
. '</tr>'
- . '<tr id="tr_element_before_generate_password">'
+ . '<tr id="tr_element_before_generate_password" >'
. '<td>&nbsp;</td>'
. '<td>'
. '<input type="radio" name="pw_hash" id="radio_pw_hash_old" '
@@ -97,13 +142,25 @@ function PMA_getHtmlForChangePassword($username, $hostname)
. '</label>'
. '</td>'
. '</tr>';
- } else {
- // See http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-5.html
- $html .= '<input type="hidden" name="pw_hash" value="new" />';
}
- $html .= '</table>'
- . '</fieldset>'
+ $html .= '</table>';
+
+ $html .= '<div '
+ . ($default_auth_plugin != 'sha256_password' ? 'style="display:none"' : '')
+ . ' id="ssl_reqd_warning_cp">'
+ . PMA_Message::notice(
+ __(
+ 'This method requires using an \'<i>SSL connection</i>\' '
+ . 'or an \'<i>unencrypted connection that encrypts the password '
+ . 'using RSA</i>\'; while connecting to the server.'
+ )
+ . PMA_Util::showMySQLDocu('sha256-authentication-plugin')
+ )
+ ->getDisplay()
+ . '</div>';
+
+ $html .= '</fieldset>'
. '<fieldset id="fieldset_change_password_footer" class="tblFooters">'
. '<input type="hidden" name="change_pw" value="1" />'
. '<input type="submit" value="' . __('Go') . '" />'
diff --git a/libraries/display_create_database.lib.php b/libraries/display_create_database.lib.php
index 0f9ac15f40..ce240a01cc 100644
--- a/libraries/display_create_database.lib.php
+++ b/libraries/display_create_database.lib.php
@@ -59,4 +59,3 @@ if ($is_create_db_priv) {
)
. '' . __('No Privileges') . '</span>';
} // end create db form or message
-?>
diff --git a/libraries/display_create_table.lib.php b/libraries/display_create_table.lib.php
index ad5e3c69a4..7087794d42 100644
--- a/libraries/display_create_table.lib.php
+++ b/libraries/display_create_table.lib.php
@@ -32,8 +32,7 @@ if (! defined('PHPMYADMIN')) {
*
*/
require_once './libraries/check_user_privileges.lib.php';
-
-$is_create_table_priv = true;
+require_once 'libraries/Template.class.php';
/**
* Returns the html for create table.
@@ -44,39 +43,7 @@ $is_create_table_priv = true;
*/
function PMA_getHtmlForCreateTable($db)
{
- $html = '<form id="create_table_form_minimal" method="post" '
- . 'action="tbl_create.php">';
- $html .= '<fieldset>';
- $html .= '<legend>';
-
- if (PMA_Util::showIcons('ActionLinksMode')) {
- $html .= PMA_Util::getImage('b_newtbl.png');
- }
- $html .= __('Create table');
-
- $html .= ' </legend>';
- $html .= PMA_URL_getHiddenInputs($db);
- $html .= '<div class="formelement">';
- $html .= __('Name') . ":";
- $html .= ' <input type="text" name="table" maxlength="64" '
- . 'size="30" required="required" />';
- $html .= ' </div>';
- $html .= ' <div class="formelement">';
- $html .= __('Number of columns') . ":";
- $html .= ' <input type="number" min="1" name="num_fields" '
- . 'value="4" required="required" />';
- $html .= ' </div>';
- $html .= ' <div class="clearfloat"></div>';
- $html .= '</fieldset>';
- $html .= '<fieldset class="tblFooters">';
- $html .= ' <input type="submit" value="' . __('Go') . '" />';
- $html .= '</fieldset>';
- $html .= '</form>';
-
- return $html;
-}
-
-if (!defined('TESTSUITE')) {
- echo PMA_getHtmlForCreateTable($db);
+ return PMA\Template::get('database/create_table')->render(
+ array('db' => $db)
+ );
}
-?>
diff --git a/libraries/display_export.inc.php b/libraries/display_export.inc.php
index 39b07d38d2..9d251a3272 100644
--- a/libraries/display_export.inc.php
+++ b/libraries/display_export.inc.php
@@ -21,6 +21,7 @@ require_once './libraries/plugin_interface.lib.php';
require_once './libraries/display_export.lib.php';
/* Scan for plugins */
+/* @var $export_list ExportPlugin[] */
$export_list = PMA_getPlugins(
"export",
'libraries/plugins/export/',
@@ -38,7 +39,14 @@ if (empty($export_list)) {
exit;
}
-$html = '<form method="post" action="export.php" '
+$html = PMA_getHtmlForExportOptionHeader($export_type, $db, $table);
+
+$cfgRelation = PMA_getRelationsParam();
+if ($cfgRelation['exporttemplateswork']) {
+ $html .= PMA_getHtmlForExportTemplateLoading($export_type);
+}
+
+$html .= '<form method="post" action="export.php" '
. ' name="dump" class="disableAjax">';
//output Hidden Inputs
diff --git a/libraries/display_export.lib.php b/libraries/display_export.lib.php
index d7f5ed828b..2613cd9d13 100644
--- a/libraries/display_export.lib.php
+++ b/libraries/display_export.lib.php
@@ -37,17 +37,17 @@ function PMA_exportCheckboxCheck($str)
*/
function PMA_getHtmlForExportSelectOptions($tmp_select = '')
{
- $multi_values = '<div style="text-align: left">';
+ $multi_values = '<div>';
$multi_values .= '<a href="#"';
$multi_values .= ' onclick="setSelectOptions'
. '(\'dump\', \'db_select[]\', true); return false;">';
- $multi_values .= __('Select All');
+ $multi_values .= __('Select all');
$multi_values .= '</a>';
$multi_values .= ' / ';
$multi_values .= '<a href="#"';
$multi_values .= ' onclick="setSelectOptions'
. '(\'dump\', \'db_select[]\', false); return false;">';
- $multi_values .= __('Unselect All') . '</a><br />';
+ $multi_values .= __('Unselect all') . '</a><br />';
$multi_values .= '<select name="db_select[]" '
. 'id="db_select" size="10" multiple="multiple">';
@@ -61,10 +61,7 @@ function PMA_getHtmlForExportSelectOptions($tmp_select = '')
}
foreach ($GLOBALS['pma']->databases as $current_db) {
- if ($current_db == 'information_schema'
- || $current_db == 'performance_schema'
- || $current_db == 'mysql'
- ) {
+ if ($GLOBALS['dbi']->isSystemSchema($current_db, true)) {
continue;
}
if (isset($_GET['db_select'])) {
@@ -148,6 +145,12 @@ function PMA_getHtmlForHiddenInput(
. htmlspecialchars($_GET['sql_query']) . '" />' . "\n";
}
+ $html .= '<input type="hidden" name="template_id"' . ' value="'
+ . (isset($_GET['template_id'])
+ ? htmlspecialchars($_GET['template_id'])
+ : '')
+ . '" />';
+
return $html;
}
@@ -185,6 +188,88 @@ function PMA_getHtmlForExportOptionHeader($export_type, $db, $table)
}
/**
+ * Returns HTML for export template operations
+ *
+ * @param string $export_type export type - server, database, or table
+ *
+ * @return string HTML for export template operations
+ */
+function PMA_getHtmlForExportTemplateLoading($export_type)
+{
+ $html = '<div class="exportoptions" id="export_templates">';
+ $html .= '<h3>' . __('Export templates:') . '</h3>';
+
+ $html .= '<div class="floatleft">';
+ $html .= '<form method="post" action="tbl_export.php" id="newTemplateForm"'
+ . ' class="ajax">';
+ $html .= '<h4>' . __('New template:') . '</h4>';
+ $html .= '<input type="text" name="templateName" id="templateName" '
+ . 'maxlength="64"' . 'required="required" '
+ . 'placeholder="' . __('Template name') . '" />';
+ $html .= '<input type="submit" name="createTemplate" id="createTemplate" '
+ . 'value="' . __('Create') . '" />';
+ $html .= '</form>';
+ $html .= '</div>';
+
+ $html .= '<div class="floatleft" style="margin-left: 50px;">';
+ $html .= '<form method="post" action="tbl_export.php"'
+ . ' id="existingTemplatesForm" class="ajax">';
+ $html .= '<h4>' . __('Existing templates:') . '</h4>';
+ $html .= '<label for="template">' . __('Template:') . '</label>';
+ $html .= '<select required="required" name="template" id="template">';
+ $html .= PMA_getOptionsForExportTemplates($export_type);
+ $html .= '</select>';
+ $html .= '<input type="submit" name="updateTemplate" '
+ . 'id="updateTemplate" value="' . __('Update') . '" />';
+ $html .= '<input type="submit" name="deleteTemplate" '
+ . 'id="deleteTemplate" value="' . __('Delete') . '" />';
+ $html .= '</form>';
+ $html .= '</div>';
+
+ $html .= '<div class="clearfloat"></div>';
+
+ $html .= '</div>';
+
+ return $html;
+}
+
+/**
+ * Returns HTML for the options in teplate dropdown
+ *
+ * @param string $export_type export type - server, database, or table
+ *
+ * @return string HTML for the options in teplate dropdown
+ */
+function PMA_getOptionsForExportTemplates($export_type)
+{
+ $ret = '<option value="">-- ' . __('Select a template') . ' --</option>';
+
+ // Get the relation settings
+ $cfgRelation = PMA_getRelationsParam();
+
+ $query = "SELECT `id`, `template_name` FROM "
+ . PMA_Util::backquote($cfgRelation['db']) . '.'
+ . PMA_Util::backquote($cfgRelation['export_templates'])
+ . " WHERE `username` = "
+ . "'" . PMA_Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']) . "'"
+ . " AND `export_type` = '" . $export_type . "'"
+ . " ORDER BY `template_name`;";
+
+ $result = PMA_queryAsControlUser($query);
+ if ($result) {
+ while ($row = $GLOBALS['dbi']->fetchAssoc($result, $GLOBALS['controllink'])) {
+ $ret .= '<option value="' . htmlspecialchars($row['id']) . '"';
+ if (!empty($_GET['template_id']) && $_GET['template_id'] == $row['id']) {
+ $ret .= ' selected="selected"';
+ }
+ $ret .= '>';
+ $ret .= htmlspecialchars($row['template_name']) . '</option>';
+ }
+ }
+ return $ret;
+}
+
+/**
* Prints Html For Export Options Method
*
* @return string
@@ -203,7 +288,7 @@ function PMA_getHtmlForExportOptionsMethod()
}
$html = '<div class="exportoptions" id="quick_or_custom">';
- $html .= '<h3>' . __('Export Method:') . '</h3>';
+ $html .= '<h3>' . __('Export method:') . '</h3>';
$html .= '<ul>';
$html .= '<li>';
$html .= '<input type="radio" name="quick_or_custom" value="quick" '
@@ -247,9 +332,9 @@ function PMA_getHtmlForExportOptionsSelection($export_type, $multi_values)
{
$html = '<div class="exportoptions" id="databases_and_tables">';
if ($export_type == 'server') {
- $html .= '<h3>' . __('Database(s):') . '</h3>';
+ $html .= '<h3>' . __('Databases:') . '</h3>';
} else if ($export_type == 'database') {
- $html .= '<h3>' . __('Table(s):') . '</h3>';
+ $html .= '<h3>' . __('Tables:') . '</h3>';
}
if (! empty($multi_values)) {
$html .= $multi_values;
@@ -260,20 +345,31 @@ function PMA_getHtmlForExportOptionsSelection($export_type, $multi_values)
}
/**
- * Prints Html For Export Options Format
+ * Prints Html For Export Options Format dropdown
*
- * @param array $export_list Export List
+ * @param ExportPlugin[] $export_list Export List
*
* @return string
*/
-function PMA_getHtmlForExportOptionsFormat($export_list)
+function PMA_getHtmlForExportOptionsFormatDropdown($export_list)
{
$html = '<div class="exportoptions" id="format">';
$html .= '<h3>' . __('Format:') . '</h3>';
$html .= PMA_pluginGetChoice('Export', 'what', $export_list, 'format');
$html .= '</div>';
+ return $html;
+}
- $html .= '<div class="exportoptions" id="format_specific_opts">';
+/**
+ * Prints Html For Export Options Format-specific options
+ *
+ * @param ExportPlugin[] $export_list Export List
+ *
+ * @return string
+ */
+function PMA_getHtmlForExportOptionsFormat($export_list)
+{
+ $html = '<div class="exportoptions" id="format_specific_opts">';
$html .= '<h3>' . __('Format-specific options:') . '</h3>';
$html .= '<p class="no_js_msg" id="scroll_to_options_msg">';
$html .= __(
@@ -342,7 +438,8 @@ function PMA_getHtmlForExportOptionsRows($db, $table, $unlim_num_rows)
} elseif (!empty($unlim_num_rows)) {
$html .= $unlim_num_rows;
} else {
- $html .= PMA_Table::countRecords($db, $table);
+ $_table = new PMA_Table($table, $db);
+ $html .= $_table->countRecords();
}
$html .= '" onfocus="this.select()" />';
$html .= '</li>';
@@ -395,11 +492,11 @@ function PMA_getHtmlForExportOptionsQuickExport()
$html .= '</label>';
$html .= '</li>';
$html .= '<li>';
- $html .= '<input type="checkbox" name="quick_export_onserverover" ';
- $html .= 'value="saveitover" id="checkbox_quick_dump_onserverover" ';
+ $html .= '<input type="checkbox" name="quick_export_onserver_overwrite" ';
+ $html .= 'value="saveitover" id="checkbox_quick_dump_onserver_overwrite" ';
$html .= PMA_exportCheckboxCheck('quick_export_onserver_overwrite');
$html .= '/>';
- $html .= '<label for="checkbox_quick_dump_onserverover">';
+ $html .= '<label for="checkbox_quick_dump_onserver_overwrite">';
$html .= __('Overwrite existing file(s)');
$html .= '</label>';
$html .= '</li>';
@@ -430,11 +527,11 @@ function PMA_getHtmlForExportOptionsOutputSaveDir()
$html .= '</label>';
$html .= '</li>';
$html .= '<li>';
- $html .= '<input type="checkbox" name="onserverover" value="saveitover"';
- $html .= ' id="checkbox_dump_onserverover" ';
+ $html .= '<input type="checkbox" name="onserver_overwrite" value="saveitover"';
+ $html .= ' id="checkbox_dump_onserver_overwrite" ';
$html .= PMA_exportCheckboxCheck('onserver_overwrite');
$html .= '/>';
- $html .= '<label for="checkbox_dump_onserverover">';
+ $html .= '<label for="checkbox_dump_onserver_overwrite">';
$html .= __('Overwrite existing file(s)');
$html .= '</label>';
$html .= '</li>';
@@ -537,14 +634,14 @@ function PMA_getHtmlForExportOptionsOutputFormat($export_type)
function PMA_getHtmlForExportOptionsOutputCharset()
{
global $cfg;
- $html = ' <li><label for="select_charset_of_file" class="desc">'
+ $html = ' <li><label for="select_charset" class="desc">'
. __('Character set of the file:') . '</label>' . "\n";
reset($cfg['AvailableCharsets']);
- $html .= '<select id="select_charset_of_file" name="charset_of_file" size="1">';
+ $html .= '<select id="select_charset" name="charset" size="1">';
foreach ($cfg['AvailableCharsets'] as $temp_charset) {
$html .= '<option value="' . $temp_charset . '"';
- if (isset($_GET['charset_of_file'])
- && ($_GET['charset_of_file'] != $temp_charset)
+ if (isset($_GET['charset'])
+ && ($_GET['charset'] != $temp_charset)
) {
$html .= '';
} elseif ((empty($cfg['Export']['charset']) && $temp_charset == 'utf-8')
@@ -575,6 +672,13 @@ function PMA_getHtmlForExportOptionsOutputCompression()
$selected_compression = "none";
}
+ // Since separate files export works with ZIP only
+ if (isset($cfg['Export']['as_separate_files'])
+ && $cfg['Export']['as_separate_files']
+ ) {
+ $selected_compression = "zip";
+ }
+
$html = "";
// zip and gzip encode features
$is_zip = ($cfg['ZipDump'] && @function_exists('gzcompress'));
@@ -629,6 +733,32 @@ function PMA_getHtmlForExportOptionsOutputRadio()
}
/**
+ * Prints Html For Export Options Checkbox - Separate files
+ *
+ * @param String $export_type Selected Export Type
+ *
+ * @return string
+ */
+function PMA_getHtmlForExportOptionsOutputSeparateFiles($export_type)
+{
+ $html = '<li>';
+ $html .= '<input type="checkbox" id="checkbox_as_separate_files" '
+ . PMA_exportCheckboxCheck('as_separate_files')
+ . ' name="as_separate_files" value="' . $export_type . '" />';
+ $html .= '<label for="checkbox_as_separate_files">';
+
+ if ($export_type == 'server') {
+ $html .= __('Export databases as separate files');
+ } elseif ($export_type == 'database') {
+ $html .= __('Export tables as separate files');
+ }
+
+ $html .= '</label></li>';
+
+ return $html;
+}
+
+/**
* Prints Html For Export Options
*
* @param String $export_type Selected Export Type
@@ -652,6 +782,21 @@ function PMA_getHtmlForExportOptionsOutput($export_type)
$html .= '<label for="btn_alias_config">';
$html .= __('Rename exported databases/tables/columns');
$html .= '</label></li>';
+
+ if ($export_type != 'server') {
+ $html .= '<li>';
+ $html .= '<input type="checkbox" name="lock_tables"';
+ $html .= ' value="something" id="checkbox_lock_tables"';
+ if (! isset($_GET['repopulate'])) {
+ $html .= PMA_exportCheckboxCheck('lock_tables') . '/>';
+ } elseif (isset($_GET['lock_tables'])) {
+ $html .= ' checked="checked"';
+ }
+ $html .= '<label for="checkbox_lock_tables">';
+ $html .= sprintf(__('Use %s statement'), '<code>LOCK TABLES</code>');
+ $html .= '</label></li>';
+ }
+
$html .= '<li>';
$html .= '<input type="radio" name="output_format" value="sendit" ';
$html .= 'id="radio_dump_asfile" ';
@@ -675,6 +820,12 @@ function PMA_getHtmlForExportOptionsOutput($export_type)
$html .= PMA_getHtmlForExportOptionsOutputCompression();
+ if ($export_type == 'server'
+ || $export_type == 'database'
+ ) {
+ $html .= PMA_getHtmlForExportOptionsOutputSeparateFiles($export_type);
+ }
+
$html .= '</ul>';
$html .= '</li>';
@@ -698,13 +849,13 @@ function PMA_getHtmlForExportOptionsOutput($export_type)
/**
* Prints Html For Export Options
*
- * @param String $export_type Selected Export Type
- * @param String $db Selected DB
- * @param String $table Selected Table
- * @param String $multi_values Export selection
- * @param String $num_tables number of tables
- * @param array $export_list Export List
- * @param String $unlim_num_rows Number of Rows
+ * @param String $export_type Selected Export Type
+ * @param String $db Selected DB
+ * @param String $table Selected Table
+ * @param String $multi_values Export selection
+ * @param String $num_tables number of tables
+ * @param ExportPlugin[] $export_list Export List
+ * @param String $unlim_num_rows Number of Rows
*
* @return string
*/
@@ -713,12 +864,13 @@ function PMA_getHtmlForExportOptions(
$num_tables, $export_list, $unlim_num_rows
) {
global $cfg;
- $html = PMA_getHtmlForExportOptionHeader($export_type, $db, $table);
- $html .= PMA_getHtmlForExportOptionsMethod();
+ $html = PMA_getHtmlForExportOptionsMethod();
+ $html .= PMA_getHtmlForExportOptionsFormatDropdown($export_list);
$html .= PMA_getHtmlForExportOptionsSelection($export_type, $multi_values);
$tableLength = /*overload*/mb_strlen($table);
- if ($tableLength && empty($num_tables) && ! PMA_Table::isMerge($db, $table)) {
+ $_table = new PMA_Table($table, $db);
+ if ($tableLength && empty($num_tables) && ! $_table->isMerge()) {
$html .= PMA_getHtmlForExportOptionsRows($db, $table, $unlim_num_rows);
}
@@ -869,4 +1021,3 @@ function PMA_getHtmlForAliasModalDialog($db = '', $table = '')
$html .= '</div>';
return $html;
}
-?>
diff --git a/libraries/display_import.inc.php b/libraries/display_import.inc.php
deleted file mode 100644
index 359be83f8d..0000000000
--- a/libraries/display_import.inc.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-
-/**
- * include file for display import : server, database, table
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- *
- */
-require_once './libraries/file_listing.lib.php';
-require_once './libraries/plugin_interface.lib.php';
-require_once './libraries/display_import.lib.php';
-require_once './libraries/display_import_ajax.lib.php';
-
-/* Scan for plugins */
-$import_list = PMA_getPlugins(
- "import",
- 'libraries/plugins/import/',
- $import_type
-);
-
-/* Fail if we didn't find any plugin */
-if (empty($import_list)) {
- PMA_Message::error(
- __(
- 'Could not load import plugins, please check your installation!'
- )
- )->display();
- exit;
-}
-
-if (PMA_isValid($_REQUEST['offset'], 'numeric')) {
- $offset = $_REQUEST['offset'];
-}
-if (isset($_REQUEST['timeout_passed'])) {
- $timeout_passed = $_REQUEST['timeout_passed'];
-}
-if (isset($_REQUEST['local_import_file'])) {
- $local_import_file = $_REQUEST['local_import_file'];
-}
-
-$timeout_passed_str = isset($timeout_passed)? $timeout_passed : null;
-$offset_str = isset($offset)? $offset : null;
-$html = PMA_getHtmlForImport(
- $upload_id,
- $import_type,
- $db,
- $table,
- $max_upload_size,
- $import_list,
- $timeout_passed_str,
- $offset_str
-);
-
-$response = PMA_Response::getInstance();
-$response->addHTML($html);
-
-?>
diff --git a/libraries/display_import.lib.php b/libraries/display_import.lib.php
index 45b923eca8..4446341a20 100644
--- a/libraries/display_import.lib.php
+++ b/libraries/display_import.lib.php
@@ -210,16 +210,18 @@ function PMA_getHtmlForImportCharset()
/**
* Prints Html For Display Import options : file property
*
- * @param int $max_upload_size Max upload size
- * @param Array $import_list import list
+ * @param int $max_upload_size Max upload size
+ * @param ImportPlugin[] $import_list import list
+ * @param String $local_import_file from upload directory
*
* @return string
*/
-function PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list)
-{
+function PMA_getHtmlForImportOptionsFile(
+ $max_upload_size, $import_list, $local_import_file
+) {
global $cfg;
$html = ' <div class="importoptions">';
- $html .= ' <h3>' . __('File to Import:') . '</h3>';
+ $html .= ' <h3>' . __('File to import:') . '</h3>';
$html .= PMA_getHtmlForImportCompressions();
$html .= ' <div class="formelementrow" id="upload_form">';
@@ -235,7 +237,7 @@ function PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list)
$html .= ' <input type="radio" name="file_location" '
. 'id="radio_local_import_file"';
if (! empty($GLOBALS['timeout_passed'])
- && ! empty($GLOBALS['local_import_file'])
+ && ! empty($local_import_file)
) {
$html .= ' checked="checked"';
}
@@ -273,7 +275,7 @@ function PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list)
function PMA_getHtmlForImportOptionsPartialImport($timeout_passed, $offset)
{
$html = ' <div class="importoptions">';
- $html .= ' <h3>' . __('Partial Import:') . '</h3>';
+ $html .= ' <h3>' . __('Partial import:') . '</h3>';
if (isset($timeout_passed) && $timeout_passed) {
$html .= '<div class="formelementrow">' . "\n";
@@ -328,9 +330,26 @@ function PMA_getHtmlForImportOptionsPartialImport($timeout_passed, $offset)
}
/**
+ * Prints Html For Display Import options : Other
+ *
+ * @return string
+ */
+function PMA_getHtmlForImportOptionsOther()
+{
+ $html = ' <div class="importoptions">';
+ $html .= ' <h3>' . __('Other options:') . '</h3>';
+ $html .= ' <div class="formelementrow">';
+ $html .= PMA_Util::getFKCheckbox();
+ $html .= ' </div>';
+ $html .= ' </div>';
+
+ return $html;
+}
+
+/**
* Prints Html For Display Import options : Format
*
- * @param Array $import_list import list
+ * @param ImportPlugin[] $import_list import list
*
* @return string
*/
@@ -343,7 +362,7 @@ function PMA_getHtmlForImportOptionsFormat($import_list)
$html .= ' </div>';
$html .= ' <div class="importoptions" id="format_specific_opts">';
- $html .= ' <h3>' . __('Format-Specific Options:') . '</h3>';
+ $html .= ' <h3>' . __('Format-specific options:') . '</h3>';
$html .= ' <p class="no_js_msg" id="scroll_to_options_msg">'
. 'Scroll down to fill in the options for the selected format '
. 'and ignore the options for other formats.</p>';
@@ -381,20 +400,21 @@ function PMA_getHtmlForImportOptionsSubmit()
/**
* Prints Html For Display Import
*
- * @param int $upload_id The selected upload id
- * @param String $import_type Import type: server, database, table
- * @param String $db Selected DB
- * @param String $table Selected Table
- * @param int $max_upload_size Max upload size
- * @param Array $import_list Import list
- * @param String $timeout_passed Timeout passed
- * @param String $offset Timeout offset
+ * @param int $upload_id The selected upload id
+ * @param String $import_type Import type: server, database, table
+ * @param String $db Selected DB
+ * @param String $table Selected Table
+ * @param int $max_upload_size Max upload size
+ * @param ImportPlugin[] $import_list Import list
+ * @param String $timeout_passed Timeout passed
+ * @param String $offset Timeout offset
+ * @param String $local_import_file from upload directory
*
* @return string
*/
function PMA_getHtmlForImport(
$upload_id, $import_type, $db, $table,
- $max_upload_size, $import_list, $timeout_passed, $offset
+ $max_upload_size, $import_list, $timeout_passed, $offset, $local_import_file
) {
global $SESSION_KEY;
$html = '';
@@ -423,10 +443,14 @@ function PMA_getHtmlForImport(
$html .= PMA_getHtmlForImportOptions($import_type, $db, $table);
- $html .= PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list);
+ $html .= PMA_getHtmlForImportOptionsFile(
+ $max_upload_size, $import_list, $local_import_file
+ );
$html .= PMA_getHtmlForImportOptionsPartialImport($timeout_passed, $offset);
+ $html .= PMA_getHtmlForImportOptionsOther();
+
$html .= PMA_getHtmlForImportOptionsFormat($import_list);
$html .= PMA_getHtmlForImportOptionsSubmit();
@@ -599,4 +623,65 @@ function PMA_getHtmlForImportWithPlugin($upload_id)
return $html;
}
-?>
+/**
+ * Gets HTML to display import dialogs
+ *
+ * @param String $import_type Import type: server|database|table
+ * @param String $db Selected DB
+ * @param String $table Selected Table
+ * @param int $max_upload_size Max upload size
+ *
+ * @return string $html
+ */
+function PMA_getImportDisplay($import_type, $db, $table, $max_upload_size)
+{
+ global $SESSION_KEY;
+ include_once './libraries/file_listing.lib.php';
+ include_once './libraries/plugin_interface.lib.php';
+ // this one generates also some globals
+ include_once './libraries/display_import_ajax.lib.php';
+
+ /* Scan for plugins */
+ /* @var $import_list ImportPlugin[] */
+ $import_list = PMA_getPlugins(
+ "import",
+ 'libraries/plugins/import/',
+ $import_type
+ );
+
+ /* Fail if we didn't find any plugin */
+ if (empty($import_list)) {
+ PMA_Message::error(
+ __(
+ 'Could not load import plugins, please check your installation!'
+ )
+ )->display();
+ exit;
+ }
+
+ if (PMA_isValid($_REQUEST['offset'], 'numeric')) {
+ $offset = $_REQUEST['offset'];
+ }
+ if (isset($_REQUEST['timeout_passed'])) {
+ $timeout_passed = $_REQUEST['timeout_passed'];
+ }
+
+ $local_import_file = '';
+ if (isset($_REQUEST['local_import_file'])) {
+ $local_import_file = $_REQUEST['local_import_file'];
+ }
+
+ $timeout_passed_str = isset($timeout_passed)? $timeout_passed : null;
+ $offset_str = isset($offset)? $offset : null;
+ return PMA_getHtmlForImport(
+ $upload_id,
+ $import_type,
+ $db,
+ $table,
+ $max_upload_size,
+ $import_list,
+ $timeout_passed_str,
+ $offset_str,
+ $local_import_file
+ );
+}
diff --git a/libraries/display_import_ajax.lib.php b/libraries/display_import_ajax.lib.php
index 04d582565b..4ce10277f7 100644
--- a/libraries/display_import_ajax.lib.php
+++ b/libraries/display_import_ajax.lib.php
@@ -126,4 +126,3 @@ function PMA_importAjaxStatus($id)
$_SESSION[$GLOBALS['SESSION_KEY']]['handler']::getUploadStatus($id)
);
}
-?>
diff --git a/libraries/display_select_lang.lib.php b/libraries/display_select_lang.lib.php
index 0ff4c86cc4..7548c16f96 100644
--- a/libraries/display_select_lang.lib.php
+++ b/libraries/display_select_lang.lib.php
@@ -95,4 +95,3 @@ function PMA_getLanguageSelectorHtml($use_fieldset = false, $show_doc = true)
return $retval;
}
-?>
diff --git a/libraries/display_structure.inc.php b/libraries/display_structure.inc.php
deleted file mode 100644
index 503724d688..0000000000
--- a/libraries/display_structure.inc.php
+++ /dev/null
@@ -1,272 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Displays the table structure ('show table' works correct since 3.23.03)
- *
- * @package PhpMyAdmin
- */
-
-require_once 'libraries/common.inc.php';
-require_once 'libraries/mysql_charsets.inc.php';
-require_once 'libraries/structure.lib.php';
-require_once 'libraries/index.lib.php';
-require_once 'libraries/tbl_info.inc.php';
-
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/* TABLE INFORMATION */
-// table header
-
-
-$HideStructureActions = '';
-if ($GLOBALS['cfg']['HideStructureActions'] === true) {
- $HideStructureActions .= ' HideStructureActions';
-}
-
-$html_form = '<form method="post" action="tbl_structure.php" name="fieldsForm" '
-. 'id="fieldsForm" class="ajax' . $HideStructureActions . '">';
-
-$response->addHTML($html_form);
-$response->addHTML(PMA_URL_getHiddenInputs($db, $table));
-
-$tabletype = '<input type="hidden" name="table_type" value=';
-if ($db_is_system_schema) {
- $tabletype .= '"information_schema" />';
-} else if ($tbl_is_view) {
- $tabletype .= '"view" />';
-} else {
- $tabletype .= '"table" />';
-}
-$response->addHTML($tabletype);
-
-$tablestructure = '<table id="tablestructure" class="data topmargin">';
-$response->addHTML($tablestructure);
-
-
-$response->addHTML(
- PMA_getHtmlForTableStructureHeader(
- $db_is_system_schema,
- $tbl_is_view
- )
-);
-
-$response->addHTML('<tbody>');
-
-// table body
-
-// prepare comments
-$comments_map = array();
-$mime_map = array();
-
-if ($GLOBALS['cfg']['ShowPropertyComments']) {
- include_once 'libraries/transformations.lib.php';
- $comments_map = PMA_getComments($db, $table);
- if ($cfgRelation['mimework'] && $cfg['BrowseMIME']) {
- $mime_map = PMA_getMIME($db, $table, true);
- }
-}
-require_once 'libraries/central_columns.lib.php';
-$central_list = PMA_getCentralColumnsFromTable($db, $table);
-$rownum = 0;
-$columns_list = array();
-$save_row = array();
-$odd_row = true;
-foreach ($fields as $row) {
- $save_row[] = $row;
- $rownum++;
- $columns_list[] = $row['Field'];
-
- $type = $row['Type'];
- $extracted_columnspec = PMA_Util::extractColumnSpec($row['Type']);
-
- if ('set' == $extracted_columnspec['type']
- || 'enum' == $extracted_columnspec['type']
- ) {
- $type_nowrap = '';
- } else {
- $type_nowrap = ' class="nowrap"';
- }
- $type = $extracted_columnspec['print_type'];
- if (empty($type)) {
- $type = ' ';
- }
-
- $field_charset = '';
- if ($extracted_columnspec['can_contain_collation']
- && ! empty($row['Collation'])
- ) {
- $field_charset = $row['Collation'];
- }
-
- // Display basic mimetype [MIME]
- if ($cfgRelation['commwork']
- && $cfgRelation['mimework']
- && $cfg['BrowseMIME']
- && isset($mime_map[$row['Field']]['mimetype'])
- ) {
- $type_mime = '<br />MIME: '
- . str_replace('_', '/', $mime_map[$row['Field']]['mimetype']);
- } else {
- $type_mime = '';
- }
-
- $attribute = $extracted_columnspec['attribute'];
-
- // prepare a common variable to reuse below; however,
- // in case of a VIEW, $analyzed_sql[0]['create_table_fields'] is empty
- if (isset($analyzed_sql[0]['create_table_fields'][$row['Field']])) {
- $tempField = $analyzed_sql[0]['create_table_fields'][$row['Field']];
- } else {
- $tempField = array();
- }
-
- // MySQL 4.1.2+ TIMESTAMP options
- // (if on_update_current_timestamp is set, then it's TRUE)
- if (isset($tempField['on_update_current_timestamp'])) {
- $attribute = 'on update CURRENT_TIMESTAMP';
- }
-
- // here, we have a TIMESTAMP that SHOW FULL COLUMNS reports as having the
- // NULL attribute, but SHOW CREATE TABLE says the contrary. Believe
- // the latter.
- if (! empty($tempField['type'])
- && $tempField['type'] == 'TIMESTAMP'
- && $tempField['timestamp_not_null']
- ) {
- $row['Null'] = '';
- }
-
-
- if (! isset($row['Default'])) {
- if ($row['Null'] == 'YES') {
- $row['Default'] = '<i>NULL</i>';
- }
- } else {
- $row['Default'] = htmlspecialchars($row['Default']);
- }
-
- $field_encoded = urlencode($row['Field']);
- $field_name = htmlspecialchars($row['Field']);
- $displayed_field_name = $field_name;
-
- // underline commented fields and display a hover-title (CSS only)
-
- if (isset($comments_map[$row['Field']])) {
- $displayed_field_name = '<span class="commented_column" title="'
- . htmlspecialchars($comments_map[$row['Field']]) . '">'
- . $field_name . '</span>';
- }
-
- if ($primary && $primary->hasColumn($field_name)) {
- $displayed_field_name .= PMA_Util::getImage(
- 'b_primary.png', __('Primary')
- );
- }
- $response->addHTML(
- '<tr class="' . ($odd_row ? 'odd': 'even') . '">'
- );
- $odd_row = !$odd_row;
- $isInCentralColumns = in_array($row['Field'], $central_list)?true:false;
- $response->addHTML(
- PMA_getHtmlTableStructureRow(
- $row, $rownum, $displayed_field_name,
- $type_nowrap, $extracted_columnspec, $type_mime,
- $field_charset, $attribute, $tbl_is_view,
- $db_is_system_schema, $url_query, $field_encoded, $titles, $table
- )
- );
-
- if (! $tbl_is_view && ! $db_is_system_schema) {
- $response->addHTML(
- PMA_getHtmlForActionsInTableStructure(
- $type, $tbl_storage_engine, $primary,
- $field_name, $url_query, $titles, $row, $rownum,
- $columns_with_unique_index,
- $isInCentralColumns
- )
- );
- } // end if (! $tbl_is_view && ! $db_is_system_schema)
-
- $response->addHTML('</tr>');
-
- unset($field_charset);
-} // end foreach
-
-$response->addHTML('</tbody></table>');
-
-$response->addHTML(
- PMA_getHtmlForCheckAllTableColumn(
- $pmaThemeImage, $text_dir, $tbl_is_view,
- $db_is_system_schema, $tbl_storage_engine
- )
-);
-
-$response->addHTML(
- '</form><hr />'
-);
-$response->addHTML(
- PMA_getHtmlDivForMoveColumnsDialog()
-);
-
-/**
- * Work on the table
- */
-
-$response->addHTML('<div id="structure-action-links">');
-
-if ($tbl_is_view) {
- $response->addHTML(PMA_getHtmlForEditView($url_params));
-}
-$response->addHTML(
- PMA_getHtmlForOptionalActionLinks(
- $url_query, $tbl_is_view, $db_is_system_schema
- )
-);
-
-$response->addHTML('</div>');
-
-if (! $tbl_is_view && ! $db_is_system_schema) {
- $response->addHTML('<br />');
- $response->addHTML(PMA_getHtmlForAddColumn($columns_list));
-}
-
-/**
- * Displays indexes
- */
-
-if (! $tbl_is_view
- && ! $db_is_system_schema
- && 'ARCHIVE' != $tbl_storage_engine
-) {
- //return the list of index
- $response->addJSON(
- 'indexes_list',
- PMA_Index::getView($GLOBALS['table'], $GLOBALS['db'])
- );
- $response->addHTML(PMA_getHtmlForDisplayIndexes());
-}
-
-/**
- * Displays Space usage and row statistics
- */
-// BEGIN - Calc Table Space
-// Get valid statistics whatever is the table type
-if ($cfg['ShowStats']) {
- //get table stats in HTML format
- $tablestats = PMA_getHtmlForDisplayTableStats(
- $showtable, $table_info_num_rows, $tbl_is_view,
- $db_is_system_schema, $tbl_storage_engine,
- $url_query, $tbl_collation
- );
- //returning the response in JSON format to be used by Ajax
- $response->addJSON('tableStat', $tablestats);
- $response->addHTML($tablestats);
-}
-// END - Calc Table Space
-
-$response->addHTML(
- '<div class="clearfloat"></div>'
-);
-?>
diff --git a/libraries/engines/bdb.lib.php b/libraries/engines/bdb.lib.php
index a96e156303..c367e9a61e 100644
--- a/libraries/engines/bdb.lib.php
+++ b/libraries/engines/bdb.lib.php
@@ -84,4 +84,3 @@ class PMA_StorageEngine_Bdb extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/berkeleydb.lib.php b/libraries/engines/berkeleydb.lib.php
index 910211ab04..36c30eff0b 100644
--- a/libraries/engines/berkeleydb.lib.php
+++ b/libraries/engines/berkeleydb.lib.php
@@ -23,4 +23,3 @@ class PMA_StorageEngine_Berkeleydb extends PMA_StorageEngine_Bdb
{
}
-?>
diff --git a/libraries/engines/binlog.lib.php b/libraries/engines/binlog.lib.php
index 65e2c269f8..a144e8f365 100644
--- a/libraries/engines/binlog.lib.php
+++ b/libraries/engines/binlog.lib.php
@@ -28,4 +28,3 @@ class PMA_StorageEngine_Binlog extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/innobase.lib.php b/libraries/engines/innobase.lib.php
index a6cd55f71e..1b8f97af03 100644
--- a/libraries/engines/innobase.lib.php
+++ b/libraries/engines/innobase.lib.php
@@ -22,4 +22,3 @@ require_once './libraries/engines/innodb.lib.php';
class PMA_StorageEngine_Innobase extends PMA_StorageEngine_Innodb
{
}
-?>
diff --git a/libraries/engines/innodb.lib.php b/libraries/engines/innodb.lib.php
index 12e4f29bb2..cb901eede0 100644
--- a/libraries/engines/innodb.lib.php
+++ b/libraries/engines/innodb.lib.php
@@ -26,19 +26,28 @@ class PMA_StorageEngine_Innodb extends PMA_StorageEngine
return array(
'innodb_data_home_dir' => array(
'title' => __('Data home directory'),
- 'desc' => __('The common part of the directory path for all InnoDB data files.'),
+ 'desc' => __(
+ 'The common part of the directory path for all InnoDB data '
+ . 'files.'
+ ),
),
'innodb_data_file_path' => array(
'title' => __('Data files'),
),
'innodb_autoextend_increment' => array(
'title' => __('Autoextend increment'),
- 'desc' => __('The increment size for extending the size of an autoextending tablespace when it becomes full.'),
+ 'desc' => __(
+ 'The increment size for extending the size of an autoextending '
+ . 'tablespace when it becomes full.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_NUMERIC,
),
'innodb_buffer_pool_size' => array(
'title' => __('Buffer pool size'),
- 'desc' => __('The size of the memory buffer InnoDB uses to cache data and indexes of its tables.'),
+ 'desc' => __(
+ 'The size of the memory buffer InnoDB uses to cache data and '
+ . 'indexes of its tables.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE,
),
'innodb_additional_mem_pool_size' => array(
@@ -321,10 +330,10 @@ class PMA_StorageEngine_Innodb extends PMA_StorageEngine
public function getPageStatus()
{
return '<pre id="pre_innodb_status">' . "\n"
- . htmlspecialchars(
- $GLOBALS['dbi']->fetchValue('SHOW ENGINE INNODB STATUS;', 0, 'Status')
- ) . "\n"
- . '</pre>' . "\n";
+ . htmlspecialchars(
+ $GLOBALS['dbi']->fetchValue('SHOW ENGINE INNODB STATUS;', 0, 'Status')
+ ) . "\n"
+ . '</pre>' . "\n";
}
/**
@@ -389,4 +398,3 @@ class PMA_StorageEngine_Innodb extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/memory.lib.php b/libraries/engines/memory.lib.php
index 9a64f396aa..074eb2e01f 100644
--- a/libraries/engines/memory.lib.php
+++ b/libraries/engines/memory.lib.php
@@ -31,4 +31,3 @@ class PMA_StorageEngine_Memory extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/merge.lib.php b/libraries/engines/merge.lib.php
index 6fee0bd3cf..e435bdd9bf 100644
--- a/libraries/engines/merge.lib.php
+++ b/libraries/engines/merge.lib.php
@@ -18,4 +18,3 @@ class PMA_StorageEngine_Merge extends PMA_StorageEngine
{
}
-?>
diff --git a/libraries/engines/mrg_myisam.lib.php b/libraries/engines/mrg_myisam.lib.php
index 3e52440608..22b73ec64a 100644
--- a/libraries/engines/mrg_myisam.lib.php
+++ b/libraries/engines/mrg_myisam.lib.php
@@ -33,4 +33,3 @@ class PMA_StorageEngine_MrgMyisam extends PMA_StorageEngine_Merge
}
}
-?>
diff --git a/libraries/engines/myisam.lib.php b/libraries/engines/myisam.lib.php
index e2591dab24..7035673b8e 100644
--- a/libraries/engines/myisam.lib.php
+++ b/libraries/engines/myisam.lib.php
@@ -24,33 +24,55 @@ class PMA_StorageEngine_Myisam extends PMA_StorageEngine
public function getVariables()
{
return array(
- 'myisam_data_pointer_size' => array(
+ 'myisam_data_pointer_size' => array(
'title' => __('Data pointer size'),
- 'desc' => __('The default pointer size in bytes, to be used by CREATE TABLE for MyISAM tables when no MAX_ROWS option is specified.'),
+ 'desc' => __(
+ 'The default pointer size in bytes, to be used by CREATE TABLE '
+ . 'for MyISAM tables when no MAX_ROWS option is specified.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE,
),
- 'myisam_recover_options' => array(
+ 'myisam_recover_options' => array(
'title' => __('Automatic recovery mode'),
- 'desc' => __('The mode for automatic recovery of crashed MyISAM tables, as set via the --myisam-recover server startup option.'),
+ 'desc' => __(
+ 'The mode for automatic recovery of crashed MyISAM tables, as '
+ . 'set via the --myisam-recover server startup option.'
+ ),
),
- 'myisam_max_sort_file_size' => array(
+ 'myisam_max_sort_file_size' => array(
'title' => __('Maximum size for temporary sort files'),
- 'desc' => __('The maximum size of the temporary file MySQL is allowed to use while re-creating a MyISAM index (during REPAIR TABLE, ALTER TABLE, or LOAD DATA INFILE).'),
+ 'desc' => __(
+ 'The maximum size of the temporary file MySQL is allowed to use '
+ . 'while re-creating a MyISAM index (during REPAIR TABLE, ALTER '
+ . 'TABLE, or LOAD DATA INFILE).'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE,
),
'myisam_max_extra_sort_file_size' => array(
'title' => __('Maximum size for temporary files on index creation'),
- 'desc' => __('If the temporary file used for fast MyISAM index creation would be larger than using the key cache by the amount specified here, prefer the key cache method.'),
+ 'desc' => __(
+ 'If the temporary file used for fast MyISAM index creation '
+ . 'would be larger than using the key cache by the amount '
+ . 'specified here, prefer the key cache method.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE,
),
'myisam_repair_threads' => array(
'title' => __('Repair threads'),
- 'desc' => __('If this value is greater than 1, MyISAM table indexes are created in parallel (each index in its own thread) during the repair by sorting process.'),
+ 'desc' => __(
+ 'If this value is greater than 1, MyISAM table indexes are '
+ . 'created in parallel (each index in its own thread) during '
+ . 'the repair by sorting process.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_NUMERIC,
),
'myisam_sort_buffer_size' => array(
'title' => __('Sort buffer size'),
- 'desc' => __('The buffer that is allocated when sorting MyISAM indexes during a REPAIR TABLE or when creating indexes with CREATE INDEX or ALTER TABLE.'),
+ 'desc' => __(
+ 'The buffer that is allocated when sorting MyISAM indexes '
+ . 'during a REPAIR TABLE or when creating indexes with CREATE '
+ . 'INDEX or ALTER TABLE.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE,
),
'myisam_stats_method' => array(
@@ -66,4 +88,3 @@ class PMA_StorageEngine_Myisam extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/ndbcluster.lib.php b/libraries/engines/ndbcluster.lib.php
index 3ee56e6e91..7b47c49a84 100644
--- a/libraries/engines/ndbcluster.lib.php
+++ b/libraries/engines/ndbcluster.lib.php
@@ -52,4 +52,3 @@ class PMA_StorageEngine_Ndbcluster extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/pbxt.lib.php b/libraries/engines/pbxt.lib.php
index fe80cde8b9..224e7d64d1 100644
--- a/libraries/engines/pbxt.lib.php
+++ b/libraries/engines/pbxt.lib.php
@@ -26,47 +26,86 @@ class PMA_StorageEngine_Pbxt extends PMA_StorageEngine
return array(
'pbxt_index_cache_size' => array(
'title' => __('Index cache size'),
- 'desc' => __('This is the amount of memory allocated to the index cache. Default value is 32MB. The memory allocated here is used only for caching index pages.'),
+ 'desc' => __(
+ 'This is the amount of memory allocated to the'
+ . ' index cache. Default value is 32MB. The memory'
+ . ' allocated here is used only for caching index pages.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_record_cache_size' => array(
'title' => __('Record cache size'),
- 'desc' => __('This is the amount of memory allocated to the record cache used to cache table data. The default value is 32MB. This memory is used to cache changes to the handle data (.xtd) and row pointer (.xtr) files.'),
+ 'desc' => __(
+ 'This is the amount of memory allocated to the'
+ . ' record cache used to cache table data. The default'
+ . ' value is 32MB. This memory is used to cache changes to'
+ . ' the handle data (.xtd) and row pointer (.xtr) files.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_log_cache_size' => array(
'title' => __('Log cache size'),
- 'desc' => __('The amount of memory allocated to the transaction log cache used to cache on transaction log data. The default is 16MB.'),
+ 'desc' => __(
+ 'The amount of memory allocated to the'
+ . ' transaction log cache used to cache on transaction log'
+ . ' data. The default is 16MB.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_log_file_threshold' => array(
'title' => __('Log file threshold'),
- 'desc' => __('The size of a transaction log before rollover, and a new log is created. The default value is 16MB.'),
+ 'desc' => __(
+ 'The size of a transaction log before rollover,'
+ . ' and a new log is created. The default value is 16MB.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_transaction_buffer_size' => array(
'title' => __('Transaction buffer size'),
- 'desc' => __('The size of the global transaction log buffer (the engine allocates 2 buffers of this size). The default is 1MB.'),
+ 'desc' => __(
+ 'The size of the global transaction log buffer'
+ . ' (the engine allocates 2 buffers of this size).'
+ . ' The default is 1MB.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_checkpoint_frequency' => array(
'title' => __('Checkpoint frequency'),
- 'desc' => __('The amount of data written to the transaction log before a checkpoint is performed. The default value is 24MB.'),
+ 'desc' => __(
+ 'The amount of data written to the transaction'
+ . ' log before a checkpoint is performed.'
+ . ' The default value is 24MB.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_data_log_threshold' => array(
'title' => __('Data log threshold'),
- 'desc' => __('The maximum size of a data log file. The default value is 64MB. PBXT can create a maximum of 32000 data logs, which are used by all tables. So the value of this variable can be increased to increase the total amount of data that can be stored in the database.'),
+ 'desc' => __(
+ 'The maximum size of a data log file. The default'
+ . ' value is 64MB. PBXT can create a maximum of 32000 data'
+ . ' logs, which are used by all tables. So the value of'
+ . ' this variable can be increased to increase the total'
+ . ' amount of data that can be stored in the database.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_garbage_threshold' => array(
'title' => __('Garbage threshold'),
- 'desc' => __('The percentage of garbage in a data log file before it is compacted. This is a value between 1 and 99. The default is 50.'),
+ 'desc' => __(
+ 'The percentage of garbage in a data log file'
+ . ' before it is compacted. This is a value between 1 and'
+ . ' 99. The default is 50.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_NUMERIC
),
'pbxt_log_buffer_size' => array(
'title' => __('Log buffer size'),
- 'desc' => __('The size of the buffer used when writing a data log. The default is 256MB. The engine allocates one buffer per thread, but only if the thread is required to write a data log.'),
+ 'desc' => __(
+ 'The size of the buffer used when writing a data'
+ . ' log. The default is 256MB. The engine allocates one'
+ . ' buffer per thread, but only if the thread is required'
+ . ' to write a data log.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_SIZE
),
'pbxt_data_file_grow_size' => array(
@@ -81,7 +120,13 @@ class PMA_StorageEngine_Pbxt extends PMA_StorageEngine
),
'pbxt_log_file_count' => array(
'title' => __('Log file count'),
- 'desc' => __('This is the number of transaction log files (pbxt/system/xlog*.xt) the system will maintain. If the number of logs exceeds this value then old logs will be deleted, otherwise they are renamed and given the next highest number.'),
+ 'desc' => __(
+ 'This is the number of transaction log files'
+ . ' (pbxt/system/xlog*.xt) the system will maintain. If the'
+ . ' number of logs exceeds this value then old logs will be'
+ . ' deleted, otherwise they are renamed and given the next'
+ . ' highest number.'
+ ),
'type' => PMA_ENGINE_DETAILS_TYPE_NUMERIC
),
);
@@ -146,4 +191,3 @@ class PMA_StorageEngine_Pbxt extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/engines/performance_schema.lib.php b/libraries/engines/performance_schema.lib.php
index ae445825dd..80ea571455 100644
--- a/libraries/engines/performance_schema.lib.php
+++ b/libraries/engines/performance_schema.lib.php
@@ -28,4 +28,3 @@ class PMA_StorageEngine_PerformanceSchema extends PMA_StorageEngine
}
}
-?>
diff --git a/libraries/error_report.lib.php b/libraries/error_report.lib.php
index 5766b01f36..0ac7ce56b8 100644
--- a/libraries/error_report.lib.php
+++ b/libraries/error_report.lib.php
@@ -27,7 +27,7 @@ if (is_readable('js/line_counts.php')) {
/**
* the url where to submit reports to
*/
-define('SUBMISSION_URL', "http://reports.phpmyadmin.net/incidents/create");
+define('SUBMISSION_URL', "https://reports.phpmyadmin.net/incidents/create");
/**
* returns the pretty printed error report data collected from the
@@ -95,13 +95,14 @@ function PMA_getReportData($exception_type = 'js')
} elseif ($exception_type == 'php') {
$errors = array();
// create php error report
- $i=0;
+ $i = 0;
if (!isset($_SESSION['prev_errors'])
|| $_SESSION['prev_errors'] == ''
) {
return array();
}
foreach ($_SESSION['prev_errors'] as $errorObj) {
+ /* @var $errorObj PMA_Error */
if ($errorObj->getLine()
&& $errorObj->getType()
&& $errorObj->getNumber() != E_USER_WARNING
@@ -342,49 +343,20 @@ function PMA_translateStacktrace($stack)
*/
function PMA_getErrorReportForm()
{
- $html = "";
- $html .= '<form action="error_report.php" method="post" name="report_frm"'
- . ' id="report_frm" class="ajax">'
- . '<fieldset style="padding-top:0px">';
-
- $html .= '<p>' . __(
- 'phpMyAdmin has encountered an error. We have collected data about'
- . ' this error as well as information about relevant configuration'
- . ' settings to send to the phpMyAdmin team to help us in'
- . ' debugging the problem.'
- ) . '</p>';
-
- $html .= '<div class="label"><label><p>'
- . __('You may examine the data in the error report:')
- . '</p></label></div>'
- . '<pre class="report-data">'
- . htmlspecialchars(PMA_getPrettyReportData())
- . '</pre>';
-
- $html .= '<div class="label"><label><p>'
- . __('Please explain the steps that lead to the error:')
- . '</p></label></div>'
- . '<textarea class="report-description" name="description"'
- . 'id="report_description"></textarea>';
-
- $html .= '<input type="checkbox" name="always_send"'
- . ' id="always_send_checkbox"/>'
- . '<label for="always_send_checkbox">'
- . __('Automatically send report next time')
- . '</label>';
-
- $html .= '</fieldset>';
-
- $html .= PMA_URL_getHiddenInputs();
+ $datas = array(
+ 'report_data' => PMA_getPrettyReportData(),
+ 'hidden_inputs' => PMA_URL_getHiddenInputs(),
+ 'hidden_fields' => null,
+ );
$reportData = PMA_getReportData();
- if (! empty($reportData)) {
- $html .= PMA_getHiddenFields($reportData);
+ if (!empty($reportData)) {
+ $datas['hidden_fields'] = PMA_getHiddenFields($reportData);
}
- $html .= '</form>';
-
- return $html;
+ include_once './libraries/Template.class.php';
+ return PMA\Template::get('error/report_form')
+ ->render($datas);
}
/**
@@ -429,4 +401,3 @@ function PMA_prettyPrint($object, $namespace="")
return $output;
}
-?>
diff --git a/libraries/export.lib.php b/libraries/export.lib.php
index b0b05041da..7dc5af7393 100644
--- a/libraries/export.lib.php
+++ b/libraries/export.lib.php
@@ -102,7 +102,7 @@ function PMA_exportOutputHandler($line)
if ($GLOBALS['output_charset_conversion']) {
$dump_buffer = PMA_convertString(
'utf-8',
- $GLOBALS['charset_of_file'],
+ $GLOBALS['charset'],
$dump_buffer
);
}
@@ -142,7 +142,7 @@ function PMA_exportOutputHandler($line)
if ($GLOBALS['output_charset_conversion']) {
$line = PMA_convertString(
'utf-8',
- $GLOBALS['charset_of_file'],
+ $GLOBALS['charset'],
$line
);
}
@@ -242,11 +242,11 @@ function PMA_getMemoryLimitForExport()
/**
* Return the filename and MIME type for export file
*
- * @param string $export_type type of export
- * @param string $remember_template whether to remember template
- * @param object $export_plugin the export plugin
- * @param string $compression compression asked
- * @param string $filename_template the filename template
+ * @param string $export_type type of export
+ * @param string $remember_template whether to remember template
+ * @param ExportPlugin $export_plugin the export plugin
+ * @param string $compression compression asked
+ * @param string $filename_template the filename template
*
* @return array the filename template and mime type
*/
@@ -328,9 +328,9 @@ function PMA_openExportFile($filename, $quick_export)
. preg_replace('@[/\\\\]@', '_', $filename);
if (file_exists($save_filename)
- && ((! $quick_export && empty($_REQUEST['onserverover']))
+ && ((! $quick_export && empty($_REQUEST['onserver_overwrite']))
|| ($quick_export
- && $_REQUEST['quick_export_onserverover'] != 'saveitover'))
+ && $_REQUEST['quick_export_onserver_overwrite'] != 'saveitover'))
) {
$message = PMA_Message::error(
__(
@@ -404,11 +404,24 @@ function PMA_closeExportFile($file_handle, $dump_buffer, $save_filename)
function PMA_compressExport($dump_buffer, $compression, $filename)
{
if ($compression == 'zip' && @function_exists('gzcompress')) {
+ $filename = substr($filename, 0, -4); // remove extension (.zip)
$zipfile = new ZipFile();
- $zipfile->addFile(
- $dump_buffer,
- substr($filename, 0, -4)
- );
+ if (is_array($dump_buffer)) {
+ foreach ($dump_buffer as $table => $dump) {
+ $ext_pos = strpos($filename, '.');
+ $extension = substr($filename, $ext_pos);
+ $zipfile->addFile(
+ $dump,
+ str_replace(
+ $extension,
+ '_' . $table . $extension,
+ $filename
+ )
+ );
+ }
+ } else {
+ $zipfile->addFile($dump_buffer, $filename);
+ }
$dump_buffer = $zipfile->file();
} elseif ($compression == 'gzip' && PMA_gzencodeNeeded()) {
// without the optional parameter level because it bugs
@@ -418,6 +431,34 @@ function PMA_compressExport($dump_buffer, $compression, $filename)
}
/**
+ * Saves the dump_buffer for a particular table in an array
+ * Used in separate files export
+ *
+ * @param string $object_name the name of current object to be stored
+ * @param boolean $append optional boolean to append to an existing index or not
+ *
+ * @return void
+ */
+function PMA_saveObjectInBuffer($object_name, $append = false)
+{
+
+ global $dump_buffer_objects, $dump_buffer, $dump_buffer_len;
+
+ if (! empty($dump_buffer)) {
+ if ($append && isset($dump_buffer_objects[$object_name])) {
+ $dump_buffer_objects[$object_name] .= $dump_buffer;
+ } else {
+ $dump_buffer_objects[$object_name] = $dump_buffer;
+ }
+ }
+
+ // Re - initialize
+ $dump_buffer = '';
+ $dump_buffer_len = 0;
+
+}
+
+/**
* Returns HTML containing the header for a displayed export
*
* @param string $export_type the export type
@@ -450,10 +491,23 @@ function PMA_getHtmlForDisplayedExportHeader($export_type, $db, $table)
// Convert the multiple select elements from an array to a string
if ($export_type == 'server' && isset($_REQUEST['db_select'])) {
$_REQUEST['db_select'] = implode(",", $_REQUEST['db_select']);
- } elseif ($export_type == 'database'
- && isset($_REQUEST['table_select'])
- ) {
- $_REQUEST['table_select'] = implode(",", $_REQUEST['table_select']);
+ } elseif ($export_type == 'database') {
+ if (isset($_REQUEST['table_select'])) {
+ $_REQUEST['table_select'] = implode(",", $_REQUEST['table_select']);
+ }
+ if (isset($_REQUEST['table_structure'])) {
+ $_REQUEST['table_structure'] = implode(
+ ",",
+ $_REQUEST['table_structure']
+ );
+ } else if (empty($_REQUEST['structure_or_data_forced'])) {
+ $_REQUEST['table_structure'] = '';
+ }
+ if (isset($_REQUEST['table_data'])) {
+ $_REQUEST['table_data'] = implode(",", $_REQUEST['table_data']);
+ } else if (empty($_REQUEST['structure_or_data_forced'])) {
+ $_REQUEST['table_data'] = '';
+ }
}
foreach ($_REQUEST as $name => $value) {
@@ -474,24 +528,25 @@ function PMA_getHtmlForDisplayedExportHeader($export_type, $db, $table)
/**
* Export at the server level
*
- * @param string $db_select the selected databases to export
- * @param string $whatStrucOrData structure or data or both
- * @param object $export_plugin the selected export plugin
- * @param string $crlf end of line character(s)
- * @param string $err_url the URL in case of error
- * @param string $export_type the export type
- * @param bool $do_relation whether to export relation info
- * @param bool $do_comments whether to add comments
- * @param bool $do_mime whether to add MIME info
- * @param bool $do_dates whether to add dates
- * @param array $aliases Alias information for db/table/column
+ * @param string $db_select the selected databases to export
+ * @param string $whatStrucOrData structure or data or both
+ * @param ExportPlugin $export_plugin the selected export plugin
+ * @param string $crlf end of line character(s)
+ * @param string $err_url the URL in case of error
+ * @param string $export_type the export type
+ * @param bool $do_relation whether to export relation info
+ * @param bool $do_comments whether to add comments
+ * @param bool $do_mime whether to add MIME info
+ * @param bool $do_dates whether to add dates
+ * @param array $aliases alias information for db/table/column
+ * @param string $separate_files whether it is a separate-files export
*
* @return void
*/
function PMA_exportServer(
$db_select, $whatStrucOrData, $export_plugin, $crlf, $err_url,
$export_type, $do_relation, $do_comments, $do_mime, $do_dates,
- $aliases
+ $aliases, $separate_files
) {
if (! empty($db_select)) {
$tmp_select = implode($db_select, '|');
@@ -504,10 +559,14 @@ function PMA_exportServer(
) {
$tables = $GLOBALS['dbi']->getTables($current_db);
PMA_exportDatabase(
- $current_db, $tables, $whatStrucOrData, $export_plugin, $crlf,
- $err_url, $export_type, $do_relation, $do_comments, $do_mime,
- $do_dates, $aliases
+ $current_db, $tables, $whatStrucOrData, $tables, $tables,
+ $export_plugin, $crlf, $err_url, $export_type, $do_relation,
+ $do_comments, $do_mime, $do_dates, $aliases,
+ $separate_files == 'database' ? $separate_files : ''
);
+ if ($separate_files == 'server') {
+ PMA_saveObjectInBuffer($current_db);
+ }
}
} // end foreach database
}
@@ -515,72 +574,80 @@ function PMA_exportServer(
/**
* Export at the database level
*
- * @param string $db the database to export
- * @param array $tables the tables to export
- * @param string $whatStrucOrData structure or data or both
- * @param object $export_plugin the selected export plugin
- * @param string $crlf end of line character(s)
- * @param string $err_url the URL in case of error
- * @param string $export_type the export type
- * @param bool $do_relation whether to export relation info
- * @param bool $do_comments whether to add comments
- * @param bool $do_mime whether to add MIME info
- * @param bool $do_dates whether to add dates
- * @param array $aliases Alias information for db/table/column
+ * @param string $db the database to export
+ * @param array $tables the tables to export
+ * @param string $whatStrucOrData structure or data or both
+ * @param array $table_structure whether to export structure for each table
+ * @param array $table_data whether to export data for each table
+ * @param ExportPlugin $export_plugin the selected export plugin
+ * @param string $crlf end of line character(s)
+ * @param string $err_url the URL in case of error
+ * @param string $export_type the export type
+ * @param bool $do_relation whether to export relation info
+ * @param bool $do_comments whether to add comments
+ * @param bool $do_mime whether to add MIME info
+ * @param bool $do_dates whether to add dates
+ * @param array $aliases Alias information for db/table/column
+ * @param string $separate_files whether it is a separate-files export
*
* @return void
*/
function PMA_exportDatabase(
- $db, $tables, $whatStrucOrData, $export_plugin, $crlf, $err_url,
- $export_type, $do_relation, $do_comments, $do_mime, $do_dates,
- $aliases
+ $db, $tables, $whatStrucOrData, $table_structure, $table_data,
+ $export_plugin, $crlf, $err_url, $export_type, $do_relation,
+ $do_comments, $do_mime, $do_dates, $aliases, $separate_files
) {
$db_alias = !empty($aliases[$db]['alias'])
? $aliases[$db]['alias'] : '';
+
if (! $export_plugin->exportDBHeader($db, $db_alias)) {
return;
}
- if (! $export_plugin->exportDBCreate($db, $db_alias)) {
+ if (! $export_plugin->exportDBCreate($db, $export_type, $db_alias)) {
return;
}
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('database', true);
+ }
- if (method_exists($export_plugin, 'exportRoutines')
- && /*overload*/mb_strpos(
- $GLOBALS['sql_structure_or_data'],
- 'structure'
- ) !== false
+ if (($GLOBALS['sql_structure_or_data'] == 'structure'
+ || $GLOBALS['sql_structure_or_data'] == 'structure_and_data')
&& isset($GLOBALS['sql_procedure_function'])
) {
$export_plugin->exportRoutines($db, $aliases);
+
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('routines');
+ }
}
$views = array();
foreach ($tables as $table) {
+ $_table = new PMA_Table($table, $db);
// if this is a view, collect it for later;
// views must be exported after the tables
- $is_view = PMA_Table::isView($db, $table);
+ $is_view = $_table->isView();
if ($is_view) {
$views[] = $table;
}
- if ($whatStrucOrData == 'structure'
- || $whatStrucOrData == 'structure_and_data'
+ if (($whatStrucOrData == 'structure'
+ || $whatStrucOrData == 'structure_and_data')
+ && in_array($table, $table_structure)
) {
// for a view, export a stand-in definition of the table
- // to resolve view dependencies
-
+ // to resolve view dependencies (only when it's a single-file export)
if ($is_view) {
-
- if (isset($GLOBALS['sql_create_view'])) {
- if (! $export_plugin->exportStructure(
+ if ($separate_files == ''
+ && isset($GLOBALS['sql_create_view'])
+ && ! $export_plugin->exportStructure(
$db, $table, $crlf, $err_url, 'stand_in',
$export_type, $do_relation, $do_comments,
$do_mime, $do_dates, $aliases
- )) {
- break 1;
- }
+ )
+ ) {
+ break;
}
-
} else if (isset($GLOBALS['sql_create_table'])) {
$table_size = $GLOBALS['maxsize'];
@@ -606,7 +673,7 @@ function PMA_exportDatabase(
$export_type, $do_relation, $do_comments,
$do_mime, $do_dates, $aliases
)) {
- break 1;
+ break;
}
}
@@ -615,29 +682,42 @@ function PMA_exportDatabase(
// if this is a view or a merge table, don't export data
if (($whatStrucOrData == 'data'
|| $whatStrucOrData == 'structure_and_data')
- && ! ($is_view || PMA_Table::isMerge($db, $table))
+ && in_array($table, $table_data)
+ && ! ($is_view || $_table->isMerge())
) {
$local_query = 'SELECT * FROM ' . PMA_Util::backquote($db)
. '.' . PMA_Util::backquote($table);
if (! $export_plugin->exportData(
$db, $table, $crlf, $err_url, $local_query, $aliases
)) {
- break 1;
+ break;
}
}
+
+ // this buffer was filled, we save it and go to the next one
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('table_' . $table);
+ }
+
// now export the triggers (needs to be done after the data because
// triggers can modify already imported tables)
if (isset($GLOBALS['sql_create_trigger']) && ($whatStrucOrData == 'structure'
|| $whatStrucOrData == 'structure_and_data')
+ && in_array($table, $table_structure)
) {
if (! $export_plugin->exportStructure(
$db, $table, $crlf, $err_url, 'triggers',
$export_type, $do_relation, $do_comments,
$do_mime, $do_dates, $aliases
)) {
- break 1;
+ break;
+ }
+
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('table_' . $table, true);
}
}
+
}
if (isset($GLOBALS['sql_create_view'])) {
@@ -652,44 +732,68 @@ function PMA_exportDatabase(
$export_type, $do_relation, $do_comments,
$do_mime, $do_dates, $aliases
)) {
- break 1;
+ break;
+ }
+
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('view_' . $view);
}
}
}
}
- if (! $export_plugin->exportDBFooter($db, $db_alias)) {
+ if (! $export_plugin->exportDBFooter($db)) {
return;
}
+ // export metadata related to this db
+ if (isset($GLOBALS['sql_metadata'])) {
+ // Types of metadata to export.
+ // In the future these can be allowed to be selected by the user
+ $metadataTypes = PMA_getMetadataTypesToExport();
+ $export_plugin->exportMetadata($db, $tables, $metadataTypes);
+
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('metadata');
+ }
+ }
+
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('extra');
+ }
+
if (($GLOBALS['sql_structure_or_data'] == 'structure'
|| $GLOBALS['sql_structure_or_data'] == 'structure_and_data')
&& isset($GLOBALS['sql_procedure_function'])
) {
- $export_plugin->exportEvents($db, $aliases);
+ $export_plugin->exportEvents($db);
+
+ if ($separate_files == 'database') {
+ PMA_saveObjectInBuffer('events');
+ }
}
}
/**
* Export at the table level
*
- * @param string $db the database to export
- * @param string $table the table to export
- * @param string $whatStrucOrData structure or data or both
- * @param object $export_plugin the selected export plugin
- * @param string $crlf end of line character(s)
- * @param string $err_url the URL in case of error
- * @param string $export_type the export type
- * @param bool $do_relation whether to export relation info
- * @param bool $do_comments whether to add comments
- * @param bool $do_mime whether to add MIME info
- * @param bool $do_dates whether to add dates
- * @param string $allrows whether "dump all rows" was ticked
- * @param string $limit_to upper limit
- * @param string $limit_from starting limit
- * @param string $sql_query query for which exporting is requested
- * @param array $aliases Alias information for db/table/column
+ * @param string $db the database to export
+ * @param string $table the table to export
+ * @param string $whatStrucOrData structure or data or both
+ * @param ExportPlugin $export_plugin the selected export plugin
+ * @param string $crlf end of line character(s)
+ * @param string $err_url the URL in case of error
+ * @param string $export_type the export type
+ * @param bool $do_relation whether to export relation info
+ * @param bool $do_comments whether to add comments
+ * @param bool $do_mime whether to add MIME info
+ * @param bool $do_dates whether to add dates
+ * @param string $allrows whether "dump all rows" was ticked
+ * @param string $limit_to upper limit
+ * @param string $limit_from starting limit
+ * @param string $sql_query query for which exporting is requested
+ * @param array $aliases Alias information for db/table/column
*
* @return void
*/
@@ -715,7 +819,8 @@ function PMA_exportTable(
$add_query = '';
}
- $is_view = PMA_Table::isView($db, $table);
+ $_table = new PMA_Table($table, $db);
+ $is_view = $_table->isView();
if ($whatStrucOrData == 'structure'
|| $whatStrucOrData == 'structure_and_data'
) {
@@ -750,7 +855,7 @@ function PMA_exportTable(
// if it is a merge table, no data is exported
if (($whatStrucOrData == 'data'
|| $whatStrucOrData == 'structure_and_data')
- && ! PMA_Table::isMerge($db, $table)
+ && ! $GLOBALS['dbi']->getTable($db, $table)->isMerge()
) {
if (! empty($sql_query)) {
// only preg_replace if needed
@@ -783,9 +888,16 @@ function PMA_exportTable(
return;
}
}
- if (! $export_plugin->exportDBFooter($db, $db_alias)) {
+ if (! $export_plugin->exportDBFooter($db)) {
return;
}
+
+ if (isset($GLOBALS['sql_metadata'])) {
+ // Types of metadata to export.
+ // In the future these can be allowed to be selected by the user
+ $metadataTypes = PMA_getMetadataTypesToExport();
+ $export_plugin->exportMetadata($db, $table, $metadataTypes);
+ }
}
/**
@@ -866,4 +978,72 @@ function PMA_mergeAliases($aliases1, $aliases2)
}
return $aliases;
}
-?>
+
+/**
+ * Locks tables
+ *
+ * @param string $db database name
+ * @param array $tables list of table names
+ * @param string $lockType lock type; "[LOW_PRIORITY] WRITE" or "READ [LOCAL]"
+ *
+ * @return mixed result of the query
+ */
+function PMA_lockTables($db, $tables, $lockType = "WRITE")
+{
+ $locks = array();
+ foreach ($tables as $table) {
+ $locks[] = PMA_Util::backquote($db) . "." . PMA_Util::backquote($table)
+ . " " . $lockType;
+ }
+
+ $sql = "LOCK TABLES " . implode(", ", $locks);
+ return $GLOBALS['dbi']->tryQuery($sql);
+}
+
+/**
+ * Releases table locks
+ *
+ * @return mixed result of the query
+ */
+function PMA_unlockTables()
+{
+ return $GLOBALS['dbi']->tryQuery("UNLOCK TABLES");
+}
+
+/**
+ * Returns all the metadata types that can be exported with a database or a table
+ *
+ * @return array metadata types.
+ */
+function PMA_getMetadataTypesToExport()
+{
+ return array(
+ 'column_info',
+ 'table_uiprefs',
+ 'tracking',
+ 'bookmark',
+ 'relation',
+ 'table_coords',
+ 'pdf_pages',
+ 'savedsearches',
+ 'central_columns',
+ 'export_templates',
+ );
+}
+
+/**
+ * Returns the checked clause, depending on the presence of key in array
+ *
+ * @param array $array array to verify
+ * @param string $key the key to look for
+ *
+ * @return string the checked clause
+ */
+function PMA_getCheckedClause($array, $key)
+{
+ if (in_array($array, $key)) {
+ return ' checked="checked"';
+ } else {
+ return '';
+ }
+}
diff --git a/libraries/gis/GIS_Factory.class.php b/libraries/gis/GIS_Factory.class.php
index 4a9474329e..4c27cd1e3c 100644
--- a/libraries/gis/GIS_Factory.class.php
+++ b/libraries/gis/GIS_Factory.class.php
@@ -63,4 +63,3 @@ class PMA_GIS_Factory
}
}
}
-?>
diff --git a/libraries/gis/GIS_Geometry.class.php b/libraries/gis/GIS_Geometry.class.php
index b5b7b78952..8645465c72 100644
--- a/libraries/gis/GIS_Geometry.class.php
+++ b/libraries/gis/GIS_Geometry.class.php
@@ -373,4 +373,3 @@ abstract class PMA_GIS_Geometry
. $srid . '"), map.getProjectionObject())';
}
}
-?>
diff --git a/libraries/gis/GIS_Geometrycollection.class.php b/libraries/gis/GIS_Geometrycollection.class.php
index fd05327d40..c972dd729b 100644
--- a/libraries/gis/GIS_Geometrycollection.class.php
+++ b/libraries/gis/GIS_Geometrycollection.class.php
@@ -361,4 +361,3 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry
return $params;
}
}
-?>
diff --git a/libraries/gis/GIS_Linestring.class.php b/libraries/gis/GIS_Linestring.class.php
index eb1e8ce122..81d025d92d 100644
--- a/libraries/gis/GIS_Linestring.class.php
+++ b/libraries/gis/GIS_Linestring.class.php
@@ -320,4 +320,3 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry
return $params;
}
}
-?>
diff --git a/libraries/gis/GIS_Multilinestring.class.php b/libraries/gis/GIS_Multilinestring.class.php
index 5ebb55ee1a..60ecef40f3 100644
--- a/libraries/gis/GIS_Multilinestring.class.php
+++ b/libraries/gis/GIS_Multilinestring.class.php
@@ -391,4 +391,3 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry
return $params;
}
}
-?>
diff --git a/libraries/gis/GIS_Multipoint.class.php b/libraries/gis/GIS_Multipoint.class.php
index 0d9692402a..6093d8e1fd 100644
--- a/libraries/gis/GIS_Multipoint.class.php
+++ b/libraries/gis/GIS_Multipoint.class.php
@@ -364,4 +364,3 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry
return $ol_array;
}
}
-?>
diff --git a/libraries/gis/GIS_Multipolygon.class.php b/libraries/gis/GIS_Multipolygon.class.php
index c17d5e5832..4247b1c551 100644
--- a/libraries/gis/GIS_Multipolygon.class.php
+++ b/libraries/gis/GIS_Multipolygon.class.php
@@ -561,4 +561,3 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry
return $params;
}
}
-?>
diff --git a/libraries/gis/GIS_Point.class.php b/libraries/gis/GIS_Point.class.php
index 14cd7837fd..7c43c118de 100644
--- a/libraries/gis/GIS_Point.class.php
+++ b/libraries/gis/GIS_Point.class.php
@@ -311,4 +311,3 @@ class PMA_GIS_Point extends PMA_GIS_Geometry
return $params;
}
}
-?>
diff --git a/libraries/gis/GIS_Polygon.class.php b/libraries/gis/GIS_Polygon.class.php
index 566c7b37f2..843a8b530f 100644
--- a/libraries/gis/GIS_Polygon.class.php
+++ b/libraries/gis/GIS_Polygon.class.php
@@ -578,4 +578,3 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry
return $params;
}
}
-?>
diff --git a/libraries/gis/GIS_Visualization.class.php b/libraries/gis/GIS_Visualization.class.php
index f5b1d3c544..393018a021 100644
--- a/libraries/gis/GIS_Visualization.class.php
+++ b/libraries/gis/GIS_Visualization.class.php
@@ -10,6 +10,8 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/sql.lib.php';
+
/**
* Handles visualization of GIS data
*
@@ -22,6 +24,8 @@ class PMA_GIS_Visualization
*/
private $_data;
+ private $_modified_sql;
+
/**
* @var array Set of default settings values are here.
*/
@@ -72,17 +76,73 @@ class PMA_GIS_Visualization
}
/**
- * Constructor. Stores user specified options.
+ * Factory
+ *
+ * @param string $sql_query SQL to fetch raw data for visualization
+ * @param array $options Users specified options
+ * @param integer $row number of rows
+ * @param integer $pos start position
+ *
+ * @return PMA_GIS_Visualization
*
- * @param array $data Data for the visualization
+ * @access public
+ */
+ public static function get($sql_query, $options, $row, $pos)
+ {
+ return new PMA_GIS_Visualization($sql_query, $options, $row, $pos);
+ }
+
+ /**
+ * Get visualization
+ *
+ * @param array $data Raw data, if set, parameters other than $options will be
+ * ignored
* @param array $options Users specified options
*
+ * @return PMA_GIS_Visualization
+ */
+ public static function getByData($data, $options)
+ {
+ return new PMA_GIS_Visualization(null, $options, null, null, $data);
+ }
+
+ /**
+ * Check if data has SRID
+ *
+ * @return bool
+ */
+ public function hasSrid()
+ {
+ foreach ($this->_data as $row) {
+ if ($row['srid'] != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Constructor. Stores user specified options.
+ *
+ * @param string $sql_query SQL to fetch raw data for visualization
+ * @param array $options Users specified options
+ * @param integer $row number of rows
+ * @param integer $pos start position
+ * @param array $data raw data. If set, parameters other than $options
+ * will be ignored
+ *
* @access public
*/
- public function __construct($data, $options)
+ private function __construct($sql_query, $options, $row, $pos, $data = null)
{
$this->_userSpecifiedSettings = $options;
- $this->_data = $data;
+ if (isset($data)) {
+ $this->_data = $data;
+ } else {
+ $this->_modified_sql = $this->_modifySqlQuery($sql_query, $row, $pos);
+ $this->_data = $this->_fetchRawData();
+ }
+
}
/**
@@ -97,6 +157,72 @@ class PMA_GIS_Visualization
}
/**
+ * Returns sql for fetching raw data
+ *
+ * @param string $sql_query The SQL to modify.
+ * @param integer $rows Number of rows.
+ * @param integer $pos Start position.
+ *
+ * @return string the modified sql query.
+ */
+ private function _modifySqlQuery($sql_query, $rows, $pos)
+ {
+ $modified_query = 'SELECT ';
+ // If label column is chosen add it to the query
+ if (! empty($this->_userSpecifiedSettings['labelColumn'])) {
+ $modified_query .= PMA_Util::backquote(
+ $this->_userSpecifiedSettings['labelColumn']
+ )
+ . ', ';
+ }
+ // Wrap the spatial column with 'ASTEXT()' function and add it
+ $modified_query .= 'ASTEXT('
+ . PMA_Util::backquote($this->_userSpecifiedSettings['spatialColumn'])
+ . ') AS ' . PMA_Util::backquote(
+ $this->_userSpecifiedSettings['spatialColumn']
+ )
+ . ', ';
+
+ // Get the SRID
+ $modified_query .= 'SRID('
+ . PMA_Util::backquote($this->_userSpecifiedSettings['spatialColumn'])
+ . ') AS ' . PMA_Util::backquote('srid') . ' ';
+
+ // Append the original query as the inner query
+ $modified_query .= 'FROM (' . $sql_query . ') AS '
+ . PMA_Util::backquote('temp_gis');
+
+ // LIMIT clause
+ if (is_numeric($rows) && $rows > 0) {
+ $modified_query .= ' LIMIT ';
+ if (is_numeric($pos) && $pos >= 0) {
+ $modified_query .= $pos . ', ' . $rows;
+ } else {
+ $modified_query .= $rows;
+ }
+ }
+
+ return $modified_query;
+ }
+
+ /**
+ * Returns raw data for GIS visualization.
+ *
+ * @return string the raw data.
+ */
+ private function _fetchRawData()
+ {
+ $modified_result = $GLOBALS['dbi']->tryQuery($this->_modified_sql);
+
+ $data = array();
+ while ($row = $GLOBALS['dbi']->fetchAssoc($modified_result)) {
+ $data[] = $row;
+ }
+
+ return $data;
+ }
+
+ /**
* A function which handles passed parameters. Useful if desired
* chart needs to be a little bit different from the default one.
*
@@ -356,6 +482,43 @@ class PMA_GIS_Visualization
}
/**
+ * Convert file to image
+ *
+ * @param string $format Output format
+ *
+ * @return string File
+ */
+ public function toImage($format)
+ {
+ if ($format == 'svg') {
+ return $this->asSvg();
+ } elseif ($format == 'png') {
+ return $this->asPng();
+ } elseif ($format == 'ol') {
+ return $this->asOl();
+ }
+ }
+
+ /**
+ * Convert file to given format
+ *
+ * @param string $filename Filename
+ * @param string $format Output format
+ *
+ * @return void
+ */
+ public function toFile($filename, $format)
+ {
+ if ($format == 'svg') {
+ $this->toFileAsSvg($filename);
+ } elseif ($format == 'png') {
+ $this->toFileAsPng($filename);
+ } elseif ($format == 'pdf') {
+ $this->toFileAsPdf($filename);
+ }
+ }
+
+ /**
* Calculates the scale, horizontal and vertical offset that should be used.
*
* @param array $data Row data
@@ -500,5 +663,16 @@ class PMA_GIS_Visualization
}
return $results;
}
+
+ /**
+ * Set user specified settings
+ *
+ * @param array $userSpecifiedSettings User specified settings
+ *
+ * @return void
+ */
+ public function setUserSpecifiedSettings($userSpecifiedSettings)
+ {
+ $this->_userSpecifiedSettings = $userSpecifiedSettings;
+ }
}
-?>
diff --git a/libraries/iconv_wrapper.lib.php b/libraries/iconv_wrapper.lib.php
index 9d1bf7f8cd..f1d74dbbac 100644
--- a/libraries/iconv_wrapper.lib.php
+++ b/libraries/iconv_wrapper.lib.php
@@ -125,4 +125,3 @@ function PMA_convertAIXMapCharsets($in_charset, $out_charset)
return array($in_charset, $out_charset);
}
-?>
diff --git a/libraries/import.lib.php b/libraries/import.lib.php
index 9bfcdf04fa..4594c947f2 100644
--- a/libraries/import.lib.php
+++ b/libraries/import.lib.php
@@ -104,9 +104,7 @@ function PMA_importRunQuery($sql = '', $full = '', $controluser = false,
// USE query changes the database, son need to track
// while running multiple queries
$is_use_query
- = (/*overload*/mb_stripos($import_run_buffer['sql'], "use ") !== false)
- ? true
- : false;
+ = /*overload*/mb_stripos($import_run_buffer['sql'], "use ") !== false;
$max_sql_len = max(
$max_sql_len,
@@ -1006,10 +1004,11 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = null,
if ($create_db) {
if (PMA_DRIZZLE) {
$sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_Util::backquote($db_name)
- . " COLLATE " . $collation;
+ . " COLLATE " . $collation . ";";
} else {
$sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_Util::backquote($db_name)
- . " DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation;
+ . " DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation
+ . ";";
}
}
@@ -1252,10 +1251,17 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = null,
$db_ops_url = 'db_operations.php' . PMA_URL_getCommon($params);
$message = '<br /><br />';
- $message .= '<strong>' . __('The following structures have either been created or altered. Here you can:') . '</strong><br />';
- $message .= '<ul><li>' . __("View a structure's contents by clicking on its name.") . '</li>';
- $message .= '<li>' . __('Change any of its settings by clicking the corresponding "Options" link.') . '</li>';
- $message .= '<li>' . __('Edit structure by following the "Structure" link.') . '</li>';
+ $message .= '<strong>' . __(
+ 'The following structures have either been created or altered. Here you can:'
+ ) . '</strong><br />';
+ $message .= '<ul><li>' . __(
+ "View a structure's contents by clicking on its name."
+ ) . '</li>';
+ $message .= '<li>' . __(
+ 'Change any of its settings by clicking the corresponding "Options" link.'
+ ) . '</li>';
+ $message .= '<li>' . __('Edit structure by following the "Structure" link.')
+ . '</li>';
$message .= sprintf(
'<br /><li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">'
. __('Options') . '</a>)</li>',
@@ -1288,9 +1294,12 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = null,
unset($params);
- if (! PMA_Table::isView($db_name, $tables[$i][TBL_NAME])) {
+ $_table = new PMA_Table($tables[$i][TBL_NAME], $db_name);
+ if (! $_table->isView()) {
$message .= sprintf(
- '<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . __('Structure') . '</a>) (<a href="%s" title="%s">' . __('Options') . '</a>)</li>',
+ '<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . __(
+ 'Structure'
+ ) . '</a>) (<a href="%s" title="%s">' . __('Options') . '</a>)</li>',
$tbl_url,
sprintf(
__('Go to table: %s'),
@@ -1388,33 +1397,33 @@ function PMA_handleSimulateDMLRequest()
continue;
}
- // Parse and Analyze the query.
- $parsed_sql = PMA_SQP_parse($sql_query);
- $analyzed_sql = PMA_SQP_analyze($parsed_sql);
+ // Parsing the query.
+ $parser = new SqlParser\Parser($sql_query);
+
+ if (empty($parser->statements[0])) {
+ continue;
+ }
+
+ $statement = $parser->statements[0];
+
$analyzed_sql_results = array(
- 'parsed_sql' => $parsed_sql,
- 'analyzed_sql' => $analyzed_sql
+ 'query' => $sql_query,
+ 'parser' => $parser,
+ 'statement' => $statement,
);
- // Only UPDATE/DELETE queries accepted.
- $query_type = $analyzed_sql_results['analyzed_sql'][0]['querytype'];
- if ($query_type != 'UPDATE' && $query_type != 'DELETE') {
+ if ((!(($statement instanceof SqlParser\Statements\UpdateStatement)
+ || ($statement instanceof SqlParser\Statements\DeleteStatement)))
+ || (!empty($statement->join))
+ ) {
$error = $error_msg;
break;
}
- // Only single-table queries accepted.
- $table_references = PMA_getTableReferences($analyzed_sql_results);
- $table_references = $table_references ? $table_references : '';
- if (preg_match('/JOIN/i', $table_references)) {
+ $tables = SqlParser\Utils\Query::getTables($statement);
+ if (count($tables) > 1) {
$error = $error_msg;
break;
- } else {
- $tables = explode(',', $table_references);
- if (count($tables) > 1) {
- $error = $error_msg;
- break;
- }
}
// Get the matched rows for the query.
@@ -1444,20 +1453,18 @@ function PMA_handleSimulateDMLRequest()
*/
function PMA_getMatchedRows($analyzed_sql_results = array())
{
- // Get the query type.
- $query_type = (isset($analyzed_sql_results['analyzed_sql'][0]['querytype']))
- ? $analyzed_sql_results['analyzed_sql'][0]['querytype']
- : '';
+ $statement = $analyzed_sql_results['statement'];
$matched_row_query = '';
- if ($query_type == 'DELETE') {
+ if ($statement instanceof SqlParser\Statements\DeleteStatement) {
$matched_row_query = PMA_getSimulatedDeleteQuery($analyzed_sql_results);
- } else if ($query_type == 'UPDATE') {
+ } elseif ($statement instanceof SqlParser\Statements\UpdateStatement) {
$matched_row_query = PMA_getSimulatedUpdateQuery($analyzed_sql_results);
}
// Execute the query and get the number of matched rows.
$matched_rows = PMA_executeMatchedRowQuery($matched_row_query);
+
// URL to matched rows.
$_url_params = array(
'db' => $GLOBALS['db'],
@@ -1466,9 +1473,7 @@ function PMA_getMatchedRows($analyzed_sql_results = array())
$matched_rows_url = 'sql.php' . PMA_URL_getCommon($_url_params);
return array(
- 'sql_query' => PMA_Util::formatSql(
- $analyzed_sql_results['parsed_sql']['raw']
- ),
+ 'sql_query' => PMA_Util::formatSql($analyzed_sql_results['query']),
'matched_rows' => $matched_rows,
'matched_rows_url' => $matched_rows_url
);
@@ -1483,94 +1488,51 @@ function PMA_getMatchedRows($analyzed_sql_results = array())
*/
function PMA_getSimulatedUpdateQuery($analyzed_sql_results)
{
- $where_clause = '';
- $extra_where_clause = array();
- $target_cols = array();
-
- $prev_term = '';
- $i = 0;
- $in_function = 0;
- foreach ($analyzed_sql_results['parsed_sql'] as $key => $term) {
- if (! isset($get_set_expr)
- && preg_match(
- '/\bSET\b/i',
- isset($term['data']) ? $term['data'] : ''
- )
- ) {
- $get_set_expr = true;
- continue;
- }
-
- if (isset($get_set_expr)) {
- if (preg_match(
- '/\bWHERE\b|\bORDER BY\b|\bLIMIT\b/i',
- isset($term['data']) ? $term['data'] : ''
- )
- ) {
- break;
- }
- if(!$in_function){
- if ($term['type'] == 'punct_listsep') {
- $extra_where_clause[] = ' OR ';
- } else if ($term['type'] == 'punct') {
- $extra_where_clause[] = ' <> ';
- } else if($term['type'] == 'alpha_functionName') {
- array_pop($extra_where_clause);
- array_pop($extra_where_clause);
- } else {
- $extra_where_clause[] = $term['data'];
- }
- }
- else if($term['type'] == 'punct_bracket_close_round') {
- $in_function--;
- }
+ $table_references = SqlParser\Utils\Query::getTables(
+ $analyzed_sql_results['statement']
+ );
- if($term['type'] == 'alpha_functionName') {
- $in_function++;
- }
+ $where = SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'WHERE'
+ );
- // Get columns in SET expression.
- if ($prev_term != 'punct') {
- if ($term['type'] != 'punct_listsep'
- && $term['type'] != 'punct'
- && $term['type'] != 'punct_bracket_open_round'
- && $term['type'] != 'punct_bracket_close_round'
- && !$in_function
- && isset($term['data'])
- ) {
- if (isset($target_cols[$i])) {
- $target_cols[$i] .= $term['data'];
- } else {
- $target_cols[$i] = $term['data'];
- }
- }
- } else {
- $i++;
- }
+ if (empty($where)) {
+ $where = '1';
+ }
- $prev_term = $term['type'];
- continue;
- }
+ $columns = array();
+ $diff = array();
+ foreach ($analyzed_sql_results['statement']->set as $set) {
+ $columns[] = $set->column;
+ $diff[] = $set->column . ' <> ' . $set->value;
+ }
+ if (!empty($diff)) {
+ $where .= ' AND (' . implode(' OR ', $diff) . ')';
}
- // Get table_references.
- $table_references = PMA_getTableReferences($analyzed_sql_results);
- $target_cols = implode(', ', $target_cols);
+ $order_and_limit = '';
- // Get WHERE clause.
- $where_clause .= $analyzed_sql_results['analyzed_sql'][0]['where_clause'];
- if (empty($where_clause)) {
- $where_clause = (!empty($extra_where_clause) && $extra_where_clause[0]) ? implode(' ',$extra_where_clause) : '1';
+ if (!empty($analyzed_sql_results['statement']->order)) {
+ $order_and_limit .= ' ORDER BY ' . SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'ORDER BY'
+ );
}
- $matched_row_query = 'SELECT '
- . $target_cols
- . ' FROM '
- . $table_references
- . ' WHERE '
- . $where_clause;
+ if (!empty($analyzed_sql_results['statement']->limit)) {
+ $order_and_limit .= ' LIMIT ' . SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'LIMIT'
+ );
+ }
- return $matched_row_query;
+ return 'SELECT ' . implode(', ', $columns) .
+ ' FROM ' . implode(', ', $table_references) .
+ ' WHERE ' . $where . $order_and_limit;
}
/**
@@ -1582,115 +1544,40 @@ function PMA_getSimulatedUpdateQuery($analyzed_sql_results)
*/
function PMA_getSimulatedDeleteQuery($analyzed_sql_results)
{
- $where_clause = '';
-
- $where_clause .= $analyzed_sql_results['analyzed_sql'][0]['where_clause'];
- if (empty($where_clause) && empty($extra_where_clause)) {
- $where_clause = '1';
- }
-
- // Get the table_references.
- $table_references = PMA_getTableReferences($analyzed_sql_results);
-
- $matched_row_query = 'SELECT * '
- . ' FROM '
- . $table_references
- . ' WHERE '
- . $where_clause;
-
- return $matched_row_query;
-}
-
-/**
- * Finds table_references from a given query.
- * Queries Supported: INSERT, UPDATE, DELETE, REPLACE, ALTER, DROP, TRUNCATE
- * and RENAME.
- *
- * @param array $analyzed_sql_results Analyzed SQL results from parser
- *
- * @return string table_references
- */
-function PMA_getTableReferences($analyzed_sql_results)
-{
- $table_references = '';
- foreach ($analyzed_sql_results['parsed_sql'] as $key => $term) {
- // Skip first KeyWord and other invalid keys.
- if ($key == 0 || ! isset($term['data'])) {
- continue;
- }
+ $table_references = SqlParser\Utils\Query::getTables(
+ $analyzed_sql_results['statement']
+ );
- // Get the query type.
- $query_type = (isset($analyzed_sql_results['analyzed_sql'][0]['querytype']))
- ? $analyzed_sql_results['analyzed_sql'][0]['querytype']
- : '';
-
- // Terms to 'ignore' from query for table_references.
- $ignore_re = '/';
- // Terminating condition for table_references.
- $terminate_re = '/';
-
- // Create relevant Regular Expressions.
- switch ($query_type) {
- case 'REPLACE':
- case 'INSERT':
- $ignore_re .= '\bINSERT\b|\bREPLACE\b|\bLOW_PRIORITY\b|\bDELAYED\b'
- . '|\bHIGH_PRIORITY\b|\bIGNORE\b|\bINTO\b';
- $terminate_re .= '\bPARTITION\b|\(|\bVALUE\b|\bVALUES\b|\bSELECT\b';
- break;
- case 'UPDATE':
- $ignore_re .= '\bUPDATE\b|\bLOW_PRIORITY\b|\bIGNORE\b';
- $terminate_re .= '\bSET\b|\bUSING\b';
- break;
- case 'DELETE':
- $ignore_re .= '\bDELETE\b|\bLOW_PRIORITY\b|\bQUICK\b|\bIGNORE\b'
- . '|\bFROM\b';
- $terminate_re .= '\bPARTITION\b|\bWHERE\b|\bORDER\b|\bLIMIT\b|\bUSING\b';
- break;
- case 'ALTER':
- $ignore_re .= '\bALTER\b|\bONLINE\b|\bOFFLINE\b|\bIGNORE\b|\bTABLE\b';
- $terminate_re .= '\bADD\b|\bALTER\b|\bCHANGE\b|\bMODIFY\b|\bDROP\b'
- . '|\bDISABLE\b|\bENABLE\b|\bRENAME\b|\bORDER\b|\bCONVERT\b'
- . '|\bDEFAULT\b|\bDISCARD\b|\bIMPORT\b|\bCOALESCE\b|\bREORGANIZE\b'
- . '|\bANALYZE\b|\bCHECK\b|\bOPTIMIZE\b|\bREBUILD\b|\bREPAIR\b'
- . '|\bPARTITION\b|\bREMOVE\b|\bCHARACTER\b';
- break;
- case 'DROP':
- $ignore_re .= '\bDROP\b|\bTEMPORARY\b|\bTABLE\b|\bIF\b|\bEXISTS\b';
- $terminate_re .= '\bRESTRICT\b|\bCASCADE\b';
- break;
- case 'TRUNCATE':
- $ignore_re .= '\bTRUNCATE\b|\bTABLE\b';
- $terminate_re .= '';
- break;
- case 'RENAME':
- $ignore_re .= '\bRENAME\b|\bTABLE\b';
- $terminate_re .= '\bTO\b';
- break;
- default:
- return false;
- }
+ $where = SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'WHERE'
+ );
- // Ignore 'case' in RegEx.
- $ignore_re .= '/i';
- $terminate_re .= '/i';
+ if (empty($where)) {
+ $where = '1';
+ }
- if ($query_type != 'TRUNCATE'
- && preg_match($terminate_re, $term['data'])
- ) {
- break;
- }
+ $order_and_limit = '';
- if (preg_match($ignore_re, $term['data'])
- || ! is_numeric($key)
- || $key == 0
- ) {
- continue;
- }
+ if (!empty($analyzed_sql_results['statement']->order)) {
+ $order_and_limit .= ' ORDER BY ' . SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'ORDER BY'
+ );
+ }
- $table_references .= ' ' . $term['data'];
+ if (!empty($analyzed_sql_results['statement']->limit)) {
+ $order_and_limit .= ' LIMIT ' . SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'LIMIT'
+ );
}
- return $table_references;
+ return 'SELECT * FROM ' . implode(', ', $table_references) .
+ ' WHERE ' . $where . $order_and_limit;
}
/**
@@ -1712,93 +1599,6 @@ function PMA_executeMatchedRowQuery($matched_row_query)
}
/**
- * Extracts unique table names from table_references.
- *
- * @param string $table_references table_references
- *
- * @return array $table_names
- */
-function PMA_getTableNamesFromTableReferences($table_references)
-{
- $table_names = array();
- $parsed_data = PMA_SQP_parse($table_references);
-
- $prev_term = array(
- 'data' => '',
- 'type' => ''
- );
- $on_encountered = false;
- $qualifier_encountered = false;
- $i = 0;
- foreach ($parsed_data as $key => $term) {
- // To skip first 'raw' key and other invalid keys.
- if (! is_numeric($key)
- || ! isset($term['data'])
- || ! isset($term['type'])
- ) {
- continue;
- }
-
- $add_to_table_names = true;
-
- // Un-quote the data, if any.
- if ($term['type'] == 'quote_backtick') {
- $term['data'] = PMA_Util::unQuote($term['data']);
- $term['type'] = 'alpha_identifier';
- }
-
- // New table name expected after 'JOIN' keyword.
- if (preg_match('/\bJOIN\b/i', $term['data'])) {
- $on_encountered = false;
- }
-
- // If term is a qualifier, set flag.
- if ($term['type'] == 'punct_qualifier') {
- $qualifier_encountered = true;
- }
-
- // Skip the JOIN conditions after 'ON' keyword.
- if (preg_match('/\bON\b/i', $term['data'])) {
- $on_encountered = true;
- }
-
- // If the word is not an 'identifier', skip it.
- if ($term['type'] != 'alpha_identifier') {
- $add_to_table_names = false;
- }
-
- // Skip table 'alias'.
- if (preg_match('/\bAS\b/i', $prev_term['data'])
- || $prev_term['type'] == 'alpha_identifier'
- ) {
- $add_to_table_names = false;
- }
-
- // Everything fine up to now, add name to list if 'unique'.
- if ($add_to_table_names
- && ! $on_encountered
- && ! in_array($term['data'], $table_names)
- ) {
- if (! $qualifier_encountered) {
- $table_names[] = PMA_Util::backquote($term['data']);
- $i++;
- } else {
- // If qualifier encountered, concatenate DB name and table name.
- $table_names[$i-1] = $table_names[$i-1]
- . '.'
- . PMA_Util::backquote($term['data']);
- $qualifier_encountered = false;
- }
- }
-
- // Update previous term.
- $prev_term = $term;
- }
-
- return $table_names;
-}
-
-/**
* Handles request for ROLLBACK.
*
* @param string $sql_query SQL query(s)
@@ -1852,37 +1652,25 @@ function PMA_handleRollbackRequest($sql_query)
*/
function PMA_checkIfRollbackPossible($sql_query)
{
- // Supported queries.
- $supported_queries = array(
- 'INSERT',
- 'UPDATE',
- 'DELETE',
- 'REPLACE'
- );
+ $parser = new SqlParser\Parser($sql_query);
- // Parse and Analyze the query.
- $parsed_sql = PMA_SQP_parse($sql_query);
- $analyzed_sql = PMA_SQP_analyze($parsed_sql);
- $analyzed_sql_results = array(
- 'parsed_sql' => $parsed_sql,
- 'analyzed_sql' => $analyzed_sql
- );
+ if (empty($parser->statements[0])) {
+ return false;
+ }
- // Get the query type.
- $query_type = (isset($analyzed_sql_results['analyzed_sql'][0]['querytype']))
- ? $analyzed_sql_results['analyzed_sql'][0]['querytype']
- : '';
+ $statement = $parser->statements[0];
// Check if query is supported.
- if (! in_array($query_type, $supported_queries)) {
+ if (!(($statement instanceof SqlParser\Statements\InsertStatement)
+ || ($statement instanceof SqlParser\Statements\UpdateStatement)
+ || ($statement instanceof SqlParser\Statements\DeleteStatement)
+ || ($statement instanceof SqlParser\Statements\ReplaceStatement))
+ ) {
return false;
}
// Get table_references from the query.
- $table_references = PMA_getTableReferences($analyzed_sql_results);
- $table_references = $table_references ? $table_references : '';
- // Get table names from table_references.
- $tables = PMA_getTableNamesFromTableReferences($table_references);
+ $tables = SqlParser\Utils\Query::getTables($statement);
// Check if each table is 'InnoDB'.
foreach ($tables as $table) {
@@ -1951,4 +1739,3 @@ function PMA_isTableTransactional($table)
return false;
}
}
-?>
diff --git a/libraries/index.lib.php b/libraries/index.lib.php
index e60aab4e44..59b1303dcc 100644
--- a/libraries/index.lib.php
+++ b/libraries/index.lib.php
@@ -19,14 +19,18 @@ require_once 'libraries/Index.class.php';
*/
function PMA_getHtmlForDisplayIndexes()
{
- $html_output = '<div id="index_div" class="ajax" >';
+ $html_output = '<div id="index_div" class="ajax';
+ if ($GLOBALS['cfg']['InitialSlidersState'] != 'disabled') {
+ $html_output .= ' print_ignore';
+ }
+ $html_output .= '" >';
$html_output .= PMA_Util::getDivForSliderEffect(
'indexes', __('Indexes')
);
- $html_output .= PMA_Index::getView($GLOBALS['table'], $GLOBALS['db']);
- $html_output .= '<fieldset class="tblFooters" style="text-align: left;">'
- . '<form action="tbl_indexes.php" method="post">';
+ $html_output .= PMA_Index::getHtmlForIndexes($GLOBALS['table'], $GLOBALS['db']);
+ $html_output .= '<fieldset class="tblFooters print_ignore" style="text-align: '
+ . 'left;"><form action="tbl_indexes.php" method="post">';
$html_output .= PMA_URL_getHiddenInputs(
$GLOBALS['db'], $GLOBALS['table']
);
diff --git a/libraries/information_schema_relations.lib.php b/libraries/information_schema_relations.lib.php
index 64be9d7d8d..3c1b618d3b 100644
--- a/libraries/information_schema_relations.lib.php
+++ b/libraries/information_schema_relations.lib.php
@@ -324,4 +324,3 @@ $GLOBALS['information_schema_relations'] = array(
)
);
-?>
diff --git a/libraries/insert_edit.lib.php b/libraries/insert_edit.lib.php
index 1aeb328ca9..c277091156 100644
--- a/libraries/insert_edit.lib.php
+++ b/libraries/insert_edit.lib.php
@@ -19,7 +19,7 @@ if (! defined('PHPMYADMIN')) {
* @param array $where_clause_array array of where clauses
* @param string $err_url error url
*
- * @return array $_form_params array of insert/edit form parameters
+ * @return array $form_params array of insert/edit form parameters
*/
function PMA_getFormParametersForInsertForm($db, $table, $where_clauses,
$where_clause_array, $err_url
@@ -134,7 +134,13 @@ function PMA_showEmptyResultMessageOrSetUniqueCondition($rows, $key_id,
list($unique_condition, $tmp_clause_is_unique)
= PMA_Util::getUniqueCondition(
- $result[$key_id], count($meta), $meta, $rows[$key_id], true
+ $result[$key_id], // handle
+ count($meta), // fields_cnt
+ $meta, // fields_meta
+ $rows[$key_id], // row
+ true, // force_unique
+ false, // restrict_to_table
+ null // analyzed_sql_results
);
if (! empty($unique_condition)) {
@@ -368,7 +374,7 @@ function PMA_getEnumSetAndTimestampColumns($column, $timestamp_seen)
* @param array $column description of column in given table
* @param boolean $is_upload upload or no
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param array $no_support_types list of datatypes that are not (yet)
* handled by PMA
* @param integer $tabindex_for_function +3000
@@ -379,7 +385,7 @@ function PMA_getEnumSetAndTimestampColumns($column, $timestamp_seen)
* @return string an html snippet
*/
function PMA_getFunctionColumn($column, $is_upload, $column_name_appendix,
- $unnullify_trigger, $no_support_types, $tabindex_for_function,
+ $onChangeClause, $no_support_types, $tabindex_for_function,
$tabindex, $idindex, $insert_mode
) {
$html_output = '';
@@ -400,7 +406,7 @@ function PMA_getFunctionColumn($column, $is_upload, $column_name_appendix,
$html_output .= '<td>' . "\n";
$html_output .= '<select name="funcs' . $column_name_appendix . '"'
- . ' ' . $unnullify_trigger
+ . ' ' . $onChangeClause
. ' tabindex="' . ($tabindex + $tabindex_for_function) . '"'
. ' id="field_' . $idindex . '_1">';
$html_output .= PMA_Util::getFunctionsForField($column, $insert_mode) . "\n";
@@ -485,14 +491,14 @@ function PMA_getNullifyCodeForNullColumn($column, $foreigners, $foreignData)
}
} elseif (/*overload*/mb_strstr($column['True_Type'], 'set')) {
$nullify_code = '3';
- } elseif ($foreigners
- && $foreigner
+ } elseif (!empty($foreigners)
+ && !empty($foreigner)
&& $foreignData['foreign_link'] == false
) {
// foreign key in a drop-down
$nullify_code = '4';
- } elseif ($foreigners
- && $foreigner
+ } elseif (!empty($foreigners)
+ && !empty($foreigner)
&& $foreignData['foreign_link'] == true
) {
// foreign key with a browsing icon
@@ -510,7 +516,7 @@ function PMA_getNullifyCodeForNullColumn($column, $foreigners, $foreignData)
* @param array $column description of column in given table
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -541,7 +547,7 @@ function PMA_getNullifyCodeForNullColumn($column, $foreigners, $foreignData)
* @return string an html snippet
*/
function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, $data,
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, $data,
$special_chars, $foreignData, $odd_row, $paramTableDbArray, $rownumber,
$titles, $text_dir, $special_chars_encoded, $vkey,
$is_upload, $biggest_max_file_size,
@@ -554,14 +560,14 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
if ($foreignData['foreign_link'] == true) {
$html_output .= PMA_getForeignLink(
$column, $backup_field, $column_name_appendix,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, $data,
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, $data,
$paramTableDbArray, $rownumber, $titles
);
} elseif (is_array($foreignData['disp_row'])) {
$html_output .= PMA_dispRowForeignData(
$backup_field, $column_name_appendix,
- $unnullify_trigger, $tabindex, $tabindex_for_value,
+ $onChangeClause, $tabindex, $tabindex_for_value,
$idindex, $data, $foreignData
);
@@ -573,7 +579,7 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
$html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
. '<td colspan="5" class="right">';
$html_output .= PMA_getTextarea(
- $column, $backup_field, $column_name_appendix, $unnullify_trigger,
+ $column, $backup_field, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $text_dir,
$special_chars_encoded, $data_type
);
@@ -581,7 +587,7 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
} elseif (/*overload*/mb_strstr($column['pma_type'], 'text')) {
$html_output .= PMA_getTextarea(
- $column, $backup_field, $column_name_appendix, $unnullify_trigger,
+ $column, $backup_field, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $text_dir,
$special_chars_encoded, $data_type
);
@@ -596,20 +602,20 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
} elseif ($column['pma_type'] == 'enum') {
$html_output .= PMA_getPmaTypeEnum(
$column, $backup_field, $column_name_appendix, $extracted_columnspec,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, $data
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, $data
);
} elseif ($column['pma_type'] == 'set') {
$html_output .= PMA_getPmaTypeSet(
$column, $extracted_columnspec, $backup_field,
- $column_name_appendix, $unnullify_trigger, $tabindex,
+ $column_name_appendix, $onChangeClause, $tabindex,
$tabindex_for_value, $idindex, $data
);
} elseif ($column['is_binary'] || $column['is_blob']) {
$html_output .= PMA_getBinaryAndBlobColumn(
$column, $data, $special_chars, $biggest_max_file_size,
- $backup_field, $column_name_appendix, $unnullify_trigger, $tabindex,
+ $backup_field, $column_name_appendix, $onChangeClause, $tabindex,
$tabindex_for_value, $idindex, $text_dir, $special_chars_encoded,
$vkey, $is_upload
);
@@ -617,7 +623,7 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
} elseif (! in_array($column['pma_type'], $no_support_types)) {
$html_output .= PMA_getValueColumnForOtherDatatypes(
$column, $default_char_editing, $backup_field,
- $column_name_appendix, $unnullify_trigger, $tabindex, $special_chars,
+ $column_name_appendix, $onChangeClause, $tabindex, $special_chars,
$tabindex_for_value, $idindex, $text_dir, $special_chars_encoded,
$data, $extracted_columnspec
);
@@ -636,7 +642,7 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
* @param array $column description of column in given table
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -650,7 +656,7 @@ function PMA_getValueColumn($column, $backup_field, $column_name_appendix,
* @return string an html snippet
*/
function PMA_getForeignLink($column, $backup_field, $column_name_appendix,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, $data,
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, $data,
$paramTableDbArray, $rownumber, $titles
) {
list($table, $db) = $paramTableDbArray;
@@ -662,7 +668,7 @@ function PMA_getForeignLink($column, $backup_field, $column_name_appendix,
$html_output .= '<input type="text" name="fields' . $column_name_appendix . '" '
. 'class="textfield" '
- . $unnullify_trigger . ' '
+ . $onChangeClause . ' '
. 'tabindex="' . ($tabindex + $tabindex_for_value) . '" '
. 'id="field_' . ($idindex) . '_3" '
. 'value="' . htmlspecialchars($data) . '" />';
@@ -686,7 +692,7 @@ function PMA_getForeignLink($column, $backup_field, $column_name_appendix,
*
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -696,7 +702,7 @@ function PMA_getForeignLink($column, $backup_field, $column_name_appendix,
* @return string an html snippet
*/
function PMA_dispRowForeignData($backup_field, $column_name_appendix,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, $data,
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, $data,
$foreignData
) {
$html_output = '';
@@ -706,7 +712,7 @@ function PMA_dispRowForeignData($backup_field, $column_name_appendix,
. ' value="foreign" />';
$html_output .= '<select name="fields' . $column_name_appendix . '"'
- . ' ' . $unnullify_trigger
+ . ' ' . $onChangeClause
. ' class="textfield"'
. ' tabindex="' . ($tabindex + $tabindex_for_value) . '"'
. ' id="field_' . $idindex . '_3">';
@@ -726,7 +732,7 @@ function PMA_dispRowForeignData($backup_field, $column_name_appendix,
* @param array $column column information
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -738,7 +744,7 @@ function PMA_dispRowForeignData($backup_field, $column_name_appendix,
* @return string an html snippet
*/
function PMA_getTextarea($column, $backup_field, $column_name_appendix,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex,
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex,
$text_dir, $special_chars_encoded, $data_type
) {
$the_class = '';
@@ -769,7 +775,7 @@ function PMA_getTextarea($column, $backup_field, $column_name_appendix,
. ' cols="' . $textareaCols . '"'
. ' dir="' . $text_dir . '"'
. ' id="field_' . ($idindex) . '_3"'
- . (! empty($unnullify_trigger) ? ' ' . $unnullify_trigger : '')
+ . (! empty($onChangeClause) ? ' ' . $onChangeClause : '')
. ' tabindex="' . ($tabindex + $tabindex_for_value) . '"'
. ' data-type="' . $data_type . '">'
. $special_chars_encoded
@@ -787,7 +793,7 @@ function PMA_getTextarea($column, $backup_field, $column_name_appendix,
* @param array $extracted_columnspec associative array containing type,
* spec_in_brackets and possibly
* enum_set_values (another array)
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -796,7 +802,7 @@ function PMA_getTextarea($column, $backup_field, $column_name_appendix,
* @return string an html snippet
*/
function PMA_getPmaTypeEnum($column, $backup_field, $column_name_appendix,
- $extracted_columnspec, $unnullify_trigger, $tabindex, $tabindex_for_value,
+ $extracted_columnspec, $onChangeClause, $tabindex, $tabindex_for_value,
$idindex, $data
) {
$html_output = '';
@@ -808,17 +814,15 @@ function PMA_getPmaTypeEnum($column, $backup_field, $column_name_appendix,
$column_enum_values = $column['values'];
$html_output .= '<input type="hidden" name="fields_type'
. $column_name_appendix . '" value="enum" />';
- $html_output .= '<input type="hidden" name="fields'
- . $column_name_appendix . '" value="" />';
$html_output .= "\n" . ' ' . $backup_field . "\n";
if (/*overload*/mb_strlen($column['Type']) > 20) {
$html_output .= PMA_getDropDownDependingOnLength(
- $column, $column_name_appendix, $unnullify_trigger,
+ $column, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $data, $column_enum_values
);
} else {
$html_output .= PMA_getRadioButtonDependingOnLength(
- $column_name_appendix, $unnullify_trigger,
+ $column_name_appendix, $onChangeClause,
$tabindex, $column, $tabindex_for_value,
$idindex, $data, $column_enum_values
);
@@ -853,7 +857,7 @@ function PMA_getColumnEnumValues($column, $extracted_columnspec)
*
* @param array $column description of column in given table
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -863,11 +867,11 @@ function PMA_getColumnEnumValues($column, $extracted_columnspec)
* @return string an html snippet
*/
function PMA_getDropDownDependingOnLength(
- $column, $column_name_appendix, $unnullify_trigger,
+ $column, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $data, $column_enum_values
) {
$html_output = '<select name="fields' . $column_name_appendix . '"'
- . ' ' . $unnullify_trigger
+ . ' ' . $onChangeClause
. ' class="textfield"'
. ' tabindex="' . ($tabindex + $tabindex_for_value) . '"'
. ' id="field_' . ($idindex) . '_3">';
@@ -893,7 +897,7 @@ function PMA_getDropDownDependingOnLength(
* Get HTML radio button for less than 20 string length
*
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param array $column description of column in given table
* @param integer $tabindex_for_value offset for the values tabindex
@@ -904,7 +908,7 @@ function PMA_getDropDownDependingOnLength(
* @return string an html snippet
*/
function PMA_getRadioButtonDependingOnLength(
- $column_name_appendix, $unnullify_trigger,
+ $column_name_appendix, $onChangeClause,
$tabindex, $column, $tabindex_for_value, $idindex, $data, $column_enum_values
) {
$j = 0;
@@ -915,7 +919,7 @@ function PMA_getRadioButtonDependingOnLength(
. ' class="textfield"'
. ' value="' . $enum_value['html'] . '"'
. ' id="field_' . ($idindex) . '_3_' . $j . '"'
- . ' ' . $unnullify_trigger;
+ . ' ' . $onChangeClause;
if ($data == $enum_value['plain']
|| ($data == ''
&& (! isset($_REQUEST['where_clause']) || $column['Null'] != 'YES')
@@ -941,7 +945,7 @@ function PMA_getRadioButtonDependingOnLength(
* enum_set_values (another array)
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -951,7 +955,7 @@ function PMA_getRadioButtonDependingOnLength(
*/
function PMA_getPmaTypeSet(
$column, $extracted_columnspec, $backup_field,
- $column_name_appendix, $unnullify_trigger, $tabindex,
+ $column_name_appendix, $onChangeClause, $tabindex,
$tabindex_for_value, $idindex, $data
) {
list($column_set_values, $select_size) = PMA_getColumnSetValueAndSelectSize(
@@ -965,7 +969,7 @@ function PMA_getPmaTypeSet(
. ' class="textfield"'
. ' size="' . $select_size . '"'
. ' multiple="multiple"'
- . ' ' . $unnullify_trigger
+ . ' ' . $onChangeClause
. ' tabindex="' . ($tabindex + $tabindex_for_value) . '"'
. ' id="field_' . ($idindex) . '_3">';
foreach ($column_set_values as $column_set_value) {
@@ -1013,7 +1017,7 @@ function PMA_getColumnSetValueAndSelectSize($column, $extracted_columnspec)
* @param integer $biggest_max_file_size biggest max file size for uploading
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -1027,7 +1031,7 @@ function PMA_getColumnSetValueAndSelectSize($column, $extracted_columnspec)
*/
function PMA_getBinaryAndBlobColumn(
$column, $data, $special_chars, $biggest_max_file_size,
- $backup_field, $column_name_appendix, $unnullify_trigger, $tabindex,
+ $backup_field, $column_name_appendix, $onChangeClause, $tabindex,
$tabindex_for_value, $idindex, $text_dir, $special_chars_encoded,
$vkey, $is_upload
) {
@@ -1056,7 +1060,7 @@ function PMA_getBinaryAndBlobColumn(
|| ($column['len'] > $GLOBALS['cfg']['LimitChars'])
) {
$html_output .= "\n" . PMA_getTextarea(
- $column, $backup_field, $column_name_appendix, $unnullify_trigger,
+ $column, $backup_field, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $text_dir,
$special_chars_encoded, 'HEX'
);
@@ -1065,7 +1069,7 @@ function PMA_getBinaryAndBlobColumn(
$fieldsize = min(max($column['len'], 4), $GLOBALS['cfg']['LimitChars']);
$html_output .= "\n" . $backup_field . "\n" . PMA_getHTMLinput(
$column, $column_name_appendix, $special_chars, $fieldsize,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, 'HEX'
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, 'HEX'
);
}
$html_output .= sprintf($fields_type_html, $fields_type_val);
@@ -1075,7 +1079,7 @@ function PMA_getBinaryAndBlobColumn(
. '<input type="file"'
. ' name="fields_upload' . $vkey . '[' . $column['Field_md5'] . ']"'
. ' class="textfield" id="field_' . $idindex . '_3" size="10"'
- . ' ' . $unnullify_trigger . '/>&nbsp;';
+ . ' ' . $onChangeClause . '/>&nbsp;';
list($html_out,) = PMA_getMaxUploadSize(
$column, $biggest_max_file_size
);
@@ -1096,7 +1100,7 @@ function PMA_getBinaryAndBlobColumn(
* @param string $column_name_appendix the name attribute
* @param string $special_chars special characters
* @param integer $fieldsize html field size
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param integer $tabindex_for_value offset for the values tabindex
* @param integer $idindex id index
@@ -1105,7 +1109,7 @@ function PMA_getBinaryAndBlobColumn(
* @return string an html snippet
*/
function PMA_getHTMLinput(
- $column, $column_name_appendix, $special_chars, $fieldsize, $unnullify_trigger,
+ $column, $column_name_appendix, $special_chars, $fieldsize, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $data_type
) {
$input_type = 'text';
@@ -1143,7 +1147,7 @@ function PMA_getHTMLinput(
. ($input_min_max !== false ? ' ' . $input_min_max : '')
. ' data-type="' . $data_type . '"'
. ($input_type === 'time' ? ' step="1"' : '')
- . ' class="' . $the_class . '" ' . $unnullify_trigger
+ . ' class="' . $the_class . '" ' . $onChangeClause
. ' tabindex="' . ($tabindex + $tabindex_for_value) . '"'
. ' id="field_' . ($idindex) . '_3" />';
}
@@ -1227,7 +1231,7 @@ function PMA_getMaxUploadSize($column, $biggest_max_file_size)
* in the config.inc.php script
* @param string $backup_field hidden input field
* @param string $column_name_appendix the name attribute
- * @param string $unnullify_trigger validation string
+ * @param string $onChangeClause onchange clause for fields
* @param integer $tabindex tab index
* @param string $special_chars special characters
* @param integer $tabindex_for_value offset for the values tabindex
@@ -1244,7 +1248,7 @@ function PMA_getMaxUploadSize($column, $biggest_max_file_size)
*/
function PMA_getValueColumnForOtherDatatypes($column, $default_char_editing,
$backup_field,
- $column_name_appendix, $unnullify_trigger, $tabindex, $special_chars,
+ $column_name_appendix, $onChangeClause, $tabindex, $special_chars,
$tabindex_for_value, $idindex, $text_dir, $special_chars_encoded, $data,
$extracted_columnspec
) {
@@ -1259,14 +1263,14 @@ function PMA_getValueColumnForOtherDatatypes($column, $default_char_editing,
$html_output .= "\n";
$GLOBALS['cfg']['CharEditing'] = $default_char_editing;
$html_output .= PMA_getTextarea(
- $column, $backup_field, $column_name_appendix, $unnullify_trigger,
+ $column, $backup_field, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $text_dir,
$special_chars_encoded, $data_type
);
} else {
$html_output .= PMA_getHTMLinput(
$column, $column_name_appendix, $special_chars, $fieldsize,
- $unnullify_trigger, $tabindex, $tabindex_for_value, $idindex, $data_type
+ $onChangeClause, $tabindex, $tabindex_for_value, $idindex, $data_type
);
if ($column['Extra'] == 'auto_increment') {
@@ -1497,11 +1501,12 @@ function PMA_getAfterInsertDropDown($where_clause, $after_insert, $found_unique_
$where_clause = array($where_clause);
}
for ($i = 0, $nb = count($where_clause); $i < $nb; $i++) {
- $is_numeric = preg_match(
+ // preg_match() returns 1 if there is a match
+ $is_numeric = (preg_match(
'@^[\s]*`[^`]*`[\.]`[^`]*` = [0-9]+@',
$where_clause[$i]
- );
- if ($is_numeric == true) {
+ ) == 1);
+ if ($is_numeric === true) {
break;
}
}
@@ -1802,7 +1807,13 @@ function PMA_setSessionForEditNext($one_where_clause)
// not a combination of all fields
list($unique_condition, $clause_is_unique)
= PMA_Util::getUniqueCondition(
- $res, count($meta), $meta, $row, true
+ $res, // handle
+ count($meta), // fields_cnt
+ $meta, // fields_meta
+ $row, // row
+ true, // force_unique
+ false, // restrict_to_table
+ null // analyzed_sql_results
);
if (! empty($unique_condition)) {
$_SESSION['edit_next'] = $unique_condition;
@@ -1885,7 +1896,6 @@ function PMA_buildSqlQuery($is_insertignore, $query_fields, $value_sets)
}
$query = array(
$insert_command . 'INTO '
- . PMA_Util::backquote($GLOBALS['db']) . '.'
. PMA_Util::backquote($GLOBALS['table'])
. ' (' . implode(', ', $query_fields) . ') VALUES ('
. implode('), (', $value_sets) . ')'
@@ -2105,6 +2115,7 @@ function PMA_transformEditedValues($db, $table,
$transform_options['wrapper_link']
= PMA_URL_getCommon($_url_params);
$class_name = PMA_getTransformationClassName($file);
+ /** @var TransformationsPlugin $transformation_plugin */
$transformation_plugin = new $class_name();
foreach ($edited_values as $cell_index => $curr_cell_edited_values) {
@@ -2411,7 +2422,7 @@ function PMA_verifyWhetherValueCanBeTruncatedAndAppendExtraData(
function PMA_getTableColumns($db, $table)
{
$GLOBALS['dbi']->selectDb($db);
- return array_values($GLOBALS['dbi']->getColumns($db, $table));
+ return array_values($GLOBALS['dbi']->getColumns($db, $table, null, true));
}
@@ -2599,7 +2610,7 @@ function PMA_getHtmlForFunctionOption($odd_row, $column, $column_name_appendix)
function PMA_getHtmlForInsertEditColumnType($column)
{
return '<td class="center' . $column['wrap'] . '">'
- . '<span class="column_type">' . $column['pma_type'] . '</span>'
+ . '<span class="column_type" dir="ltr">' . $column['pma_type'] . '</span>'
. '</td>';
}
@@ -2631,8 +2642,7 @@ function PMA_getHtmlForInsertEditFormHeader($has_blob_field, $is_upload)
* Function to get html for each insert/edit column
*
* @param array $table_columns table columns
- * @param int $i row counter
- * @param array $column column
+ * @param int $column_number column index in table_columns
* @param array $comments_map comments map
* @param bool $timestamp_seen whether timestamp seen
* @param array $current_result current result
@@ -2664,7 +2674,7 @@ function PMA_getHtmlForInsertEditFormHeader($has_blob_field, $is_upload)
*
* @return string
*/
-function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
+function PMA_getHtmlForInsertEditFormColumn($table_columns, $column_number,
$comments_map, $timestamp_seen, $current_result, $chg_evt_handler,
$jsvkey, $vkey, $insert_mode, $current_row, $odd_row, &$o_rows,
&$tabindex, $columns_cnt, $is_upload, $tabindex_for_function,
@@ -2672,8 +2682,8 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
$row_id, $titles, $biggest_max_file_size, $default_char_editing,
$text_dir, $repopulate, $column_mime, $where_clause
) {
- if (! isset($table_columns[$i]['processed'])) {
- $column = $table_columns[$i];
+ $column = $table_columns[$column_number];
+ if (! isset($column['processed'])) {
$column = PMA_analyzeTableColumnsArray(
$column, $comments_map, $timestamp_seen
);
@@ -2688,7 +2698,9 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
= PMA_Util::extractColumnSpec($column['Type']);
if (-1 === $column['len']) {
- $column['len'] = $GLOBALS['dbi']->fieldLen($current_result, $i);
+ $column['len'] = $GLOBALS['dbi']->fieldLen(
+ $current_result, $column_number
+ );
// length is unknown for geometry fields,
// make enough space to edit very simple WKTs
if (-1 === $column['len']) {
@@ -2696,7 +2708,7 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
}
}
//Call validation when the form submitted...
- $unnullify_trigger = $chg_evt_handler
+ $onChangeClause = $chg_evt_handler
. "=\"return verificationsAfterFieldChange('"
. PMA_escapeJsString($column['Field_md5']) . "', '"
. PMA_escapeJsString($jsvkey) . "','" . $column['pma_type'] . "')\"";
@@ -2753,7 +2765,7 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
unset($tmp);
}
- $idindex = ($o_rows * $columns_cnt) + $i + 1;
+ $idindex = ($o_rows * $columns_cnt) + $column_number + 1;
$tabindex = $idindex;
// Get a list of data types that are not yet supported.
@@ -2764,7 +2776,7 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
if ($GLOBALS['cfg']['ShowFunctionFields']) {
$html_output .= PMA_getFunctionColumn(
$column, $is_upload, $column_name_appendix,
- $unnullify_trigger, $no_support_types, $tabindex_for_function,
+ $onChangeClause, $no_support_types, $tabindex_for_function,
$tabindex, $idindex, $insert_mode
);
}
@@ -2786,11 +2798,11 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
// HTML attribute
//add data attributes "no of decimals" and "data type"
- $no_decimals=0;
+ $no_decimals = 0;
$type = current(explode("(", $column['pma_type']));
if (preg_match('/\(([^()]+)\)/', $column['pma_type'], $match)) {
$match[0] = trim($match[0], '()');
- $no_decimals=$match[0];
+ $no_decimals = $match[0];
}
$html_output .= '<td' . ' data-type="' . $type . '"' . ' data-decimals="'
. $no_decimals . '">' . "\n";
@@ -2826,7 +2838,8 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
if (method_exists($transformation_plugin, 'getInputHtml')) {
$transformed_html = $transformation_plugin->getInputHtml(
$column, $row_id, $column_name_appendix,
- $transformation_options, $current_value, $text_dir
+ $transformation_options, $current_value, $text_dir,
+ $tabindex, $tabindex_for_value, $idindex
);
}
if (method_exists($transformation_plugin, 'getScripts')) {
@@ -2840,7 +2853,7 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
$html_output .= $transformed_html;
} else {
$html_output .= PMA_getValueColumn(
- $column, $backup_field, $column_name_appendix, $unnullify_trigger,
+ $column, $backup_field, $column_name_appendix, $onChangeClause,
$tabindex, $tabindex_for_value, $idindex, $data, $special_chars,
$foreignData, $odd_row, array($table, $db), $row_id, $titles,
$text_dir, $special_chars_encoded, $vkey, $is_upload,
@@ -2859,7 +2872,6 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
*
* @param array $url_params url parameters
* @param array $table_columns table columns
- * @param array $column column
* @param array $comments_map comments map
* @param bool $timestamp_seen whether timestamp seen
* @param array $current_result current result
@@ -2888,7 +2900,7 @@ function PMA_getHtmlForInsertEditFormColumn($table_columns, $i, $column,
* @return string
*/
function PMA_getHtmlForInsertEditRow($url_params, $table_columns,
- $column, $comments_map, $timestamp_seen, $current_result, $chg_evt_handler,
+ $comments_map, $timestamp_seen, $current_result, $chg_evt_handler,
$jsvkey, $vkey, $insert_mode, $current_row, &$o_rows, &$tabindex, $columns_cnt,
$is_upload, $tabindex_for_function, $foreigners, $tabindex_for_null,
$tabindex_for_value, $table, $db, $row_id, $titles,
@@ -2905,13 +2917,18 @@ function PMA_getHtmlForInsertEditRow($url_params, $table_columns,
if (isset($where_clause_array[$row_id])) {
$where_clause = $where_clause_array[$row_id];
}
- for ($i = 0; $i < $columns_cnt; $i++) {
+ for ($column_number = 0; $column_number < $columns_cnt; $column_number++) {
+ $table_column = $table_columns[$column_number];
+ // skip this column if user does not have necessary column privilges
+ if (! PMA_userHasColumnPrivileges($table_column, $insert_mode)) {
+ continue;
+ }
$column_mime = array();
- if (isset($mime_map[$table_columns[$i]['Field']])) {
- $column_mime = $mime_map[$table_columns[$i]['Field']];
+ if (isset($mime_map[$table_column['Field']])) {
+ $column_mime = $mime_map[$table_column['Field']];
}
$html_output .= PMA_getHtmlForInsertEditFormColumn(
- $table_columns, $i, $column, $comments_map, $timestamp_seen,
+ $table_columns, $column_number, $comments_map, $timestamp_seen,
$current_result, $chg_evt_handler, $jsvkey, $vkey, $insert_mode,
$current_row, $odd_row, $o_rows, $tabindex, $columns_cnt, $is_upload,
$tabindex_for_function, $foreigners, $tabindex_for_null,
@@ -2928,4 +2945,19 @@ function PMA_getHtmlForInsertEditRow($url_params, $table_columns,
return $html_output;
}
-?>
+
+/**
+ * Returns whether the user has necessary insert/update privileges for the column
+ *
+ * @param array $table_column array of column details
+ * @param bool $insert_mode whether on insert mode
+ *
+ * @return boolean whether user has necessary privileges
+ */
+function PMA_userHasColumnPrivileges($table_column, $insert_mode)
+{
+ $privileges = $table_column['Privileges'];
+ return ($insert_mode && strstr($privileges, 'insert') !== false)
+ || (! $insert_mode && strstr($privileges, 'update') !== false)
+ || is_null($privileges); // Drizzle
+}
diff --git a/libraries/ip_allow_deny.lib.php b/libraries/ip_allow_deny.lib.php
index 0c84b833bc..ecd55a7514 100644
--- a/libraries/ip_allow_deny.lib.php
+++ b/libraries/ip_allow_deny.lib.php
@@ -338,4 +338,3 @@ function PMA_allowDeny($type)
return false;
} // end of the "PMA_AllowDeny()" function
-?>
diff --git a/libraries/js_escape.lib.php b/libraries/js_escape.lib.php
index b92eae0693..bd45133665 100644
--- a/libraries/js_escape.lib.php
+++ b/libraries/js_escape.lib.php
@@ -132,4 +132,45 @@ function PMA_printJsValue($key, $value)
echo PMA_getJsValue($key, $value);
}
-?>
+/**
+ * Formats javascript assignment for form validation api
+ * with proper escaping of a value.
+ *
+ * @param string $key Name of value to set
+ * @param string $value Value to set
+ * @param boolean $addOn Check if $.validator.format is required or not
+ * @param boolean $comma Check if comma is required
+ *
+ * @return string Javascript code.
+ */
+function PMA_getJsValueForFormValidation($key, $value, $addOn, $comma)
+{
+ $result = $key . ': ';
+ if ($addOn) {
+ $result .= '$.validator.format(';
+ }
+ $result .= PMA_formatJsVal($value);
+ if ($addOn) {
+ $result .= ')';
+ }
+ if ($comma) {
+ $result .= ', ';
+ }
+ return $result;
+}
+
+/**
+ * Prints javascript assignment for form validation api
+ * with proper escaping of a value.
+ *
+ * @param string $key Name of value to set
+ * @param string $value Value to set
+ * @param boolean $addOn Check if $.validator.format is required or not
+ * @param boolean $comma Check if comma is required
+ *
+ * @return void
+ */
+function PMA_printJsValueForFormValidation($key, $value, $addOn=false, $comma=true)
+{
+ echo PMA_getJsValueForFormValidation($key, $value, $addOn, $comma);
+}
diff --git a/libraries/kanji-encoding.lib.php b/libraries/kanji-encoding.lib.php
index 0495112b79..79222aa73d 100644
--- a/libraries/kanji-encoding.lib.php
+++ b/libraries/kanji-encoding.lib.php
@@ -165,4 +165,3 @@ function PMA_Kanji_encodingForm()
PMA_Kanji_checkEncoding();
-?>
diff --git a/libraries/language_stats.inc.php b/libraries/language_stats.inc.php
index 986b030ff0..7559b50af0 100644
--- a/libraries/language_stats.inc.php
+++ b/libraries/language_stats.inc.php
@@ -3,85 +3,85 @@
/* Generated by scripts/remove-incomplete-mo */
$GLOBALS["language_stats"] = array (
- 'af' => 9,
- 'ar' => 38,
- 'az' => 58,
- 'be' => 27,
- 'be@latin' => 26,
- 'bg' => 63,
- 'bn' => 82,
- 'br' => 19,
- 'bs' => 14,
- 'ca' => 100,
- 'ckb' => 20,
- 'cs' => 98,
- 'cy' => 19,
- 'da' => 100,
- 'de' => 100,
+ 'af' => 8,
+ 'ar' => 34,
+ 'az' => 53,
+ 'be' => 24,
+ 'be@latin' => 24,
+ 'bg' => 58,
+ 'bn' => 75,
+ 'br' => 17,
+ 'bs' => 12,
+ 'ca' => 96,
+ 'ckb' => 18,
+ 'cs' => 95,
+ 'cy' => 18,
+ 'da' => 93,
+ 'de' => 99,
'el' => 100,
- 'en_GB' => 88,
+ 'en_GB' => 80,
'eo' => 2,
- 'es' => 100,
+ 'es' => 98,
'et' => 100,
- 'eu' => 17,
- 'fa' => 27,
- 'fi' => 63,
+ 'eu' => 15,
+ 'fa' => 25,
+ 'fi' => 57,
'fr' => 100,
- 'fy' => 21,
- 'gl' => 86,
- 'he' => 18,
- 'hi' => 41,
- 'hr' => 32,
- 'hu' => 99,
- 'hy' => 66,
- 'ia' => 69,
- 'id' => 76,
+ 'fy' => 19,
+ 'gl' => 80,
+ 'he' => 17,
+ 'hi' => 37,
+ 'hr' => 29,
+ 'hu' => 97,
+ 'hy' => 61,
+ 'ia' => 70,
+ 'id' => 69,
'it' => 100,
- 'ja' => 73,
- 'ka' => 15,
- 'kk' => 10,
+ 'ja' => 66,
+ 'ka' => 13,
+ 'kk' => 9,
'km' => 5,
'kn' => 4,
- 'ko' => 82,
- 'ksh' => 1,
+ 'ko' => 77,
+ 'ksh' => 0,
'ky' => 1,
'li' => 1,
- 'lt' => 48,
- 'lv' => 21,
- 'mk' => 17,
+ 'lt' => 43,
+ 'lv' => 18,
+ 'mk' => 16,
'ml' => 1,
- 'mn' => 22,
- 'ms' => 11,
- 'nb' => 63,
+ 'mn' => 20,
+ 'ms' => 10,
+ 'nb' => 58,
'ne' => 1,
'nl' => 100,
'pa' => 2,
- 'pl' => 86,
- 'pt' => 59,
- 'pt_BR' => 99,
- 'ro' => 59,
- 'ru' => 99,
- 'si' => 65,
- 'sk' => 85,
+ 'pl' => 78,
+ 'pt' => 53,
+ 'pt_BR' => 92,
+ 'ro' => 53,
+ 'ru' => 97,
+ 'si' => 60,
+ 'sk' => 80,
'sl' => 100,
- 'sq' => 100,
- 'sr' => 25,
- 'sr@latin' => 49,
- 'sv' => 88,
- 'ta' => 38,
- 'te' => 10,
- 'th' => 34,
+ 'sq' => 99,
+ 'sr' => 23,
+ 'sr@latin' => 45,
+ 'sv' => 80,
+ 'ta' => 34,
+ 'te' => 9,
+ 'th' => 31,
'tk' => 0,
'tr' => 100,
- 'tt' => 18,
- 'ug' => 11,
- 'uk' => 89,
- 'ur' => 19,
- 'uz' => 36,
- 'uz@latin' => 35,
+ 'tt' => 16,
+ 'ug' => 10,
+ 'uk' => 81,
+ 'ur' => 17,
+ 'uz' => 33,
+ 'uz@latin' => 32,
'vi' => 2,
- 'vls' => 3,
- 'zh_CN' => 82,
- 'zh_TW' => 99,
+ 'vls' => 2,
+ 'zh_CN' => 76,
+ 'zh_TW' => 98,
);
?>
diff --git a/libraries/logging.lib.php b/libraries/logging.lib.php
index 975fc5a0c3..49db0ec122 100644
--- a/libraries/logging.lib.php
+++ b/libraries/logging.lib.php
@@ -27,4 +27,3 @@ function PMA_logUser($user, $status = 'ok')
}
}
-?>
diff --git a/libraries/mime.lib.php b/libraries/mime.lib.php
index a252cb3e9a..85b684d9e4 100644
--- a/libraries/mime.lib.php
+++ b/libraries/mime.lib.php
@@ -31,4 +31,3 @@ function PMA_detectMIME(&$test)
}
return 'application/octet-stream';
}
-?>
diff --git a/libraries/mult_submits.inc.php b/libraries/mult_submits.inc.php
index 36db950c71..2005c4a1b4 100644
--- a/libraries/mult_submits.inc.php
+++ b/libraries/mult_submits.inc.php
@@ -38,6 +38,11 @@ foreach ($request_params as $one_request_param) {
}
}
+global $db, $table, $clause_is_unique, $from_prefix, $goto,
+ $mult_btn, $original_sql_query, $query_type, $reload,
+ $selected, $selected_fld, $selected_recent_table, $sql_query,
+ $submit_mult, $table_type, $to_prefix, $url_query, $pmaThemeImage;
+
/**
* Prepares the work and runs some other scripts if required
*/
@@ -57,80 +62,62 @@ if (! empty($submit_mult)
} elseif (! empty($_POST['selected_tbl'])) {
// coming from database structure view - do something with
// selected tables
- if ($submit_mult == 'print') {
- include './tbl_printview.php';
- } else {
- $selected = $_POST['selected_tbl'];
- switch ($submit_mult) {
- case 'add_prefix_tbl':
- case 'replace_prefix_tbl':
- case 'copy_tbl_change_prefix':
- case 'drop_db':
- case 'drop_tbl':
- case 'empty_tbl':
- $what = $submit_mult;
- break;
- case 'check_tbl':
- case 'optimize_tbl':
- case 'repair_tbl':
- case 'analyze_tbl':
- $query_type = $submit_mult;
- unset($submit_mult);
- $mult_btn = __('Yes');
- break;
- case 'export':
- unset($submit_mult);
- include 'db_export.php';
- exit;
- break;
- case 'show_create':
- $show_create = PMA_getHtmlShowCreate($GLOBALS['db'], $selected);
- // Send response to client.
- $response = PMA_Response::getInstance();
- $response->addJSON('message', $show_create);
- exit;
- case 'sync_unique_columns_central_list':
- include_once 'libraries/central_columns.lib.php';
- $centralColsError = PMA_syncUniqueColumns($selected);
- break;
- case 'delete_unique_columns_central_list':
- include_once 'libraries/central_columns.lib.php';
- $centralColsError = PMA_deleteColumnsFromList($selected);
- break;
- case 'make_consistent_with_central_list':
- include_once 'libraries/central_columns.lib.php';
- $centralColsError = PMA_makeConsistentWithList(
- $GLOBALS['db'],
- $selected
+ $selected = $_POST['selected_tbl'];
+ switch ($submit_mult) {
+ case 'add_prefix_tbl':
+ case 'replace_prefix_tbl':
+ case 'copy_tbl_change_prefix':
+ case 'drop_db':
+ case 'drop_tbl':
+ case 'empty_tbl':
+ $what = $submit_mult;
+ break;
+ case 'check_tbl':
+ case 'optimize_tbl':
+ case 'repair_tbl':
+ case 'analyze_tbl':
+ case 'checksum_tbl':
+ $query_type = $submit_mult;
+ unset($submit_mult);
+ $mult_btn = __('Yes');
+ break;
+ case 'export':
+ unset($submit_mult);
+ include 'db_export.php';
+ exit;
+ break;
+ case 'show_create':
+ $show_create = PMA\Template::get('database/structure/show_create')
+ ->render(
+ array(
+ 'db' => $GLOBALS['db'],
+ 'db_objects' => $selected,
+ )
);
- break;
- } // end switch
- }
+ // Send response to client.
+ $response = PMA_Response::getInstance();
+ $response->addJSON('message', $show_create);
+ exit;
+ case 'sync_unique_columns_central_list':
+ include_once 'libraries/central_columns.lib.php';
+ $centralColsError = PMA_syncUniqueColumns($selected);
+ break;
+ case 'delete_unique_columns_central_list':
+ include_once 'libraries/central_columns.lib.php';
+ $centralColsError = PMA_deleteColumnsFromList($selected);
+ break;
+ case 'make_consistent_with_central_list':
+ include_once 'libraries/central_columns.lib.php';
+ $centralColsError = PMA_makeConsistentWithList(
+ $GLOBALS['db'],
+ $selected
+ );
+ break;
+ } // end switch
} elseif (isset($selected_fld) && !empty($selected_fld)) {
// coming from table structure view - do something with
// selected columns
- $selected = $selected_fld;
- list(
- $what_ret, $query_type_ret, $is_unset_submit_mult, $mult_btn_ret,
- $centralColsError
- )
- = PMA_getDataForSubmitMult(
- $submit_mult, $GLOBALS['db'], $table,
- $selected, $action
- );
- //update the existing variables
- if (isset($what_ret)) {
- $what = $what_ret;
- }
- if (isset($query_type_ret)) {
- $query_type = $query_type_ret;
- }
- if ($is_unset_submit_mult) {
- unset($submit_mult);
- }
- if (isset($mult_btn_ret)) {
- $mult_btn = $mult_btn_ret;
- }
+ // handled in StructrueController
} else {
// coming from browsing - do something with selected rows
$what = 'row_delete';
@@ -160,7 +147,19 @@ if (!empty($submit_mult) && !empty($what)) {
include './libraries/tbl_info.inc.php';
} elseif (/*overload*/mb_strlen($db)) {
include './libraries/db_common.inc.php';
- include './libraries/db_info.inc.php';
+
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
+
} else {
include_once './libraries/server_common.inc.php';
}
@@ -168,7 +167,7 @@ if (!empty($submit_mult) && !empty($what)) {
// Builds the query
list($full_query, $reload, $full_query_views)
= PMA_getQueryFromSelected(
- $what, $db, $table, $selected, $views
+ $what, $table, $selected, $views
);
// Displays the confirmation form
@@ -178,12 +177,18 @@ if (!empty($submit_mult) && !empty($what)) {
isset($original_url_query)? $original_url_query : null
);
+ $response = PMA_Response::getInstance();
+
if ($what == 'replace_prefix_tbl' || $what == 'copy_tbl_change_prefix') {
- echo PMA_getHtmlForReplacePrefixTable($what, $action, $_url_params);
+ $response->addHTML(
+ PMA_getHtmlForReplacePrefixTable($what, $action, $_url_params)
+ );
} elseif ($what == 'add_prefix_tbl') {
- echo PMA_getHtmlForAddPrefixTable($action, $_url_params);
+ $response->addHTML(PMA_getHtmlForAddPrefixTable($action, $_url_params));
} else {
- echo PMA_getHtmlForOtherActions($what, $action, $_url_params, $full_query);
+ $response->addHTML(
+ PMA_getHtmlForOtherActions($what, $action, $_url_params, $full_query)
+ );
}
exit;
@@ -214,17 +219,11 @@ if (!empty($submit_mult) && !empty($what)) {
$GLOBALS['dbi']->freeResult($result);
}
- if (! isset($_REQUEST['fk_check'])
- && ($query_type == 'drop_tbl'
+ if ($query_type == 'drop_tbl'
|| $query_type == 'empty_tbl'
- || $query_type == 'row_delete')
+ || $query_type == 'row_delete'
) {
- $default_fk_check_value = $GLOBALS['dbi']->fetchValue(
- 'SHOW VARIABLES LIKE \'foreign_key_checks\';', 0, 1
- ) == 'ON';
-
- // for disabling foreign key checks while dropping tables
- $GLOBALS['dbi']->query('SET FOREIGN_KEY_CHECKS = 0;');
+ $default_fk_check_value = PMA_Util::handleDisableFKCheckInit();
}
list(
@@ -251,15 +250,31 @@ if (!empty($submit_mult) && !empty($what)) {
}
if ($use_sql) {
+
/**
* Parse and analyze the query
*/
include_once 'libraries/parse_analyze.inc.php';
PMA_executeQueryAndSendQueryResponse(
- $analyzed_sql_results, false, $db, $table, null, null, null,
- false, null, null, null, $goto, $pmaThemeImage, null, null,
- $query_type, $sql_query, $selected, null
+ $analyzed_sql_results, // analyzed_sql_results
+ false, // is_gotofile
+ $db, // db
+ $table, // table
+ null, // find_real_end
+ null, // sql_query_for_bookmark
+ null, // extra_data
+ null, // message_to_show
+ null, // message
+ null, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ null, // disp_query
+ null, // disp_message
+ $query_type, // query_type
+ $sql_query, // sql_query
+ $selected, // selectedTables
+ null // complete_query
);
} elseif (!$run_parts) {
$GLOBALS['dbi']->selectDb($db);
@@ -274,13 +289,11 @@ if (!empty($submit_mult) && !empty($what)) {
$message = PMA_Message::error($GLOBALS['dbi']->getError());
}
}
- if (! isset($_REQUEST['fk_check'])
- && ($query_type == 'drop_tbl'
+ if ($query_type == 'drop_tbl'
|| $query_type == 'empty_tbl'
- || $query_type == 'row_delete')
- && $default_fk_check_value
+ || $query_type == 'row_delete'
) {
- $GLOBALS['dbi']->query('SET FOREIGN_KEY_CHECKS = 1;');
+ PMA_Util::handleDisableFKCheckCleanup($default_fk_check_value);
}
if ($rebuild_database_list) {
// avoid a problem with the database list navigator
@@ -304,4 +317,3 @@ if (!empty($submit_mult) && !empty($what)) {
$message = PMA_Message::success(__('No change'));
}
}
-?>
diff --git a/libraries/mult_submits.lib.php b/libraries/mult_submits.lib.php
index ed1f637a0d..bfc2830c6c 100644
--- a/libraries/mult_submits.lib.php
+++ b/libraries/mult_submits.lib.php
@@ -45,7 +45,7 @@ function PMA_getUrlParams(
foreach ($selected as $sval) {
if ($what == 'row_delete') {
$_url_params['selected'][] = 'DELETE FROM '
- . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table)
+ . PMA_Util::backquote($table)
. ' WHERE ' . urldecode($sval) . ' LIMIT 1;';
} else {
$_url_params['selected'][] = $sval;
@@ -150,6 +150,12 @@ function PMA_getQueryStrFromSelected(
$use_sql = true;
break;
+ case 'checksum_tbl':
+ $sql_query .= (empty($sql_query) ? 'CHECKSUM TABLE ' : ', ')
+ . PMA_Util::backquote($selected[$i]);
+ $use_sql = true;
+ break;
+
case 'repair_tbl':
$sql_query .= (empty($sql_query) ? 'REPAIR TABLE ' : ', ')
. PMA_Util::backquote($selected[$i]);
@@ -294,32 +300,6 @@ function PMA_getQueryStrFromSelected(
}
/**
- * Gets table primary key
- *
- * @param string $db name of db
- * @param string $table name of table
- *
- * @return string
- */
-function PMA_getKeyForTablePrimary($db, $table)
-{
- $GLOBALS['dbi']->selectDb($db);
- $result = $GLOBALS['dbi']->query(
- 'SHOW KEYS FROM ' . PMA_Util::backquote($table) . ';'
- );
- $primary = '';
- while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
- // Backups the list of primary keys
- if ($row['Key_name'] == 'PRIMARY') {
- $primary .= $row['Column_name'] . ', ';
- }
- } // end while
- $GLOBALS['dbi']->freeResult($result);
-
- return $primary;
-}
-
-/**
* Gets HTML for replace_prefix_tbl or copy_tbl_change_prefix
*
* @param string $what mult_submit type
@@ -403,7 +383,7 @@ function PMA_getHtmlForAddPrefixTable($action, $_url_params)
* @param string $what mult_submit type
* @param string $action action type
* @param array $_url_params URL params
- * @param array $full_query full sql query string
+ * @param string $full_query full sql query string
*
* @return string
*/
@@ -428,22 +408,7 @@ function PMA_getHtmlForOtherActions($what, $action, $_url_params, $full_query)
// Display option to disable foreign key checks while dropping tables
if ($what === 'drop_tbl' || $what === 'empty_tbl' || $what === 'row_delete') {
$html .= '<div id="foreignkeychk">';
- $html .= '<label for="fkc_checkbox">';
- $html .= __('Foreign key check:');
- $html .= '</label>';
- $html .= '<span class="checkbox">';
- $html .= '<input type="checkbox" name="fk_check" value="1" '
- . 'id="fkc_checkbox"';
- $default_fk_check_value = $GLOBALS['dbi']->fetchValue(
- 'SHOW VARIABLES LIKE \'foreign_key_checks\';', 0, 1
- ) == 'ON';
- if ($default_fk_check_value) {
- $html .= ' checked="checked"';
- }
- $html .= '/></span>';
- $html .= '<label id="fkc_status" for="fkc_checkbox">';
- $html .= ($default_fk_check_value) ? __('(Enabled)') : __('(Disabled)');
- $html .= '</label>';
+ $html .= PMA_Util::getFKCheckbox();
$html .= '</div>';
}
$html .= '<input id="buttonYes" type="submit" name="mult_btn" value="'
@@ -457,95 +422,16 @@ function PMA_getHtmlForOtherActions($what, $action, $_url_params, $full_query)
}
/**
- * Get List of information for Submit Mult
- *
- * @param string $submit_mult mult_submit type
- * @param string $db database name
- * @param string $table table name
- * @param array $selected the selected columns
- * @param string $action action type
- *
- * @return array
- */
-function PMA_getDataForSubmitMult($submit_mult, $db, $table, $selected, $action)
-{
- $what = null;
- $query_type = null;
- $is_unset_submit_mult = false;
- $mult_btn = null;
- $centralColsError = null;
- switch ($submit_mult) {
- case 'drop':
- $what = 'drop_fld';
- break;
- case 'primary':
- // Gets table primary key
- $primary = PMA_getKeyForTablePrimary($db, $table);
- if (empty($primary)) {
- // no primary key, so we can safely create new
- $is_unset_submit_mult = true;
- $query_type = 'primary_fld';
- $mult_btn = __('Yes');
- } else {
- // primary key exists, so lets as user
- $what = 'primary_fld';
- }
- break;
- case 'index':
- $is_unset_submit_mult = true;
- $query_type = 'index_fld';
- $mult_btn = __('Yes');
- break;
- case 'unique':
- $is_unset_submit_mult = true;
- $query_type = 'unique_fld';
- $mult_btn = __('Yes');
- break;
- case 'spatial':
- $is_unset_submit_mult = true;
- $query_type = 'spatial_fld';
- $mult_btn = __('Yes');
- break;
- case 'ftext':
- $is_unset_submit_mult = true;
- $query_type = 'fulltext_fld';
- $mult_btn = __('Yes');
- break;
- case 'add_to_central_columns':
- include_once 'libraries/central_columns.lib.php';
- $centralColsError = PMA_syncUniqueColumns($selected, false);
- break;
- case 'remove_from_central_columns':
- include_once 'libraries/central_columns.lib.php';
- $centralColsError = PMA_deleteColumnsFromList($selected, false);
- break;
- case 'change':
- PMA_displayHtmlForColumnChange($db, $table, $selected, $action);
- // execution stops here but PMA_Response correctly finishes
- // the rendering
- exit;
- case 'browse':
- // this should already be handled by tbl_structure.php
- }
-
- return array(
- $what, $query_type, $is_unset_submit_mult, $mult_btn,
- $centralColsError
- );
-}
-
-/**
* Get query string from Selected
*
* @param string $what mult_submit type
- * @param string $db database name
* @param string $table table name
* @param array $selected the selected columns
* @param array $views table views
*
* @return array
*/
-function PMA_getQueryFromSelected($what, $db, $table, $selected, $views)
+function PMA_getQueryFromSelected($what, $table, $selected, $views)
{
$reload = false;
$full_query_views = null;
@@ -561,8 +447,7 @@ function PMA_getQueryFromSelected($what, $db, $table, $selected, $views)
switch ($what) {
case 'row_delete':
$full_query .= 'DELETE FROM '
- . PMA_Util::backquote(htmlspecialchars($db))
- . '.' . PMA_Util::backquote(htmlspecialchars($table))
+ . PMA_Util::backquote(htmlspecialchars($table))
// Do not append a "LIMIT 1" clause here
// (it's not binlog friendly).
// We don't need the clause because the calling panel permits
@@ -644,4 +529,3 @@ function PMA_getQueryFromSelected($what, $db, $table, $selected, $views)
return array($full_query, $reload, $full_query_views);
}
-?>
diff --git a/libraries/mysql_charsets.inc.php b/libraries/mysql_charsets.inc.php
index d4d74e17df..431f7950ad 100644
--- a/libraries/mysql_charsets.inc.php
+++ b/libraries/mysql_charsets.inc.php
@@ -126,4 +126,3 @@ define('PMA_CSDROPDOWN_CHARSET', 1);
*/
require_once './libraries/mysql_charsets.lib.php';
-?>
diff --git a/libraries/mysql_charsets.lib.php b/libraries/mysql_charsets.lib.php
index af48c264ee..353f7c6943 100644
--- a/libraries/mysql_charsets.lib.php
+++ b/libraries/mysql_charsets.lib.php
@@ -126,9 +126,7 @@ function PMA_getDbCollation($db)
return $GLOBALS['dbi']->fetchValue($sql);
} else {
$GLOBALS['dbi']->selectDb($db);
- $return = $GLOBALS['dbi']->fetchValue(
- 'SHOW VARIABLES LIKE \'collation_database\'', 0, 1
- );
+ $return = $GLOBALS['dbi']->fetchValue('SELECT @@collation_database');
if ($db !== $GLOBALS['db']) {
$GLOBALS['dbi']->selectDb($GLOBALS['db']);
}
@@ -143,9 +141,7 @@ function PMA_getDbCollation($db)
*/
function PMA_getServerCollation()
{
- return $GLOBALS['dbi']->fetchValue(
- 'SHOW VARIABLES LIKE \'collation_server\'', 0, 1
- );
+ return $GLOBALS['dbi']->fetchValue('SELECT @@collation_server');
}
/**
@@ -239,6 +235,9 @@ function PMA_getCollationDescr($collation)
case 'romanian':
$descr = __('Romanian');
break;
+ case 'sinhala':
+ $descr = __('Sinhalese');
+ break;
case 'slovak':
$descr = __('Slovak');
break;
@@ -266,6 +265,10 @@ function PMA_getCollationDescr($collation)
case 'unicode':
$descr = __('Unicode') . ' (' . __('multilingual') . ')';
break;
+ case 'vietnamese':
+ $descr = __('Vietnamese');
+ break;
+ /** @noinspection PhpMissingBreakStatementInspection */
case 'bin':
$is_bin = true;
// no break; statement here, continuing with 'general' section:
@@ -376,4 +379,3 @@ function PMA_getCollationDescr($collation)
return $descr;
}
-?>
diff --git a/libraries/mysql_relations.lib.php b/libraries/mysql_relations.lib.php
index a9b061a8fb..a6bc43a522 100644
--- a/libraries/mysql_relations.lib.php
+++ b/libraries/mysql_relations.lib.php
@@ -166,4 +166,3 @@ $GLOBALS['mysql_relations'] = array(
),
),
);
-?> \ No newline at end of file
diff --git a/libraries/navigation/Navigation.class.php b/libraries/navigation/Navigation.class.php
index b8cca7517f..bd9114787b 100644
--- a/libraries/navigation/Navigation.class.php
+++ b/libraries/navigation/Navigation.class.php
@@ -60,6 +60,11 @@ class PMA_Navigation
if (! PMA_Response::getInstance()->isAjax()) {
// closes the tags that were opened by the navigation header
$retval .= '</div>'; // pma_navigation_tree
+ $retval .= '<div id="pma_navi_settings_container">';
+ if (!defined('PMA_DISABLE_NAVI_SETTINGS')) {
+ $retval .= PMA_PageSettings::getNaviSettings();
+ }
+ $retval .= '</div>'; //pma_navi_settings_container
$retval .= '</div>'; // pma_navigation_content
$retval .= $this->_getDropHandler();
$retval .= '</div>'; // pma_navigation
@@ -184,6 +189,7 @@ class PMA_Navigation
$GLOBALS['dbi']->freeResult($result);
$typeMap = array(
+ 'group' => __('Groups:'),
'event' => __('Events:'),
'function' => __('Functions:'),
'procedure' => __('Procedures:'),
@@ -225,4 +231,3 @@ class PMA_Navigation
return $html;
}
}
-?>
diff --git a/libraries/navigation/NavigationHeader.class.php b/libraries/navigation/NavigationHeader.class.php
index 73a6dafb92..e707f53db0 100644
--- a/libraries/navigation/NavigationHeader.class.php
+++ b/libraries/navigation/NavigationHeader.class.php
@@ -9,6 +9,9 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/Template.class.php';
+use PMA\Template;
+
/**
* This class renders the logo, links, server selection,
* which are then displayed at the top of the navigation panel
@@ -73,11 +76,10 @@ class PMA_NavigationHeader
*/
private function _logo()
{
- $retval = '<!-- LOGO START -->';
// display Logo, depending on $GLOBALS['cfg']['NavigationDisplayLogo']
if (!$GLOBALS['cfg']['NavigationDisplayLogo']) {
- $retval .= '<!-- LOGO END -->';
- return $retval;
+ return Template::get('navigation/logo')
+ ->render(array('displayLogo' => false));
}
$logo = 'phpMyAdmin';
@@ -88,44 +90,56 @@ class PMA_NavigationHeader
$logo = '<img src="' . $GLOBALS['pmaThemeImage'] . 'pma_logo2.png" '
. 'alt="' . $logo . '" id="imgpmalogo" />';
}
- $retval .= '<div id="pmalogo">';
- if ($GLOBALS['cfg']['NavigationLogoLink']) {
- $logo_link = trim(
- htmlspecialchars($GLOBALS['cfg']['NavigationLogoLink'])
- );
- // prevent XSS, see PMASA-2013-9
- // if link has protocol, allow only http and https
- if (preg_match('/^[a-z]+:/i', $logo_link)
- && ! preg_match('/^https?:/i', $logo_link)
- ) {
- $logo_link = 'index.php';
- }
- $retval .= ' <a href="' . $logo_link;
- switch ($GLOBALS['cfg']['NavigationLogoLinkWindow']) {
- case 'new':
- $retval .= '" target="_blank"';
- break;
- case 'main':
- // do not add our parameters for an external link
- $host = parse_url(
- $GLOBALS['cfg']['NavigationLogoLink'], PHP_URL_HOST
+
+ if (!$GLOBALS['cfg']['NavigationLogoLink']) {
+ return Template::get('navigation/logo')
+ ->render(
+ array(
+ 'displayLogo' => true,
+ 'useLogoLink' => false,
+ 'logo' => $logo,
+ )
);
- if (empty($host)) {
- $retval .= PMA_URL_getCommon() . '"';
- } else {
- $retval .= '" target="_blank"';
- }
+ }
+
+ $useLogoLink = true;
+ $linkAttriks = null;
+ $logoLink = trim(
+ htmlspecialchars($GLOBALS['cfg']['NavigationLogoLink'])
+ );
+ // prevent XSS, see PMASA-2013-9
+ // if link has protocol, allow only http and https
+ if (preg_match('/^[a-z]+:/i', $logoLink)
+ && ! preg_match('/^https?:/i', $logoLink)
+ ) {
+ $logoLink = 'index.php';
+ }
+ switch ($GLOBALS['cfg']['NavigationLogoLinkWindow']) {
+ case 'new':
+ $linkAttriks = 'target="_blank"';
+ break;
+ case 'main':
+ // do not add our parameters for an external link
+ $host = parse_url(
+ $GLOBALS['cfg']['NavigationLogoLink'], PHP_URL_HOST
+ );
+ if (empty($host)) {
+ $logoLink .= PMA_URL_getCommon();
+ } else {
+ $linkAttriks = 'target="_blank"';
}
- $retval .= '>';
- $retval .= $logo;
- $retval .= '</a>';
- } else {
- $retval .= $logo;
}
- $retval .= '</div>';
- $retval .= '<!-- LOGO END -->';
- return $retval;
+ return Template::get('navigation/logo')
+ ->render(
+ array(
+ 'displayLogo' => true,
+ 'useLogoLink' => $useLogoLink,
+ 'logoLink' => $logoLink,
+ 'linkAttribs' => $linkAttriks,
+ 'logo' => $logo,
+ )
+ );
}
/**
@@ -189,6 +203,17 @@ class PMA_NavigationHeader
$retval .= PMA_Util::getNavigationLink(
'#',
$showText,
+ __('Navigation panel settings'),
+ $showIcon,
+ 's_cog.png',
+ 'pma_navigation_settings_icon',
+ false,
+ '',
+ defined('PMA_DISABLE_NAVI_SETTINGS') ? array('hide') : array()
+ );
+ $retval .= PMA_Util::getNavigationLink(
+ '#',
+ $showText,
__('Reload navigation panel'),
$showIcon,
's_reload.png',
@@ -220,4 +245,3 @@ class PMA_NavigationHeader
return $retval;
}
}
-?>
diff --git a/libraries/navigation/NavigationTree.class.php b/libraries/navigation/NavigationTree.class.php
index 9f45dc592a..1ad23cb2b7 100644
--- a/libraries/navigation/NavigationTree.class.php
+++ b/libraries/navigation/NavigationTree.class.php
@@ -42,28 +42,28 @@ class PMA_NavigationTree
private $_pos;
/**
- * @var int The names of the type of items that are being paginated on
- * the second level of the navigation tree. These may be
- * tables, views, functions, procedures or events.
+ * @var array The names of the type of items that are being paginated on
+ * the second level of the navigation tree. These may be
+ * tables, views, functions, procedures or events.
*/
private $_pos2_name = array();
/**
- * @var int The positions of nodes in the lists of tables, views,
- * routines or events used for pagination
+ * @var array The positions of nodes in the lists of tables, views,
+ * routines or events used for pagination
*/
private $_pos2_value = array();
/**
- * @var int The names of the type of items that are being paginated
- * on the second level of the navigation tree.
- * These may be columns or indexes
+ * @var array The names of the type of items that are being paginated
+ * on the second level of the navigation tree.
+ * These may be columns or indexes
*/
private $_pos3_name = array();
/**
- * @var int The positions of nodes in the lists of columns or indexes
- * used for pagination
+ * @var array The positions of nodes in the lists of columns or indexes
+ * used for pagination
*/
private $_pos3_value = array();
@@ -82,8 +82,8 @@ class PMA_NavigationTree
private $_searchClause2 = '';
/**
- * @var string Whether a warning was raised for large item groups
- * which can affect performance.
+ * @var bool Whether a warning was raised for large item groups
+ * which can affect performance.
*/
private $_largeGroupWarning = false;
@@ -318,12 +318,20 @@ class PMA_NavigationTree
*/
private function _buildPathPart($path, $type2, $pos2, $type3, $pos3)
{
+ if (empty($pos2)) {
+ $pos2 = 0;
+ }
+ if (empty($pos3)) {
+ $pos3 = 0;
+ }
+
$retval = true;
if (count($path) <= 1) {
return $retval;
}
array_shift($path); // remove 'root'
+ /* @var $db Node_Database */
$db = $this->_tree->getChild($path[0]);
$retval = $db;
@@ -411,6 +419,7 @@ class PMA_NavigationTree
return $retval;
}
+ /* @var $table Node_Table */
$table = $container->getChild($path[0], true);
if ($table === false) {
if (!$db->getPresence('tables', $path[0])) {
@@ -487,14 +496,14 @@ class PMA_NavigationTree
* References to existing children are returned
* if this function is called twice on the same node
*
- * @param Node $table The table node, new containers will be
- * attached to this node
- * @param int $pos2 The position for the pagination of
- * the branch at the second level of the tree
- * @param string $type3 The type of item being paginated on
- * the third level of the tree
- * @param int $pos3 The position for the pagination of
- * the branch at the third level of the tree
+ * @param Node_Table $table The table node, new containers will be
+ * attached to this node
+ * @param int $pos2 The position for the pagination of
+ * the branch at the second level of the tree
+ * @param string $type3 The type of item being paginated on
+ * the third level of the tree
+ * @param int $pos3 The position for the pagination of
+ * the branch at the third level of the tree
*
* @return array An array of new nodes
*/
@@ -542,40 +551,68 @@ class PMA_NavigationTree
* References to existing children are returned
* if this function is called twice on the same node
*
- * @param Node $db The database node, new containers will be
- * attached to this node
- * @param string $type The type of item being paginated on
- * the second level of the tree
- * @param int $pos2 The position for the pagination of
- * the branch at the second level of the tree
+ * @param Node_Database $db The database node, new containers will be
+ * attached to this node
+ * @param string $type The type of item being paginated on
+ * the second level of the tree
+ * @param int $pos2 The position for the pagination of
+ * the branch at the second level of the tree
*
* @return array An array of new nodes
*/
private function _addDbContainers($db, $type, $pos2)
{
+ // Get items to hide
+ $hidden = $db->getHiddenItems('group');
+ if (!$GLOBALS['cfg']['NavigationTreeShowTables']
+ && !in_array('tables', $hidden)
+ ) {
+ $hidden[] = 'tables';
+ }
+ if (!$GLOBALS['cfg']['NavigationTreeShowViews']
+ && !in_array('views', $hidden)
+ ) {
+ $hidden[] = 'views';
+ }
+ if (!$GLOBALS['cfg']['NavigationTreeShowFunctions']
+ && !in_array('functions', $hidden)
+ ) {
+ $hidden[] = 'functions';
+ }
+ if (!$GLOBALS['cfg']['NavigationTreeShowProcedures']
+ && !in_array('procedures', $hidden)
+ ) {
+ $hidden[] = 'procedures';
+ }
+ if (!$GLOBALS['cfg']['NavigationTreeShowEvents']
+ && !in_array('events', $hidden)
+ ) {
+ $hidden[] = 'events';
+ }
+
$retval = array();
if ($db->hasChildren(true) == 0) {
- if ($db->getPresence('tables')) {
+ if (!in_array('tables', $hidden) && $db->getPresence('tables')) {
$retval['tables'] = PMA_NodeFactory::getInstance(
'Node_Table_Container'
);
}
- if ($db->getPresence('views')) {
+ if (!in_array('views', $hidden) && $db->getPresence('views')) {
$retval['views'] = PMA_NodeFactory::getInstance(
'Node_View_Container'
);
}
- if ($db->getPresence('functions')) {
+ if (!in_array('functions', $hidden) && $db->getPresence('functions')) {
$retval['functions'] = PMA_NodeFactory::getInstance(
'Node_Function_Container'
);
}
- if ($db->getPresence('procedures')) {
+ if (!in_array('procedures', $hidden) && $db->getPresence('procedures')) {
$retval['procedures'] = PMA_NodeFactory::getInstance(
'Node_Procedure_Container'
);
}
- if ($db->getPresence('events')) {
+ if (!in_array('events', $hidden) && $db->getPresence('events')) {
$retval['events'] = PMA_NodeFactory::getInstance(
'Node_Event_Container'
);
@@ -663,9 +700,9 @@ class PMA_NavigationTree
}
}
//Bug #4375: Check if prefix is the name of a DB, to create a group.
- foreach ($node->children as $child) {
- if (array_key_exists($child->name, $prefixes)) {
- $prefixes[$child->name]++;
+ foreach ($node->children as $otherChild) {
+ if (array_key_exists($otherChild->name, $prefixes)) {
+ $prefixes[$otherChild->name]++;
}
}
}
@@ -676,24 +713,38 @@ class PMA_NavigationTree
}
}
}
+ // It is not a group if it has only one item
foreach ($prefixes as $key => $value) {
if ($value == 1) {
unset($prefixes[$key]);
- } else if ($value > 500 && ! $this->_largeGroupWarning) {
- trigger_error(
- __(
- 'There are large item groups in navigation panel which '
- . 'may affect the performance. Consider disabling item '
- . 'grouping in the navigation panel.'
- ),
- E_USER_WARNING
- );
- $this->_largeGroupWarning = true;
+ }
+ }
+ // rfe #1634 Don't group if there's only one group and no other items
+ if (count($prefixes) == 1) {
+ $keys = array_keys($prefixes);
+ $key = $keys[0];
+ if ($prefixes[$key] == count($node->children) - 1) {
+ unset($prefixes[$key]);
}
}
if (count($prefixes)) {
+ /** @var Node[] $groups */
$groups = array();
foreach ($prefixes as $key => $value) {
+
+ // warn about large groups
+ if ($value > 500 && ! $this->_largeGroupWarning) {
+ trigger_error(
+ __(
+ 'There are large item groups in navigation panel which '
+ . 'may affect the performance. Consider disabling item '
+ . 'grouping in the navigation panel.'
+ ),
+ E_USER_WARNING
+ );
+ $this->_largeGroupWarning = true;
+ }
+
$groups[$key] = new Node(
$key,
Node::CONTAINER,
@@ -955,7 +1006,7 @@ class PMA_NavigationTree
if ($node->hasSiblings()
|| $node->realParent() === false
) {
- if ( $node->type == Node::CONTAINER
+ if ($node->type == Node::CONTAINER
&& count($node->children) == 0
&& $GLOBALS['is_ajax_request'] != true
) {
@@ -1008,7 +1059,11 @@ class PMA_NavigationTree
$retval .= $this->_pos;
$retval .= "</span>";
$retval .= $this->_getPaginationParamsHtml($node);
- $retval .= $node->getIcon($match);
+ if ($GLOBALS['cfg']['ShowDatabasesNavigationAsTree']
+ || $parentName != 'root'
+ ) {
+ $retval .= $node->getIcon($match);
+ }
$retval .= "</a>";
$retval .= "</div>";
@@ -1032,7 +1087,7 @@ class PMA_NavigationTree
'indexes'
);
$parent = $node->parents(false, true);
- $isNewView = $parent[0]->real_name == 'views' && $node->isNew == true;
+ $isNewView = $parent[0]->real_name == 'views' && $node->isNew === true;
if ($parent[0]->type == Node::CONTAINER
&& (in_array($parent[0]->real_name, $haveAjax) || $isNewView)
) {
@@ -1100,10 +1155,10 @@ class PMA_NavigationTree
} else {
$retval .= "&nbsp;{$node->name}";
}
+ $retval .= $node->getHtmlForControlButtons();
if ($node->type == Node::CONTAINER) {
$retval .= "</i>";
}
- $retval .= $node->getHtmlForControlButtons();
$retval .= '<div class="clearfloat"></div>';
$wrap = true;
} else {
@@ -1114,7 +1169,7 @@ class PMA_NavigationTree
if ($recursive) {
$hide = '';
- if ($node->visible == false) {
+ if (!$node->visible) {
$hide = " style='display: none;'";
}
$children = $node->children;
@@ -1178,9 +1233,9 @@ class PMA_NavigationTree
'server' => $GLOBALS['server']
);
$retval .= '<div id="pma_navigation_db_select">';
- $retval .= '<form action="db_structure.php">';
+ $retval .= '<form action="index.php">';
$retval .= PMA_getHiddenFields($url_params);
- $retval .= '<select name="db" id="navi_db_select">'
+ $retval .= '<select name="db" class="hide" id="navi_db_select">'
. '<option value="" dir="' . $GLOBALS['text_dir'] . '">'
. '(' . __('Databases') . ') ...</option>' . "\n";
$selected = $GLOBALS['db'];
@@ -1205,11 +1260,20 @@ class PMA_NavigationTree
}
$retval .= '</select></form>';
$retval .= '</div></div>';
- $retval .= '<div id="pma_navigation_tree_content">';
- $retval .= '<div style="margin:0.75em">';
- $retval .= __('Please select a database.');
- $retval .= '</div>';
- $retval .= '</div>';
+ $retval .= '<div id="pma_navigation_tree_content"><ul>';
+ $children = $this->_tree->children;
+ usort($children, array('PMA_NavigationTree', 'sortNode'));
+ $this->_setVisibility();
+ for ($i=0, $nbChildren = count($children); $i < $nbChildren; $i++) {
+ if ($i == 0) {
+ $retval .= $this->_renderNode($children[0], true, 'first');
+ } else if ($i + 1 != $nbChildren) {
+ $retval .= $this->_renderNode($children[$i], true);
+ } else {
+ $retval .= $this->_renderNode($children[$i], true, 'last');
+ }
+ }
+ $retval .= '</ul></div>';
return $retval;
}
@@ -1449,4 +1513,3 @@ class PMA_NavigationTree
return $retval;
}
}
-?>
diff --git a/libraries/navigation/NodeFactory.class.php b/libraries/navigation/NodeFactory.class.php
index c76e835aff..e3be5b62b6 100644
--- a/libraries/navigation/NodeFactory.class.php
+++ b/libraries/navigation/NodeFactory.class.php
@@ -94,4 +94,3 @@ class PMA_NodeFactory
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node.class.php b/libraries/navigation/Nodes/Node.class.php
index b632708287..849901566a 100644
--- a/libraries/navigation/Nodes/Node.class.php
+++ b/libraries/navigation/Nodes/Node.class.php
@@ -62,8 +62,8 @@ class Node
public $parent;
/**
- * @var array An array of Node objects that are
- * direct children of this node
+ * @var Node[] An array of Node objects that are
+ * direct children of this node
*/
public $children = array();
@@ -101,7 +101,7 @@ class Node
public $classes = '';
/**
- * @var string Whether this node is a link for creating new objects
+ * @var bool Whether this node is a link for creating new objects
*/
public $isNew = false;
@@ -124,8 +124,6 @@ class Node
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -211,14 +209,14 @@ class Node
$parents = array();
if ($self
&& ($this->type != Node::CONTAINER || $containers)
- && ($this->is_group != true || $groups)
+ && (!$this->is_group || $groups)
) {
$parents[] = $this;
}
$parent = $this->parent;
while (isset($parent)) {
- if ( ($parent->type != Node::CONTAINER || $containers)
- && ($parent->is_group != true || $groups)
+ if (($parent->type != Node::CONTAINER || $containers)
+ && (!$parent->is_group || $groups)
) {
$parents[] = $parent;
}
@@ -386,16 +384,24 @@ class Node
$query = "SHOW DATABASES ";
$query .= $this->_getWhereClause('Database', $searchClause);
$handle = $GLOBALS['dbi']->tryQuery($query);
- if ($handle !== false) {
- $count = 0;
- while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
- if ($pos <= 0 && $count < $maxItems) {
- $retval[] = $arr[0];
- $count++;
- }
- $pos--;
+ if ($handle === false) {
+ return $retval;
+ }
+
+ $count = 0;
+ if (!$GLOBALS['dbi']->dataSeek($handle, $pos)) {
+ return $retval;
+ }
+
+ while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
+ if ($count < $maxItems) {
+ $retval[] = $arr[0];
+ $count++;
+ } else {
+ break;
}
}
+
return $retval;
}
@@ -795,7 +801,7 @@ class Node
public function getNavigationHidingData()
{
$cfgRelation = PMA_getRelationsParam();
- if (isset($cfgRelation['navwork']) && $cfgRelation['navwork']) {
+ if ($cfgRelation['navwork']) {
$navTable = PMA_Util::backquote($cfgRelation['db'])
. "." . PMA_Util::backquote($cfgRelation['navigationhiding']);
$sqlQuery = "SELECT `db_name`, COUNT(*) AS `count` FROM " . $navTable
@@ -810,4 +816,3 @@ class Node
return null;
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Column.class.php b/libraries/navigation/Nodes/Node_Column.class.php
index 2b7e34cebb..525859bc63 100644
--- a/libraries/navigation/Nodes/Node_Column.class.php
+++ b/libraries/navigation/Nodes/Node_Column.class.php
@@ -23,8 +23,6 @@ class Node_Column extends Node
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Column
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -44,4 +42,3 @@ class Node_Column extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Column_Container.class.php b/libraries/navigation/Nodes/Node_Column_Container.class.php
index db818e7bf2..fb0a518e6a 100644
--- a/libraries/navigation/Nodes/Node_Column_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Column_Container.class.php
@@ -18,8 +18,6 @@ class Node_Column_Container extends Node
{
/**
* Initialises the class
- *
- * @return Node_Column_Container
*/
public function __construct()
{
@@ -54,4 +52,3 @@ class Node_Column_Container extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Database.class.php b/libraries/navigation/Nodes/Node_Database.class.php
index bcc593267c..c564dc6679 100644
--- a/libraries/navigation/Nodes/Node_Database.class.php
+++ b/libraries/navigation/Nodes/Node_Database.class.php
@@ -21,7 +21,7 @@ class Node_Database extends Node
*
* @var int
*/
- private $_hiddenCount = 0;
+ protected $hiddenCount = 0;
/**
* Initialises the class
@@ -30,8 +30,6 @@ class Node_Database extends Node
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Database
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -40,8 +38,12 @@ class Node_Database extends Node
's_db.png',
__('Database operations')
);
+
+ $script_name = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ );
$this->links = array(
- 'text' => $GLOBALS['cfg']['DefaultTabDatabase']
+ 'text' => $script_name
. '?server=' . $GLOBALS['server']
. '&amp;db=%1$s&amp;token=' . $_SESSION[' PMA_token '],
'icon' => 'db_operations.php?server=' . $GLOBALS['server']
@@ -92,7 +94,7 @@ class Node_Database extends Node
/**
* Returns the number of tables or views present inside this database
*
- * @param string $which tables|views
+ * @param string $which tables|views
* @param string $searchClause A string used to filter the results of
* the query
* @param boolean $singleItem Whether to get presence of a single known
@@ -334,7 +336,6 @@ class Node_Database extends Node
public function getData($type, $pos, $searchClause = '')
{
$retval = array();
- $db = $this->real_name;
switch ($type) {
case 'tables':
$retval = $this->_getTables($pos, $searchClause);
@@ -357,35 +358,54 @@ class Node_Database extends Node
// Remove hidden items so that they are not displayed in navigation tree
$cfgRelation = PMA_getRelationsParam();
- if (isset($cfgRelation['navwork']) && $cfgRelation['navwork']) {
- $navTable = PMA_Util::backquote($cfgRelation['db'])
- . "." . PMA_Util::backquote($cfgRelation['navigationhiding']);
- $sqlQuery = "SELECT `item_name` FROM " . $navTable
- . " WHERE `username`='" . $cfgRelation['user'] . "'"
- . " AND `item_type`='" . substr($type, 0, -1)
- . "'" . " AND `db_name`='" . PMA_Util::sqlAddSlashes($db) . "'";
- $result = PMA_queryAsControlUser($sqlQuery, false);
- if ($result) {
- $hiddenItems = array();
- while ($row = $GLOBALS['dbi']->fetchArray($result)) {
- $hiddenItems[] = $row[0];
- }
- foreach ($retval as $key => $item) {
- if (in_array($item, $hiddenItems)) {
- unset($retval[$key]);
- }
+ if ($cfgRelation['navwork']) {
+ $hiddenItems = $this->getHiddenItems(substr($type, 0, -1));
+ foreach ($retval as $key => $item) {
+ if (in_array($item, $hiddenItems)) {
+ unset($retval[$key]);
}
}
- $GLOBALS['dbi']->freeResult($result);
}
return $retval;
}
/**
+ * Return list of hidden items of given type
+ *
+ * @param string $type The type of items we are looking for
+ * ('table', 'function', 'group', etc.)
+ *
+ * @return array Array containing hidden items of given type
+ */
+ public function getHiddenItems($type)
+ {
+ $db = $this->real_name;
+ $cfgRelation = PMA_getRelationsParam();
+ if (empty($cfgRelation['navigationhiding'])) {
+ return array();
+ }
+ $navTable = PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['navigationhiding']);
+ $sqlQuery = "SELECT `item_name` FROM " . $navTable
+ . " WHERE `username`='" . $cfgRelation['user'] . "'"
+ . " AND `item_type`='" . $type
+ . "'" . " AND `db_name`='" . PMA_Util::sqlAddSlashes($db) . "'";
+ $result = PMA_queryAsControlUser($sqlQuery, false);
+ $hiddenItems = array();
+ if ($result) {
+ while ($row = $GLOBALS['dbi']->fetchArray($result)) {
+ $hiddenItems[] = $row[0];
+ }
+ }
+ $GLOBALS['dbi']->freeResult($result);
+ return $hiddenItems;
+ }
+
+ /**
* Returns the list of tables or views inside this database
*
- * @param string $which tables|views
+ * @param string $which tables|views
* @param int $pos The offset of the list within the results
* @param string $searchClause A string used to filter the results of the query
*
@@ -437,12 +457,15 @@ class Node_Database extends Node
$handle = $GLOBALS['dbi']->tryQuery($query);
if ($handle !== false) {
$count = 0;
- while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
- if ($pos <= 0 && $count < $maxItems) {
- $retval[] = $arr[0];
- $count++;
+ if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
+ while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
+ if ($count < $maxItems) {
+ $retval[] = $arr[0];
+ $count++;
+ } else {
+ break;
+ }
}
- $pos--;
}
}
}
@@ -478,7 +501,7 @@ class Node_Database extends Node
/**
* Returns the list of procedures or functions inside this database
*
- * @param string $routineType PROCEDURE|FUNCTION
+ * @param string $routineType PROCEDURE|FUNCTION
* @param int $pos The offset of the list within the results
* @param string $searchClause A string used to filter the results of the query
*
@@ -519,12 +542,15 @@ class Node_Database extends Node
$handle = $GLOBALS['dbi']->tryQuery($query);
if ($handle !== false) {
$count = 0;
- while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
- if ($pos <= 0 && $count < $maxItems) {
- $retval[] = $arr['Name'];
- $count++;
+ if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
+ while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
+ if ($count < $maxItems) {
+ $retval[] = $arr['Name'];
+ $count++;
+ } else {
+ break;
+ }
}
- $pos--;
}
}
}
@@ -599,12 +625,15 @@ class Node_Database extends Node
$handle = $GLOBALS['dbi']->tryQuery($query);
if ($handle !== false) {
$count = 0;
- while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
- if ($pos <= 0 && $count < $maxItems) {
- $retval[] = $arr['Name'];
- $count++;
+ if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
+ while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
+ if ($count < $maxItems) {
+ $retval[] = $arr['Name'];
+ $count++;
+ } else {
+ break;
+ }
}
- $pos--;
}
}
}
@@ -612,16 +641,16 @@ class Node_Database extends Node
}
/**
- * Returns HTML for show hidden button displayed infront of database node
+ * Returns HTML for control buttons displayed infront of a node
*
- * @return String HTML for show hidden button
+ * @return String HTML for control buttons
*/
public function getHtmlForControlButtons()
{
$ret = '';
$cfgRelation = PMA_getRelationsParam();
- if (isset($cfgRelation['navwork']) && $cfgRelation['navwork']) {
- if ( $this->_hiddenCount > 0) {
+ if ($cfgRelation['navwork']) {
+ if ($this->hiddenCount > 0) {
$ret = '<span class="dbItemControls">'
. '<a href="navigation.php'
. PMA_URL_getCommon()
@@ -633,6 +662,7 @@ class Node_Database extends Node
)
. '</a></span>';
}
+
}
return $ret;
}
@@ -646,7 +676,7 @@ class Node_Database extends Node
*/
public function setHiddenCount($count)
{
- $this->_hiddenCount = $count;
+ $this->hiddenCount = $count;
}
/**
@@ -656,8 +686,7 @@ class Node_Database extends Node
*/
public function getHiddenCount()
{
- return $this->_hiddenCount;
+ return $this->hiddenCount;
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_DatabaseChild.class.php b/libraries/navigation/Nodes/Node_DatabaseChild.class.php
index 398d0b2178..672232a111 100644
--- a/libraries/navigation/Nodes/Node_DatabaseChild.class.php
+++ b/libraries/navigation/Nodes/Node_DatabaseChild.class.php
@@ -10,22 +10,31 @@ if (! defined('PHPMYADMIN')) {
}
/**
- * Represents a node that is a concrete child of a database node
+ * Represents a node that is a child of a database node
+ * This may either be a concrete child such as table or a container
+ * such as table container
*
* @package PhpMyAdmin-Navigation
*/
abstract class Node_DatabaseChild extends Node
{
/**
- * Returns HTML for hide button displayed infront of the database child node
+ * Returns the type of the item represented by the node.
+ *
+ * @return string type of the item
+ */
+ protected abstract function getItemType();
+
+ /**
+ * Returns HTML for control buttons displayed infront of a node
*
- * @return String HTML for hide button
+ * @return String HTML for control buttons
*/
public function getHtmlForControlButtons()
{
$ret = '';
$cfgRelation = PMA_getRelationsParam();
- if (isset($cfgRelation['navwork']) && $cfgRelation['navwork']) {
+ if ($cfgRelation['navwork']) {
$db = $this->realParent()->real_name;
$item = $this->real_name;
$ret = '<span class="navItemControls">'
@@ -41,12 +50,4 @@ abstract class Node_DatabaseChild extends Node
}
return $ret;
}
-
- /**
- * Returns the type of the item represented by the node.
- *
- * @return string type of the item
- */
- protected abstract function getItemType();
}
-?>
diff --git a/libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php b/libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php
new file mode 100644
index 0000000000..05c9f3e5ba
--- /dev/null
+++ b/libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php
@@ -0,0 +1,47 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Represents container node that carries children of a database
+ *
+ * @package PhpMyAdmin-Navigation
+ */
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+require_once 'libraries/navigation/Nodes/Node_DatabaseChild.class.php';
+
+/**
+ * Represents container node that carries children of a database
+ *
+ * @package PhpMyAdmin-Navigation
+ */
+abstract class Node_DatabaseChild_Container extends Node_DatabaseChild
+{
+ /**
+ * Initialises the class by setting the common variables
+ *
+ * @param string $name An identifier for the new node
+ * @param int $type Type of node, may be one of CONTAINER or OBJECT
+ */
+ public function __construct($name, $type = Node::OBJECT)
+ {
+ parent::__construct($name, $type);
+ if ($GLOBALS['cfg']['NavigationTreeEnableGrouping']) {
+ $this->separator = $GLOBALS['cfg']['NavigationTreeTableSeparator'];
+ $this->separator_depth = (int)(
+ $GLOBALS['cfg']['NavigationTreeTableLevel']
+ );
+ }
+ }
+
+ /**
+ * Returns the type of the item represented by the node.
+ *
+ * @return string type of the item
+ */
+ protected function getItemType()
+ {
+ return 'group';
+ }
+}
diff --git a/libraries/navigation/Nodes/Node_Database_Container.class.php b/libraries/navigation/Nodes/Node_Database_Container.class.php
index 2610558d00..dc7994900a 100644
--- a/libraries/navigation/Nodes/Node_Database_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Database_Container.class.php
@@ -22,8 +22,6 @@ class Node_Database_Container extends Node
* Initialises the class
*
* @param string $name An identifier for the new node
- *
- * @return Node_Database_Container
*/
public function __construct($name)
{
@@ -48,4 +46,3 @@ class Node_Database_Container extends Node
}
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Event.class.php b/libraries/navigation/Nodes/Node_Event.class.php
index d2714aff33..697e81a965 100644
--- a/libraries/navigation/Nodes/Node_Event.class.php
+++ b/libraries/navigation/Nodes/Node_Event.class.php
@@ -25,8 +25,6 @@ class Node_Event extends Node_DatabaseChild
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Event
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -54,4 +52,3 @@ class Node_Event extends Node_DatabaseChild
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Event_Container.class.php b/libraries/navigation/Nodes/Node_Event_Container.class.php
index 3764d23242..0abc9a537d 100644
--- a/libraries/navigation/Nodes/Node_Event_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Event_Container.class.php
@@ -9,17 +9,17 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php';
+
/**
* Represents a container for events nodes in the navigation tree
*
* @package PhpMyAdmin-Navigation
*/
-class Node_Event_Container extends Node
+class Node_Event_Container extends Node_DatabaseChild_Container
{
/**
* Initialises the class
- *
- * @return Node_Event_Container
*/
public function __construct()
{
@@ -51,4 +51,3 @@ class Node_Event_Container extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Function.class.php b/libraries/navigation/Nodes/Node_Function.class.php
index 6f88b409a2..44901155b1 100644
--- a/libraries/navigation/Nodes/Node_Function.class.php
+++ b/libraries/navigation/Nodes/Node_Function.class.php
@@ -25,8 +25,6 @@ class Node_Function extends Node_DatabaseChild
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Function
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -35,10 +33,10 @@ class Node_Function extends Node_DatabaseChild
$this->links = array(
'text' => 'db_routines.php?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;item_name=%1$s&amp;item_type=FUNCTION'
- . '&amp;execute_dialog=1&amp;token=' . $_SESSION[' PMA_token '],
+ . '&amp;edit_item=1&amp;token=' . $_SESSION[' PMA_token '],
'icon' => 'db_routines.php?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;item_name=%1$s&amp;item_type=FUNCTION'
- . '&amp;edit_item=1&amp;token=' . $_SESSION[' PMA_token ']
+ . '&amp;execute_dialog=1&amp;token=' . $_SESSION[' PMA_token ']
);
$this->classes = 'function';
}
@@ -54,4 +52,3 @@ class Node_Function extends Node_DatabaseChild
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Function_Container.class.php b/libraries/navigation/Nodes/Node_Function_Container.class.php
index 7829db442f..c06bd71968 100644
--- a/libraries/navigation/Nodes/Node_Function_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Function_Container.class.php
@@ -9,12 +9,14 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php';
+
/**
* Represents a container for functions nodes in the navigation tree
*
* @package PhpMyAdmin-Navigation
*/
-class Node_Function_Container extends Node
+class Node_Function_Container extends Node_DatabaseChild_Container
{
/**
* Initialises the class
@@ -50,4 +52,3 @@ class Node_Function_Container extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Index.class.php b/libraries/navigation/Nodes/Node_Index.class.php
index 50f60f991f..57f874884c 100644
--- a/libraries/navigation/Nodes/Node_Index.class.php
+++ b/libraries/navigation/Nodes/Node_Index.class.php
@@ -23,8 +23,6 @@ class Node_Index extends Node
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Index
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -42,4 +40,3 @@ class Node_Index extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Index_Container.class.php b/libraries/navigation/Nodes/Node_Index_Container.class.php
index c94569833b..8cb8228a05 100644
--- a/libraries/navigation/Nodes/Node_Index_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Index_Container.class.php
@@ -18,8 +18,6 @@ class Node_Index_Container extends Node
{
/**
* Initialises the class
- *
- * @return Node_Index_Container
*/
public function __construct()
{
@@ -54,4 +52,3 @@ class Node_Index_Container extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Procedure.class.php b/libraries/navigation/Nodes/Node_Procedure.class.php
index 5d402bd54a..dde72447b9 100644
--- a/libraries/navigation/Nodes/Node_Procedure.class.php
+++ b/libraries/navigation/Nodes/Node_Procedure.class.php
@@ -25,8 +25,6 @@ class Node_Procedure extends Node_DatabaseChild
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Procedure
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -35,10 +33,10 @@ class Node_Procedure extends Node_DatabaseChild
$this->links = array(
'text' => 'db_routines.php?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;item_name=%1$s&amp;item_type=PROCEDURE'
- . '&amp;execute_dialog=1&amp;token=' . $_SESSION[' PMA_token '],
+ . '&amp;edit_item=1&amp;token=' . $_SESSION[' PMA_token '],
'icon' => 'db_routines.php?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;item_name=%1$s&amp;item_type=PROCEDURE'
- . '&amp;edit_item=1&amp;token=' . $_SESSION[' PMA_token ']
+ . '&amp;execute_dialog=1&amp;token=' . $_SESSION[' PMA_token ']
);
$this->classes = 'procedure';
}
@@ -54,4 +52,3 @@ class Node_Procedure extends Node_DatabaseChild
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Procedure_Container.class.php b/libraries/navigation/Nodes/Node_Procedure_Container.class.php
index 9678ecab4d..e190b23042 100644
--- a/libraries/navigation/Nodes/Node_Procedure_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Procedure_Container.class.php
@@ -9,17 +9,17 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php';
+
/**
* Represents a container for procedure nodes in the navigation tree
*
* @package PhpMyAdmin-Navigation
*/
-class Node_Procedure_Container extends Node
+class Node_Procedure_Container extends Node_DatabaseChild_Container
{
/**
* Initialises the class
- *
- * @return Node_Procedure_Container
*/
public function __construct()
{
@@ -52,4 +52,3 @@ class Node_Procedure_Container extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Table.class.php b/libraries/navigation/Nodes/Node_Table.class.php
index 10a521a52c..e5b8bd81a3 100644
--- a/libraries/navigation/Nodes/Node_Table.class.php
+++ b/libraries/navigation/Nodes/Node_Table.class.php
@@ -25,43 +25,44 @@ class Node_Table extends Node_DatabaseChild
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Table
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
parent::__construct($name, $type, $is_group);
$this->icon = array();
- $this->_addIcon($GLOBALS['cfg']['NavigationTreeDefaultTabTable']);
- $this->_addIcon($GLOBALS['cfg']['NavigationTreeDefaultTabTable2']);
- switch($GLOBALS['cfg']['DefaultTabTable']) {
- case 'tbl_structure.php':
- $this->title = __('Structure');
- break;
- case 'tbl_select.php':
- $this->title = __('Search');
- break;
- case 'tbl_change.php':
- $this->title = __('Insert');
- break;
- case 'tbl_sql.php':
- $this->title = __('SQL');
- break;
- case 'sql.php':
- $this->title = __('Browse');
- break;
- }
+ $this->_addIcon(
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['NavigationTreeDefaultTabTable'], 'table'
+ )
+ );
+ $this->_addIcon(
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['NavigationTreeDefaultTabTable2'], 'table'
+ )
+ );
+ $title = PMA_Util::getTitleForTarget(
+ $GLOBALS['cfg']['DefaultTabTable']
+ );
+ $this->title = $title;
+
+ $script_name = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ );
$this->links = array(
- 'text' => $GLOBALS['cfg']['DefaultTabTable']
+ 'text' => $script_name
. '?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;table=%1$s'
. '&amp;pos=0&amp;token=' . $_SESSION[' PMA_token '],
'icon' => array(
- $GLOBALS['cfg']['NavigationTreeDefaultTabTable']
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['NavigationTreeDefaultTabTable'], 'table'
+ )
. '?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;table=%1$s&amp;token='
. $_SESSION[' PMA_token '],
- $GLOBALS['cfg']['NavigationTreeDefaultTabTable2']
+ PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['NavigationTreeDefaultTabTable2'], 'table'
+ )
. '?server=' . $GLOBALS['server']
. '&amp;db=%2$s&amp;table=%1$s&amp;token='
. $_SESSION[' PMA_token ']
@@ -180,12 +181,15 @@ class Node_Table extends Node_DatabaseChild
}
$count = 0;
- while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
- if ($pos <= 0 && $count < $maxItems) {
- $retval[] = $arr['Field'];
- $count++;
+ if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
+ while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
+ if ($count < $maxItems) {
+ $retval[] = $arr['Field'];
+ $count++;
+ } else {
+ break;
+ }
}
- $pos--;
}
break;
case 'indexes':
@@ -234,12 +238,15 @@ class Node_Table extends Node_DatabaseChild
}
$count = 0;
- while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
- if ($pos <= 0 && $count < $maxItems) {
- $retval[] = $arr['Trigger'];
- $count++;
+ if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
+ while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
+ if ($count < $maxItems) {
+ $retval[] = $arr['Trigger'];
+ $count++;
+ } else {
+ break;
+ }
}
- $pos--;
}
break;
default:
@@ -291,4 +298,3 @@ class Node_Table extends Node_DatabaseChild
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Table_Container.class.php b/libraries/navigation/Nodes/Node_Table_Container.class.php
index 9d49c290ea..0c65f76c6a 100644
--- a/libraries/navigation/Nodes/Node_Table_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Table_Container.class.php
@@ -9,17 +9,17 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php';
+
/**
* Represents a container for table nodes in the navigation tree
*
* @package PhpMyAdmin-Navigation
*/
-class Node_Table_Container extends Node
+class Node_Table_Container extends Node_DatabaseChild_Container
{
/**
* Initialises the class
- *
- * @return Node_Table_Container
*/
public function __construct()
{
@@ -33,12 +33,6 @@ class Node_Table_Container extends Node
. '&amp;db=%1$s&amp;tbl_type=table'
. '&amp;token=' . $_SESSION[' PMA_token '],
);
- if ($GLOBALS['cfg']['NavigationTreeEnableGrouping']) {
- $this->separator = $GLOBALS['cfg']['NavigationTreeTableSeparator'];
- $this->separator_depth = (int)(
- $GLOBALS['cfg']['NavigationTreeTableLevel']
- );
- }
$this->real_name = 'tables';
$this->classes = 'tableContainer subContainer';
@@ -57,4 +51,3 @@ class Node_Table_Container extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Trigger.class.php b/libraries/navigation/Nodes/Node_Trigger.class.php
index a64a271929..846b86f957 100644
--- a/libraries/navigation/Nodes/Node_Trigger.class.php
+++ b/libraries/navigation/Nodes/Node_Trigger.class.php
@@ -23,8 +23,6 @@ class Node_Trigger extends Node
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_Trigger
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -42,4 +40,3 @@ class Node_Trigger extends Node
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_Trigger_Container.class.php b/libraries/navigation/Nodes/Node_Trigger_Container.class.php
index 2e5370997c..4c06e2b0fb 100644
--- a/libraries/navigation/Nodes/Node_Trigger_Container.class.php
+++ b/libraries/navigation/Nodes/Node_Trigger_Container.class.php
@@ -18,8 +18,6 @@ class Node_Trigger_Container extends Node
{
/**
* Initialises the class
- *
- * @return Node_Trigger_Container
*/
public function __construct()
{
@@ -54,4 +52,3 @@ class Node_Trigger_Container extends Node
}
-?>
diff --git a/libraries/navigation/Nodes/Node_View.class.php b/libraries/navigation/Nodes/Node_View.class.php
index 6ac1c1191f..cd509bf6fb 100644
--- a/libraries/navigation/Nodes/Node_View.class.php
+++ b/libraries/navigation/Nodes/Node_View.class.php
@@ -25,8 +25,6 @@ class Node_View extends Node_DatabaseChild
* @param int $type Type of node, may be one of CONTAINER or OBJECT
* @param bool $is_group Whether this object has been created
* while grouping nodes
- *
- * @return Node_View
*/
public function __construct($name, $type = Node::OBJECT, $is_group = false)
{
@@ -54,4 +52,3 @@ class Node_View extends Node_DatabaseChild
}
}
-?>
diff --git a/libraries/navigation/Nodes/Node_View_Container.class.php b/libraries/navigation/Nodes/Node_View_Container.class.php
index 40881b849d..e03832be22 100644
--- a/libraries/navigation/Nodes/Node_View_Container.class.php
+++ b/libraries/navigation/Nodes/Node_View_Container.class.php
@@ -9,17 +9,17 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/navigation/Nodes/Node_DatabaseChild_Container.class.php';
+
/**
* Represents a container for view nodes in the navigation tree
*
* @package PhpMyAdmin-Navigation
*/
-class Node_View_Container extends Node
+class Node_View_Container extends Node_DatabaseChild_Container
{
/**
* Initialises the class
- *
- * @return Node_View_Container
*/
public function __construct()
{
@@ -33,12 +33,6 @@ class Node_View_Container extends Node
. '&amp;db=%1$s&amp;tbl_type=view'
. '&amp;token=' . $_SESSION[' PMA_token '],
);
- if ($GLOBALS['cfg']['NavigationTreeEnableGrouping']) {
- $this->separator = $GLOBALS['cfg']['NavigationTreeTableSeparator'];
- $this->separator_depth = (int)(
- $GLOBALS['cfg']['NavigationTreeTableLevel']
- );
- }
$this->classes = 'viewContainer subContainer';
$this->real_name = 'views';
@@ -57,4 +51,3 @@ class Node_View_Container extends Node
}
}
-?>
diff --git a/libraries/normalization.lib.php b/libraries/normalization.lib.php
index 0ee65aa190..00208e8b4a 100644
--- a/libraries/normalization.lib.php
+++ b/libraries/normalization.lib.php
@@ -10,6 +10,9 @@
if (! defined('PHPMYADMIN')) {
exit;
}
+
+require_once 'libraries/Template.class.php';
+
/**
* build the html for columns of $colTypeCategory category
* in form of given $listType in a table
@@ -20,7 +23,7 @@ if (! defined('PHPMYADMIN')) {
* |Date and time using the _pgettext() format
* @param string $listType type of list to build, supported dropdown|checkbox
*
- * @return HTML for list of columns in form of given list types
+ * @return string HTML for list of columns in form of given list types
*/
function PMA_getHtmlForColumnsList(
$db, $table, $colTypeCategory='all', $listType='dropdown'
@@ -31,7 +34,7 @@ function PMA_getHtmlForColumnsList(
$columnTypeList = $types[$colTypeCategory];
}
$GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
- $columns = (array) $GLOBALS['dbi']->getColumns(
+ $columns = $GLOBALS['dbi']->getColumns(
$db, $table, null,
true, $GLOBALS['userlink']
);
@@ -69,7 +72,7 @@ function PMA_getHtmlForColumnsList(
* @param string $table current table
* @param array $columnMeta array containing default values for the fields
*
- * @return HTML
+ * @return string HTML
*/
function PMA_getHtmlForCreateNewColumn(
$num_fields, $db, $table, $columnMeta=array()
@@ -78,25 +81,39 @@ function PMA_getHtmlForCreateNewColumn(
$content_cells = array();
$available_mime = array();
$mime_map = array();
- $header_cells = PMA_getHeaderCells(
- true, null,
- $cfgRelation['mimework'], $db, $table
- );
if ($cfgRelation['mimework'] && $GLOBALS['cfg']['BrowseMIME']) {
$mime_map = PMA_getMIME($db, $table);
$available_mime = PMA_getAvailableMIMEtypes();
}
$comments_map = PMA_getComments($db, $table);
for ($columnNumber = 0; $columnNumber < $num_fields; $columnNumber++) {
- $content_cells[$columnNumber] = PMA_getHtmlForColumnAttributes(
- $columnNumber, $columnMeta, '',
- 8, '', null, array(), null, null,
- $comments_map, null, true,
- array(), $cfgRelation,
- isset($available_mime)?$available_mime:array(), $mime_map
+ $content_cells[$columnNumber] = array(
+ 'columnNumber' => $columnNumber,
+ 'columnMeta' => $columnMeta,
+ 'type_upper' => '',
+ 'length_values_input_size' => 8,
+ 'length' => '',
+ 'extracted_columnspec' => array(),
+ 'submit_attribute' => null,
+ 'comments_map' => $comments_map,
+ 'fields_meta' => null,
+ 'is_backup' => true,
+ 'move_columns' => array(),
+ 'cfgRelation' => $cfgRelation,
+ 'available_mime' => isset($available_mime)?$available_mime:array(),
+ 'mime_map' => $mime_map
);
}
- return PMA_getHtmlForTableFieldDefinitions($header_cells, $content_cells);
+
+ return PMA\Template::get('columns_definitions/table_fields_definitions')
+ ->render(
+ array(
+ 'is_backup' => true,
+ 'fields_meta' => null,
+ 'mimework' => $cfgRelation['mimework'],
+ 'content_cells' => $content_cells
+ )
+ );
}
/**
* build the html for step 1.1 of normalization
@@ -106,7 +123,7 @@ function PMA_getHtmlForCreateNewColumn(
* @param string $normalizedTo up to which step normalization will go,
* possible values 1nf|2nf|3nf
*
- * @return HTML for step 1.1
+ * @return string HTML for step 1.1
*/
function PMA_getHtmlFor1NFStep1($db, $table, $normalizedTo)
{
@@ -159,7 +176,7 @@ function PMA_getHtmlFor1NFStep1($db, $table, $normalizedTo)
* @param string $db current database
* @param string $table current table
*
- * @return HTML contents for step 1.2
+ * @return string HTML contents for step 1.2
*/
function PMA_getHtmlContentsFor1NFStep2($db, $table)
{
@@ -193,8 +210,13 @@ function PMA_getHtmlContentsFor1NFStep2($db, $table)
. '<a href="#" id="addNewPrimary">'
. __('+ Add a new primary key column') . '</a>';
}
- $res = array('legendText'=>$legendText, 'headText'=>$headText,
- 'subText'=>$subText, 'hasPrimaryKey'=>$hasPrimaryKey, 'extra'=>$extra);
+ $res = array(
+ 'legendText' => $legendText,
+ 'headText' => $headText,
+ 'subText' => $subText,
+ 'hasPrimaryKey' => $hasPrimaryKey,
+ 'extra' => $extra
+ );
return $res;
}
@@ -204,7 +226,7 @@ function PMA_getHtmlContentsFor1NFStep2($db, $table)
* @param string $db current database
* @param string $table current table
*
- * @return HTML contents for step 1.4
+ * @return string HTML contents for step 1.4
*/
function PMA_getHtmlContentsFor1NFStep4($db, $table)
{
@@ -228,9 +250,11 @@ function PMA_getHtmlContentsFor1NFStep4($db, $table)
. '" onclick="goToFinish1NF();"'
. '/>';
$res = array(
- 'legendText'=>$legendText, 'headText'=>$headText,
- 'subText'=>$subText, 'extra'=>$extra
- );
+ 'legendText' => $legendText,
+ 'headText' => $headText,
+ 'subText' => $subText,
+ 'extra' => $extra
+ );
return $res;
}
@@ -240,7 +264,7 @@ function PMA_getHtmlContentsFor1NFStep4($db, $table)
* @param string $db current database
* @param string $table current table
*
- * @return HTML contents for step 1.3
+ * @return string HTML contents for step 1.3
*/
function PMA_getHtmlContentsFor1NFStep3($db, $table)
{
@@ -272,9 +296,12 @@ function PMA_getHtmlContentsFor1NFStep3($db, $table)
$pk[] = $col->getName();
}
$res = array(
- 'legendText'=>$legendText, 'headText'=>$headText,
- 'subText'=>$subText, 'extra'=>$extra, 'primary_key'=> json_encode($pk)
- );
+ 'legendText' => $legendText,
+ 'headText' => $headText,
+ 'subText' => $subText,
+ 'extra' => $extra,
+ 'primary_key' => json_encode($pk)
+ );
return $res;
}
@@ -284,7 +311,7 @@ function PMA_getHtmlContentsFor1NFStep3($db, $table)
* @param string $db current database
* @param string $table current table
*
- * @return HTML contents for 2NF step 2.1
+ * @return string HTML contents for 2NF step 2.1
*/
function PMA_getHtmlFor2NFstep1($db, $table)
{
@@ -337,7 +364,7 @@ function PMA_getHtmlFor2NFstep1($db, $table)
. 'whose values combined together are sufficient'
. ' to determine the value of the column.'
);
- $cnt=0;
+ $cnt = 0;
foreach ($columns as $column) {
if (!in_array($column, $pk)) {
$cnt++;
@@ -360,8 +387,11 @@ function PMA_getHtmlFor2NFstep1($db, $table)
$extra = '<h3>' . __('Table is already in second normal form.') . '</h3>';
}
$res = array(
- 'legendText'=>$legendText, 'headText'=>$headText,
- 'subText'=>$subText,'extra'=>$extra, 'primary_key'=> $key
+ 'legendText' => $legendText,
+ 'headText' => $headText,
+ 'subText' => $subText,
+ 'extra' => $extra,
+ 'primary_key' => $key
);
return $res;
}
@@ -372,7 +402,7 @@ function PMA_getHtmlFor2NFstep1($db, $table)
* @param array $partialDependencies array containing all the dependencies
* @param string $table current table
*
- * @return HTML
+ * @return string HTML
*/
function PMA_getHtmlForNewTables2NF($partialDependencies,$table)
{
@@ -384,7 +414,7 @@ function PMA_getHtmlForNewTables2NF($partialDependencies,$table)
), htmlspecialchars($table)
) . '</b></p>';
$tableName = $table;
- $i=1;
+ $i = 1;
foreach ($partialDependencies as $key=>$dependents) {
$html .= '<p><input type="text" name="' . htmlspecialchars($key)
. '" value="' . htmlspecialchars($tableName) . '"/>'
@@ -466,8 +496,10 @@ function PMA_createNewTablesFor2NF($partialDependencies, $tablesName, $table, $d
}
}
return array(
- 'legendText'=>__('End of step'), 'headText'=>$headText,
- 'queryError'=>$error, 'extra'=>$message
+ 'legendText' => __('End of step'),
+ 'headText' => $headText,
+ 'queryError' => $error,
+ 'extra' => $message
);
}
@@ -484,7 +516,7 @@ function PMA_createNewTablesFor2NF($partialDependencies, $tablesName, $table, $d
function PMA_getHtmlForNewTables3NF($dependencies, $tables, $db)
{
$html = "";
- $i=1;
+ $i = 1;
$newTables = array();
foreach ($tables as $table=>$arrDependson) {
if (count(array_unique($arrDependson)) == 1) {
@@ -528,7 +560,7 @@ function PMA_getHtmlForNewTables3NF($dependencies, $tables, $db)
}
}
}
- return array('html'=>$html, 'newTables'=>$newTables);
+ return array('html' => $html, 'newTables' => $newTables);
}
/**
@@ -609,8 +641,10 @@ function PMA_createNewTablesFor3NF($newTables, $db)
}
}
return array(
- 'legendText'=>__('End of step'), 'headText'=>$headText,
- 'queryError'=>$error, 'extra'=>$message
+ 'legendText' => __('End of step'),
+ 'headText' => $headText,
+ 'queryError' => $error,
+ 'extra' => $message
);
}
/**
@@ -672,7 +706,7 @@ function PMA_moveRepeatingGroup(
}
}
return array(
- 'queryError'=>$error, 'message'=>$message
+ 'queryError' => $error, 'message' => $message
);
}
@@ -700,8 +734,8 @@ function PMA_getHtmlFor3NFstep1($db, $tables)
. 'Note: A column may have no transitive dependency, '
. 'in that case you don\'t have to select any.'
);
- $cnt=0;
- foreach ($tables as $key=>$table) {
+ $cnt = 0;
+ foreach ($tables as $table) {
$primary = PMA_Index::getPrimary($table, $db);
$primarycols = $primary->getColumns();
$selectTdForm = "";
@@ -710,10 +744,10 @@ function PMA_getHtmlFor3NFstep1($db, $tables)
$pk[] = $col->getName();
}
$GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
- $columns = (array) $GLOBALS['dbi']->getColumnNames(
- $db, $table, $GLOBALS['userlink']
- );
- if (count($columns)-count($pk)<=1) {
+ $columns = (array) $GLOBALS['dbi']->getColumnNames(
+ $db, $table, $GLOBALS['userlink']
+ );
+ if (count($columns) - count($pk) <= 1) {
continue;
}
foreach ($columns as $column) {
@@ -747,15 +781,17 @@ function PMA_getHtmlFor3NFstep1($db, $tables)
$extra = "<h3>" . __("Table is already in Third normal form!") . "</h3>";
}
$res = array(
- 'legendText'=>$legendText, 'headText'=>$headText,
- 'subText'=>$subText,'extra'=>$extra
+ 'legendText' => $legendText,
+ 'headText' => $headText,
+ 'subText' => $subText,
+ 'extra' => $extra
);
return $res;
}
/**
* get html for options to normalize table
*
- * @return HTML
+ * @return string HTML
*/
function PMA_getHtmlForNormalizetable()
{
@@ -768,7 +804,8 @@ function PMA_getHtmlForNormalizetable()
$html_output .= '<fieldset>';
$html_output .= '<legend>'
. __('Improve table structure (Normalization):') . '</legend>';
- $html_output .= '<h3>' . __('Select up to what step you want to normalize') . '</h3>';
+ $html_output .= '<h3>' . __('Select up to what step you want to normalize')
+ . '</h3>';
$choices = array(
'1nf' => __('First step of normalization (1NF)'),
'2nf' => __('Second step of normalization (1NF+2NF)'),
@@ -796,7 +833,7 @@ function PMA_getHtmlForNormalizetable()
* @param string $table current table
* @param string $db current database
*
- * @return HTML containing the list of all the possible partial dependencies
+ * @return string HTML containing the list of all the possible partial dependencies
*/
function PMA_findPartialDependencies($table, $db)
{
diff --git a/libraries/opendocument.lib.php b/libraries/opendocument.lib.php
index e127d45c48..e46a0d683b 100644
--- a/libraries/opendocument.lib.php
+++ b/libraries/opendocument.lib.php
@@ -168,4 +168,3 @@ function PMA_createOpenDocument($mime, $data)
);
return $zipfile -> file();
}
-?>
diff --git a/libraries/operations.lib.php b/libraries/operations.lib.php
index 40b38a17a9..67bcfcf5c9 100644
--- a/libraries/operations.lib.php
+++ b/libraries/operations.lib.php
@@ -11,6 +11,8 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/Partition.class.php';
+
/**
* Get HTML output for database comment
*
@@ -26,10 +28,9 @@ function PMA_getHtmlForDatabaseComment($db)
. '<fieldset>'
. '<legend>';
if (PMA_Util::showIcons('ActionLinksMode')) {
- $html_output .= '<img class="icon ic_b_comment" '
- . 'src="themes/dot.gif" alt="" />';
+ $html_output .= PMA_Util::getImage('b_comment.png') . '&nbsp;';
}
- $html_output .= __('Database comment:');
+ $html_output .= __('Database comment');
$html_output .= '</legend>';
$html_output .= '<input type="text" name="comment" '
. 'class="textfield" size="30"'
@@ -70,13 +71,39 @@ function PMA_getHtmlForRenameDatabase($db)
. '<legend>';
if (PMA_Util::showIcons('ActionLinksMode')) {
- $html_output .= PMA_Util::getImage('b_edit.png');
+ $html_output .= PMA_Util::getImage('b_edit.png') . '&nbsp;';
}
- $html_output .= __('Rename database to:')
+ $html_output .= __('Rename database to')
. '</legend>';
$html_output .= '<input id="new_db_name" type="text" name="newname" '
- . 'size="30" class="textfield" value="" required="required" />'
+ . 'maxlength="64" size="30" class="textfield" required="required" '
+ . 'value="' . htmlspecialchars($db) . '"/>';
+
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['db_priv']) && $GLOBALS['db_priv']
+ && isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_adjust_privileges" checked="checked" />';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_adjust_privileges" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled/>';
+ }
+
+ $html_output .= '<label for="checkbox_adjust_privileges">'
+ . __('Adjust privileges') . PMA_Util::showDocu('faq', 'faq6-39')
+ . '</label><br />';
+ }
+
+ $html_output .= ''
. '</fieldset>'
. '<fieldset class="tblFooters">'
. '<input id="rename_db_input" type="submit" value="' . __('Go') . '" />'
@@ -114,7 +141,7 @@ function PMA_getHtmlForDropDatabaseLink($db)
. '<fieldset class="caution">';
$html_output .= '<legend>';
if (PMA_Util::showIcons('ActionLinksMode')) {
- $html_output .= PMA_Util::getImage('b_deltbl.png');
+ $html_output .= PMA_Util::getImage('b_deltbl.png') . '&nbsp';
}
$html_output .= __('Remove database')
. '</legend>';
@@ -170,15 +197,17 @@ function PMA_getHtmlForCopyDatabase($db)
. '<legend>';
if (PMA_Util::showIcons('ActionLinksMode')) {
- $html_output .= PMA_Util::getImage('b_edit.png');
+ $html_output .= PMA_Util::getImage('b_edit.png') . '&nbsp';
}
- $html_output .= __('Copy database to:')
+ $html_output .= __('Copy database to')
. '</legend>'
- . '<input type="text" name="newname" size="30" '
- . 'class="textfield" value="" required="required" /><br />'
+ . '<input type="text" maxlength="64" name="newname" size="30" '
+ . 'class="textfield" value="' . htmlspecialchars($db) . '" '
+ . 'required="required" /><br />'
. PMA_Util::getRadioFields(
'what', $choices, 'data', true
);
+ $html_output .= '<br />';
$html_output .= '<input type="checkbox" name="create_database_before_copying" '
. 'value="1" id="checkbox_create_database_before_copying"'
. 'checked="checked" />';
@@ -194,9 +223,33 @@ function PMA_getHtmlForCopyDatabase($db)
$html_output .= '<label for="checkbox_auto_increment">'
. __('Add AUTO_INCREMENT value') . '</label><br />';
$html_output .= '<input type="checkbox" name="add_constraints" value="1"'
- . 'id="checkbox_constraints" />';
+ . 'id="checkbox_constraints" checked="checked"/>';
$html_output .= '<label for="checkbox_constraints">'
. __('Add constraints') . '</label><br />';
+ $html_output .= '<br />';
+
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['db_priv']) && $GLOBALS['db_priv']
+ && isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges" checked="checked" />';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled/>';
+ }
+ $html_output .= '<label for="checkbox_privileges">'
+ . __('Adjust privileges') . PMA_Util::showDocu('faq', 'faq6-39')
+ . '</label><br />';
+ }
+
$html_output .= '<input type="checkbox" name="switch_to_new" value="true"'
. 'id="checkbox_switch"'
. ((isset($pma_switch_to_new) && $pma_switch_to_new == 'true')
@@ -235,10 +288,10 @@ function PMA_getHtmlForChangeDatabaseCharset($db, $table)
$html_output .= '<fieldset>' . "\n"
. ' <legend>';
if (PMA_Util::showIcons('ActionLinksMode')) {
- $html_output .= PMA_Util::getImage('s_asci.png');
+ $html_output .= PMA_Util::getImage('s_asci.png') . '&nbsp';
}
$html_output .= '<label for="select_db_collation">' . __('Collation')
- . ':</label>' . "\n"
+ . '</label>' . "\n"
. '</legend>' . "\n"
. PMA_generateCharsetDropdownBox(
PMA_CSDROPDOWN_COLLATION,
@@ -309,7 +362,7 @@ function PMA_createDbBeforeCopy()
// lower_case_table_names=1 `DB` becomes `db`
if (! PMA_DRIZZLE) {
$lowerCaseTableNames = $GLOBALS['dbi']->fetchValue(
- 'SHOW VARIABLES LIKE "lower_case_table_names"', 0, 1
+ 'SELECT @@lower_case_table_names'
);
if ($lowerCaseTableNames === '1') {
$_REQUEST['newname'] = /*overload*/mb_strtolower(
@@ -363,7 +416,7 @@ function PMA_getViewsAndCreateSqlViewStandIn(
// to be able to rename a db containing views,
// first all the views are collected and a stand-in is created
// the real views are created after the tables
- if (PMA_Table::isView($db, $each_table)) {
+ if ($GLOBALS['dbi']->getTable($db, $each_table)->isView()) {
// If view exists, and 'add drop view' is selected: Drop it!
if ($_REQUEST['what'] != 'nocopy'
@@ -405,7 +458,7 @@ function PMA_copyTables($tables_full, $move, $db)
$sqlContraints = array();
foreach ($tables_full as $each_table => $tmp) {
// skip the views; we have created stand-in definitions
- if (PMA_Table::isView($db, $each_table)) {
+ if ($GLOBALS['dbi']->getTable($db, $each_table)->isView()) {
continue;
}
@@ -414,7 +467,7 @@ function PMA_copyTables($tables_full, $move, $db)
// do not copy the data from a Merge table
// note: on the calling FORM, 'data' means 'structure and data'
- if (PMA_Table::isMerge($db, $each_table)) {
+ if ($GLOBALS['dbi']->getTable($db, $each_table)->isMerge()) {
if ($this_what == 'data') {
$this_what = 'structure';
}
@@ -524,6 +577,165 @@ function PMA_handleTheViews($views, $move, $db)
}
/**
+ * Adjust the privileges after Renaming the db
+ *
+ * @param string $oldDb Database name before renaming
+ * @param string $newname New Database name requested
+ *
+ * @return void
+ */
+function PMA_AdjustPrivileges_moveDB($oldDb, $newname)
+{
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['db_priv']) && $GLOBALS['db_priv']
+ && isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $GLOBALS['dbi']->selectDb('mysql');
+
+ // For Db specific privileges
+ $query_db_specific = 'UPDATE ' . PMA_Util::backquote('db')
+ . 'SET Db = "' . $newname
+ . '" where Db = "' . $oldDb . '";';
+ $GLOBALS['dbi']->query($query_db_specific);
+
+ // For table specific privileges
+ $query_table_specific = 'UPDATE ' . PMA_Util::backquote('tables_priv')
+ . 'SET Db = "' . $newname
+ . '" where Db = "' . $oldDb . '";';
+ $GLOBALS['dbi']->query($query_table_specific);
+
+ // For column specific privileges
+ $query_col_specific = 'UPDATE ' . PMA_Util::backquote('columns_priv')
+ . 'SET Db = "' . $newname
+ . '" where Db = "' . $oldDb . '";';
+ $GLOBALS['dbi']->query($query_col_specific);
+
+ // For procedures specific privileges
+ $query_proc_specific = 'UPDATE ' . PMA_Util::backquote('procs_priv')
+ . 'SET Db = "' . $newname
+ . '" where Db = "' . $oldDb . '";';
+ $GLOBALS['dbi']->query($query_proc_specific);
+
+ // Finally FLUSH the new privileges
+ $flush_query = "FLUSH PRIVILEGES;";
+ $GLOBALS['dbi']->query($flush_query);
+ }
+ }
+}
+
+/**
+ * Adjust the privileges after Copying the db
+ *
+ * @param string $oldDb Database name before copying
+ * @param string $newname New Database name requested
+ *
+ * @return void
+ */
+function PMA_AdjustPrivileges_copyDB($oldDb, $newname)
+{
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['db_priv']) && $GLOBALS['db_priv']
+ && isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $GLOBALS['dbi']->selectDb('mysql');
+
+ $query_db_specific_old = 'SELECT * FROM '
+ . PMA_Util::backquote('db') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_db = $GLOBALS['dbi']->fetchResult($query_db_specific_old, 0);
+
+ foreach ($old_privs_db as $old_priv) {
+ $newDb_db_privs_query = 'INSERT INTO ' . PMA_Util::backquote('db')
+ . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '", "'
+ . $old_priv[7] . '", "' . $old_priv[8] . '", "' . $old_priv[9]
+ . '", "' . $old_priv[10] . '", "' . $old_priv[11] . '", "'
+ . $old_priv[12] . '", "' . $old_priv[13] . '", "' . $old_priv[14]
+ . '", "' . $old_priv[15] . '", "' . $old_priv[16] . '", "'
+ . $old_priv[17] . '", "' . $old_priv[18] . '", "' . $old_priv[19]
+ . '", "' . $old_priv[20] . '", "' . $old_priv[21] . '");';
+
+ $GLOBALS['dbi']->query($newDb_db_privs_query);
+ }
+
+ // For Table Specific privileges
+ $query_table_specific_old = 'SELECT * FROM '
+ . PMA_Util::backquote('tables_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_table = $GLOBALS['dbi']->fetchResult(
+ $query_table_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_table as $old_priv) {
+ $newDb_table_privs_query = 'INSERT INTO ' . PMA_Util::backquote(
+ 'tables_priv'
+ ) . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '", "'
+ . $old_priv[7] . '");';
+
+ $GLOBALS['dbi']->query($newDb_table_privs_query);
+ }
+
+ // For Column Specific privileges
+ $query_col_specific_old = 'SELECT * FROM '
+ . PMA_Util::backquote('columns_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_col = $GLOBALS['dbi']->fetchResult(
+ $query_col_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_col as $old_priv) {
+ $newDb_col_privs_query = 'INSERT INTO ' . PMA_Util::backquote(
+ 'columns_priv'
+ ) . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '");';
+
+ $GLOBALS['dbi']->query($newDb_col_privs_query);
+ }
+
+ // For Procedure Specific privileges
+ $query_proc_specific_old = 'SELECT * FROM '
+ . PMA_Util::backquote('procs_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_proc = $GLOBALS['dbi']->fetchResult(
+ $query_proc_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_proc as $old_priv) {
+ $newDb_proc_privs_query = 'INSERT INTO ' . PMA_Util::backquote(
+ 'procs_priv'
+ ) . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '", "'
+ . $old_priv[7] . '");';
+
+ $GLOBALS['dbi']->query($newDb_proc_privs_query);
+ }
+
+ // Finally FLUSH the new privileges
+ $flush_query = "FLUSH PRIVILEGES;";
+ $GLOBALS['dbi']->query($flush_query);
+ }
+ }
+}
+
+/**
* Create all accumulated constraints
*
* @param array $sqlConstratints array of sql constraints for the database
@@ -621,7 +833,7 @@ function PMA_getHtmlForMoveTable()
. '<input type="hidden" name="what" value="data" />'
. '<fieldset id="fieldset_table_rename">';
- $html_output .= '<legend>' . __('Move table to (database<b>.</b>table):')
+ $html_output .= '<legend>' . __('Move table to (database<b>.</b>table)')
. '</legend>';
if (count($GLOBALS['pma']->databases) > $GLOBALS['cfg']['MaxDbList']) {
@@ -635,7 +847,7 @@ function PMA_getHtmlForMoveTable()
}
$html_output .= '&nbsp;<strong>.</strong>&nbsp;';
$html_output .= '<input class="halfWidth" type="text" size="20" name="new_name"'
- . ' required="required" '
+ . ' maxlength="64" required="required" '
. 'value="' . htmlspecialchars($GLOBALS['table']) . '" /><br />';
// starting with MySQL 5.0.24, SHOW CREATE TABLE includes the AUTO_INCREMENT
@@ -645,10 +857,30 @@ function PMA_getHtmlForMoveTable()
. 'value="1" id="checkbox_auto_increment_mv" checked="checked" />'
. '<label for="checkbox_auto_increment_mv">'
. __('Add AUTO_INCREMENT value')
- . '</label><br />'
- . '</fieldset>';
+ . '</label><br />';
- $html_output .= '<fieldset class="tblFooters">'
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges_tables_move" '
+ . 'checked="checked" />';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges_tables_move" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled/>';
+ }
+ $html_output .= '<label for="checkbox_privileges_tables_move">'
+ . __('Adjust privileges') . PMA_Util::showDocu('faq', 'faq6-39')
+ . '</label><br />';
+ }
+
+ $html_output .= '</fieldset><fieldset class="tblFooters">'
. '<input type="submit" name="submit_move" value="' . __('Go') . '" />'
. '</fieldset>'
. '</form>'
@@ -665,7 +897,7 @@ function PMA_getHtmlForMoveTable()
* @param string $tbl_storage_engine table storage engine
* @param boolean $is_myisam_or_aria whether MYISAM | ARIA or not
* @param boolean $is_isam whether ISAM or not
- * @param array $pack_keys pack keys
+ * @param string $pack_keys pack keys
* @param string $auto_increment value of auto increment
* @param string $delay_key_write delay key write
* @param string $transactional value of transactional
@@ -707,6 +939,103 @@ function PMA_getTableOptionDiv($comment, $tbl_collation, $tbl_storage_engine,
}
/**
+ * Get HTML for the rename table part of table options
+ *
+ * @return string $html_output
+ */
+function PMA_getHtmlForRenameTable()
+{
+ $html_output = '<tr><td class="vmiddle">' . __('Rename table to') . '</td>'
+ . '<td>'
+ . '<input type="text" size="20" name="new_name" maxlength="64" '
+ . 'value="' . htmlspecialchars($GLOBALS['table'])
+ . '" required="required" />'
+ . '</td></tr>'
+ . '<tr><td></td><td>';
+
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges_table_options" '
+ . 'checked="checked" />';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges_table_options" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled/>';
+ }
+ $html_output .= '<label for="checkbox_privileges_table_options">'
+ . __('Adjust privileges') . '&nbsp;'
+ . PMA_Util::showDocu('faq', 'faq6-39') . '</label>';
+ }
+
+ $html_output .= '</td></tr>';
+ return $html_output;
+}
+
+/**
+ * Get HTML for the table comments part of table options
+ *
+ * @param string $current_value of the table comments
+ *
+ * @return string $html_output
+ */
+function PMA_getHtmlForTableComments($current_value)
+{
+ $commentLength = PMA_MYSQL_INT_VERSION >= 50503 ? 2048 : 60;
+ $html_output = '<tr><td class="vmiddle">' . __('Table comments') . '</td>'
+ . '<td><input type="text" name="comment" '
+ . 'maxlength="' . $commentLength . '" size="30"'
+ . 'value="' . htmlspecialchars($current_value) . '" />'
+ . '<input type="hidden" name="prev_comment" value="'
+ . htmlspecialchars($current_value) . '" />'
+ . '</td>'
+ . '</tr>';
+
+ return $html_output;
+}
+
+/**
+ * Get HTML for the PACK KEYS part of table options
+ *
+ * @param string $current_value of the pack keys option
+ *
+ * @return string $html_output
+ */
+function PMA_getHtmlForPackKeys($current_value)
+{
+ $html_output = '<tr>'
+ . '<td class="vmiddle"><label for="new_pack_keys">PACK_KEYS</label></td>'
+ . '<td><select name="new_pack_keys" id="new_pack_keys">';
+
+ $html_output .= '<option value="DEFAULT"';
+ if ($current_value == 'DEFAULT') {
+ $html_output .= 'selected="selected"';
+ }
+ $html_output .= '>DEFAULT</option>
+ <option value="0"';
+ if ($current_value == '0') {
+ $html_output .= 'selected="selected"';
+ }
+ $html_output .= '>0</option>
+ <option value="1" ';
+ if ($current_value == '1') {
+ $html_output .= 'selected="selected"';
+ }
+ $html_output .= '>1</option>'
+ . '</select>'
+ . '</td>'
+ . '</tr>';
+
+ return $html_output;
+}
+
+/**
* Get HTML fieldset for Table option, it contains HTML table for options
*
* @param string $comment Comment
@@ -714,7 +1043,7 @@ function PMA_getTableOptionDiv($comment, $tbl_collation, $tbl_storage_engine,
* @param string $tbl_storage_engine table storage engine
* @param boolean $is_myisam_or_aria whether MYISAM | ARIA or not
* @param boolean $is_isam whether ISAM or not
- * @param array $pack_keys pack keys
+ * @param string $pack_keys pack keys
* @param string $delay_key_write delay key write
* @param string $auto_increment value of auto increment
* @param string $transactional value of transactional
@@ -735,29 +1064,12 @@ function PMA_getTableOptionFieldset($comment, $tbl_collation,
. '<legend>' . __('Table options') . '</legend>';
$html_output .= '<table>';
- //Change table name
- $html_output .= '<tr><td>' . __('Rename table to') . '</td>'
- . '<td>'
- . '<input type="text" size="20" name="new_name" '
- . 'value="' . htmlspecialchars($GLOBALS['table'])
- . '" required="required" />'
- . '</td>'
- . '</tr>';
-
- //Table comments
- $commentLength = PMA_MYSQL_INT_VERSION >= 50503 ? 2048 : 60;
- $html_output .= '<tr><td>' . __('Table comments') . '</td>'
- . '<td><input type="text" name="comment"'
- . ' maxlength="' . $commentLength . '" size="30"'
- . 'value="' . htmlspecialchars($comment) . '" />'
- . '<input type="hidden" name="prev_comment" value="'
- . htmlspecialchars($comment) . '" />'
- . '</td>'
- . '</tr>';
+ $html_output .= PMA_getHtmlForRenameTable();
+ $html_output .= PMA_getHtmlForTableComments($comment);
//Storage engine
- $html_output .= '<tr><td>' . __('Storage Engine')
- . PMA_Util::showMySQLDocu('Storage_engines')
+ $html_output .= '<tr><td class="vmiddle">' . __('Storage Engine')
+ . '&nbsp;' . PMA_Util::showMySQLDocu('Storage_engines')
. '</td>'
. '<td>'
. PMA_StorageEngine::getHtmlSelect(
@@ -767,7 +1079,7 @@ function PMA_getTableOptionFieldset($comment, $tbl_collation,
. '</tr>';
//Table character set
- $html_output .= '<tr><td>' . __('Collation') . '</td>'
+ $html_output .= '<tr><td class="vmiddle">' . __('Collation') . '</td>'
. '<td>'
. PMA_generateCharsetDropdownBox(
PMA_CSDROPDOWN_COLLATION,
@@ -776,29 +1088,17 @@ function PMA_getTableOptionFieldset($comment, $tbl_collation,
. '</td>'
. '</tr>';
- if ($is_myisam_or_aria || $is_isam) {
- $html_output .= '<tr>'
- . '<td><label for="new_pack_keys">PACK_KEYS</label></td>'
- . '<td><select name="new_pack_keys" id="new_pack_keys">';
+ // Change all Column collations
+ $html_output .= '<tr><td></td><td>'
+ . '<input type="checkbox" name="change_all_collations" value="1" '
+ . 'id="checkbox_change_all_collations" />'
+ . '<label for="checkbox_change_all_collations">'
+ . __('Change all column collations')
+ . '</label>'
+ . '</td></tr>';
- $html_output .= '<option value="DEFAULT"';
- if ($pack_keys == 'DEFAULT') {
- $html_output .= 'selected="selected"';
- }
- $html_output .= '>DEFAULT</option>
- <option value="0"';
- if ($pack_keys == '0') {
- $html_output .= 'selected="selected"';
- }
- $html_output .= '>0</option>
- <option value="1" ';
- if ($pack_keys == '1') {
- $html_output .= 'selected="selected"';
- }
- $html_output .= '>1</option>'
- . '</select>'
- . '</td>'
- . '</tr>';
+ if ($is_myisam_or_aria || $is_isam) {
+ $html_output .= PMA_getHtmlForPackKeys($pack_keys);
} // end if (MYISAM|ISAM)
if ($is_myisam_or_aria) {
@@ -832,7 +1132,7 @@ function PMA_getTableOptionFieldset($comment, $tbl_collation,
if (/*overload*/mb_strlen($auto_increment) > 0
&& ($is_myisam_or_aria || $is_innodb || $is_pbxt)
) {
- $html_output .= '<tr><td>'
+ $html_output .= '<tr><td class="vmiddle">'
. '<label for="auto_increment_opt">AUTO_INCREMENT</label></td>'
. '<td><input type="number" name="new_auto_increment" '
. 'id="auto_increment_opt"'
@@ -851,7 +1151,7 @@ function PMA_getTableOptionFieldset($comment, $tbl_collation,
if (isset($possible_row_formats[$tbl_storage_engine])) {
$current_row_format
= /*overload*/mb_strtoupper($GLOBALS['showtable']['Row_format']);
- $html_output .= '<tr><td>'
+ $html_output .= '<tr><td class="vmiddle">'
. '<label for="new_row_format">ROW_FORMAT</label></td>'
. '<td>';
$html_output .= PMA_Util::getDropdown(
@@ -879,11 +1179,14 @@ function PMA_getTableOptionFieldset($comment, $tbl_collation,
function PMA_getHtmlForTableRow($attribute, $label, $val)
{
return '<tr>'
- . '<td><label for="' . $attribute . '">' . $label . '</label></td>'
- . '<td><input type="checkbox" name="' . $attribute . '"'
- . ' id="' . $attribute . '"'
- . ' value="1"'
- . ((!empty($val) && $val == 1) ? ' checked="checked"' : '') . '/></td>'
+ . '<td class="vmiddle">'
+ . '<label for="' . $attribute . '">' . $label . '</label>'
+ . '</td>'
+ . '<td>'
+ . '<input type="checkbox" name="' . $attribute . '" id="' . $attribute . '"'
+ . ' value="1"' . ((!empty($val) && $val == 1) ? ' checked="checked"' : '')
+ . '/>'
+ . '</td>'
. '</tr>';
}
@@ -922,6 +1225,7 @@ function PMA_getPossibleRowFormat()
)
);
+ /** @var PMA_StorageEngine_Innodb $innodbEnginePlugin */
$innodbEnginePlugin = PMA_StorageEngine::getEngine('innodb');
$innodbPluginVersion = $innodbEnginePlugin->getInnodbPluginVersion();
if (!empty($innodbPluginVersion)) {
@@ -957,7 +1261,7 @@ function PMA_getHtmlForCopytable()
$html_output .= '<fieldset>';
$html_output .= '<legend>'
- . __('Copy table to (database<b>.</b>table):') . '</legend>';
+ . __('Copy table to (database<b>.</b>table)') . '</legend>';
if (count($GLOBALS['pma']->databases) > $GLOBALS['cfg']['MaxDbList']) {
$html_output .= '<input class="halfWidth" type="text" maxlength="100" '
@@ -970,17 +1274,19 @@ function PMA_getHtmlForCopytable()
}
$html_output .= '&nbsp;<strong>.</strong>&nbsp;';
$html_output .= '<input class="halfWidth" type="text" required="required" '
- . 'size="20" name="new_name" '
+ . 'size="20" name="new_name" maxlength="64" '
. 'value="' . htmlspecialchars($GLOBALS['table']) . '"/><br />';
$choices = array(
- 'structure' => __('Structure only'),
- 'data' => __('Structure and data'),
- 'dataonly' => __('Data only'));
+ 'structure' => __('Structure only'),
+ 'data' => __('Structure and data'),
+ 'dataonly' => __('Data only')
+ );
$html_output .= PMA_Util::getRadioFields(
'what', $choices, 'data', true
);
+ $html_output .= '<br />';
$html_output .= '<input type="checkbox" name="drop_if_exists" '
. 'value="true" id="checkbox_drop" />'
@@ -995,11 +1301,33 @@ function PMA_getHtmlForCopytable()
// foreign keys
if (PMA_getForeigners($GLOBALS['db'], $GLOBALS['table'], '', 'foreign')) {
$html_output .= '<input type="checkbox" name="add_constraints" '
- . 'value="1" id="checkbox_constraints" />';
+ . 'value="1" id="checkbox_constraints" checked="checked"/>';
$html_output .= '<label for="checkbox_constraints">'
. __('Add constraints') . '</label><br />';
} // endif
+ $html_output .= '<br />';
+
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_adjust_privileges" checked="checked" />';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_adjust_privileges" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled/>';
+ }
+ $html_output .= '<label for="checkbox_adjust_privileges">'
+ . __('Adjust privileges') . PMA_Util::showDocu('faq', 'faq6-39')
+ . '</label><br />';
+ }
+
if (isset($_COOKIE['pma_switch_to_new'])
&& $_COOKIE['pma_switch_to_new'] == 'true'
) {
@@ -1069,76 +1397,67 @@ function PMA_getListofMaintainActionLink($is_myisam_or_aria,
) {
$html_output = '';
- if ($is_myisam_or_aria || $is_innodb || $is_berkeleydb) {
- if ($is_myisam_or_aria || $is_innodb) {
- $params = array(
- 'sql_query' => 'CHECK TABLE '
- . PMA_Util::backquote($GLOBALS['table']),
- 'table_maintenance' => 'Go',
- );
- $html_output .= PMA_getMaintainActionlink(
- __('Check table'),
- $params,
- $url_params,
- 'CHECK_TABLE'
- );
- }
- if ($is_innodb) {
- $params = array(
- 'sql_query' => 'ALTER TABLE '
- . PMA_Util::backquote($GLOBALS['table'])
- . ' ENGINE = InnoDB;'
- );
- $html_output .= PMA_getMaintainActionlink(
- __('Defragment table'),
- $params,
- $url_params,
- 'InnoDB_File_Defragmenting'
- );
- }
- if ($is_innodb || $is_myisam_or_aria || $is_berkeleydb) {
- $params = array(
- 'sql_query' => 'ANALYZE TABLE '
- . PMA_Util::backquote($GLOBALS['table']),
- 'table_maintenance' => 'Go',
- );
- $html_output .= PMA_getMaintainActionlink(
- __('Analyze table'),
- $params,
- $url_params,
- 'ANALYZE_TABLE'
- );
- }
- if ($is_myisam_or_aria && !PMA_DRIZZLE) {
- $params = array(
- 'sql_query' => 'REPAIR TABLE '
- . PMA_Util::backquote($GLOBALS['table']),
- 'table_maintenance' => 'Go',
- );
- $html_output .= PMA_getMaintainActionlink(
- __('Repair table'),
- $params,
- $url_params,
- 'REPAIR_TABLE'
- );
- }
- if (($is_myisam_or_aria || $is_innodb || $is_berkeleydb)
- && !PMA_DRIZZLE
- ) {
- $params = array(
- 'sql_query' => 'OPTIMIZE TABLE '
- . PMA_Util::backquote($GLOBALS['table']),
- 'table_maintenance' => 'Go',
- );
- $html_output .= PMA_getMaintainActionlink(
- __('Optimize table'),
- $params,
- $url_params,
- 'OPTIMIZE_TABLE'
- );
- }
- } // end MYISAM or BERKELEYDB case
+ // analyze table
+ if ($is_innodb || $is_myisam_or_aria || $is_berkeleydb) {
+ $params = array(
+ 'sql_query' => 'ANALYZE TABLE '
+ . PMA_Util::backquote($GLOBALS['table']),
+ 'table_maintenance' => 'Go',
+ );
+ $html_output .= PMA_getMaintainActionlink(
+ __('Analyze table'),
+ $params,
+ $url_params,
+ 'ANALYZE_TABLE'
+ );
+ }
+ // check table
+ if ($is_myisam_or_aria || $is_innodb) {
+ $params = array(
+ 'sql_query' => 'CHECK TABLE '
+ . PMA_Util::backquote($GLOBALS['table']),
+ 'table_maintenance' => 'Go',
+ );
+ $html_output .= PMA_getMaintainActionlink(
+ __('Check table'),
+ $params,
+ $url_params,
+ 'CHECK_TABLE'
+ );
+ }
+
+ // checksum table
+ if (! PMA_DRIZZLE) {
+ $params = array(
+ 'sql_query' => 'CHECKSUM TABLE '
+ . PMA_Util::backquote($GLOBALS['table']),
+ 'table_maintenance' => 'Go',
+ );
+ $html_output .= PMA_getMaintainActionlink(
+ __('Checksum table'),
+ $params,
+ $url_params,
+ 'CHECKSUM_TABLE'
+ );
+ }
+
+ // defragment table
+ if ($is_innodb) {
+ $params = array(
+ 'sql_query' => 'ALTER TABLE '
+ . PMA_Util::backquote($GLOBALS['table'])
+ . ' ENGINE = InnoDB;'
+ );
+ $html_output .= PMA_getMaintainActionlink(
+ __('Defragment table'),
+ $params,
+ $url_params,
+ 'InnoDB_File_Defragmenting'
+ );
+ }
+
+ // flush table
$params = array(
'sql_query' => 'FLUSH TABLE '
. PMA_Util::backquote($GLOBALS['table']),
@@ -1148,7 +1467,6 @@ function PMA_getListofMaintainActionLink($is_myisam_or_aria,
),
'reload' => 1,
);
-
$html_output .= PMA_getMaintainActionlink(
__('Flush the table (FLUSH)'),
$params,
@@ -1156,6 +1474,38 @@ function PMA_getListofMaintainActionLink($is_myisam_or_aria,
'FLUSH'
);
+ // optimize table
+ if (($is_myisam_or_aria || $is_innodb || $is_berkeleydb)
+ && !PMA_DRIZZLE
+ ) {
+ $params = array(
+ 'sql_query' => 'OPTIMIZE TABLE '
+ . PMA_Util::backquote($GLOBALS['table']),
+ 'table_maintenance' => 'Go',
+ );
+ $html_output .= PMA_getMaintainActionlink(
+ __('Optimize table'),
+ $params,
+ $url_params,
+ 'OPTIMIZE_TABLE'
+ );
+ }
+
+ // repair table
+ if ($is_myisam_or_aria && !PMA_DRIZZLE) {
+ $params = array(
+ 'sql_query' => 'REPAIR TABLE '
+ . PMA_Util::backquote($GLOBALS['table']),
+ 'table_maintenance' => 'Go',
+ );
+ $html_output .= PMA_getMaintainActionlink(
+ __('Repair table'),
+ $params,
+ $url_params,
+ 'REPAIR_TABLE'
+ );
+ }
+
return $html_output;
}
@@ -1207,7 +1557,7 @@ function PMA_getHtmlForDeleteDataOrTable(
'truncate_tbl_anchor'
);
}
- if (!empty ($dropTableUrlParams)) {
+ if (!empty($dropTableUrlParams)) {
$html_output .= PMA_getDeleteDataOrTablelink(
$dropTableUrlParams,
'DROP_TABLE',
@@ -1255,28 +1605,49 @@ function PMA_getHtmlForPartitionMaintenance($partition_names, $url_params)
'CHECK' => __('Check'),
'OPTIMIZE' => __('Optimize'),
'REBUILD' => __('Rebuild'),
- 'REPAIR' => __('Repair')
+ 'REPAIR' => __('Repair'),
+ 'TRUNCATE' => __('Truncate')
+ );
+
+ $partition_method = PMA_Partition::getPartitionMethod(
+ $GLOBALS['db'], $GLOBALS['table']
);
+ // add COALESCE or DROP option to choices array depeding on Partition method
+ if ($partition_method == 'RANGE' || $partition_method == 'LIST') {
+ $choices['DROP'] = __('Drop');
+ } else {
+ $choices['COALESCE'] = __('Coalesce');
+ }
$html_output = '<div class="operations_half_width">'
- . '<form method="post" action="tbl_operations.php">'
+ . '<form id="partitionsForm" class="ajax" '
+ . 'method="post" action="tbl_operations.php" >'
. PMA_URL_getHiddenInputs($GLOBALS['db'], $GLOBALS['table'])
. '<fieldset>'
- . '<legend>' . __('Partition maintenance') . '</legend>';
+ . '<legend>'
+ . __('Partition maintenance')
+ . PMA_Util::showMySQLDocu('partitioning_maintenance')
+ . '</legend>';
- $html_select = '<select name="partition_name">' . "\n";
+ $html_select = '<select id="partition_name" name="partition_name[]"'
+ . ' multiple="multiple" required="required">' . "\n";
+ $first = true;
foreach ($partition_names as $one_partition) {
$one_partition = htmlspecialchars($one_partition);
- $html_select .= '<option value="' . $one_partition . '">'
- . $one_partition . '</option>' . "\n";
+ $html_select .= '<option value="' . $one_partition . '"';
+ if ($first) {
+ $html_select .= ' selected="selected"';
+ $first = false;
+ }
+ $html_select .= '>' . $one_partition . '</option>' . "\n";
}
$html_select .= '</select>' . "\n";
$html_output .= sprintf(__('Partition %s'), $html_select);
+ $html_output .= '<div class="clearfloat" />';
$html_output .= PMA_Util::getRadioFields(
- 'partition_operation', $choices, '', false
+ 'partition_operation', $choices, 'ANALYZE', false, true, 'floatleft'
);
- $html_output .= PMA_Util::showMySQLDocu('partitioning_maintenance');
$this_url_params = array_merge(
$url_params,
array(
@@ -1285,7 +1656,9 @@ function PMA_getHtmlForPartitionMaintenance($partition_names, $url_params)
. ' REMOVE PARTITIONING;'
)
);
- $html_output .= '<br /><a href="sql.php'
+ $html_output .= '<div class="clearfloat" /><br />';
+
+ $html_output .= '<a href="sql.php'
. PMA_URL_getCommon($this_url_params) . '">'
. __('Remove partitioning') . '</a>';
@@ -1561,13 +1934,148 @@ function PMA_getQueryAndResultForPartition()
$sql_query = 'ALTER TABLE '
. PMA_Util::backquote($GLOBALS['table']) . ' '
. $_REQUEST['partition_operation']
- . ' PARTITION '
- . $_REQUEST['partition_name'] . ';';
+ . ' PARTITION ';
+
+ if ($_REQUEST['partition_operation'] == 'COALESCE') {
+ $sql_query .= count($_REQUEST['partition_name']);
+ } else {
+ $sql_query .= implode(', ', $_REQUEST['partition_name']) . ';';
+ }
+
$result = $GLOBALS['dbi']->query($sql_query);
return array($sql_query, $result);
}
+/**
+ * Adjust the privileges after renaming/moving a table
+ *
+ * @param string $oldDb Database name before table renaming/moving table
+ * @param string $oldTable Table name before table renaming/moving table
+ * @param string $newDb Database name after table renaming/ moving table
+ * @param string $newTable Table name after table renaming/moving table
+ *
+ * @return void
+ */
+function PMA_AdjustPrivileges_renameOrMoveTable($oldDb, $oldTable, $newDb, $newTable)
+{
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $GLOBALS['dbi']->selectDb('mysql');
+
+ // For table specific privileges
+ $query_table_specific = 'UPDATE ' . PMA_Util::backquote('tables_priv')
+ . 'SET Db = "' . $newDb . '", Table_name = "' . $newTable
+ . '" where Db = "' . $oldDb . '" AND Table_name = "' . $oldTable
+ . '";';
+ $GLOBALS['dbi']->query($query_table_specific);
+
+ // For column specific privileges
+ $query_col_specific = 'UPDATE ' . PMA_Util::backquote('columns_priv')
+ . 'SET Db = "' . $newDb . '", Table_name = "' . $newTable
+ . '" where Db = "' . $oldDb . '" AND Table_name = "' . $oldTable
+ . '";';
+ $GLOBALS['dbi']->query($query_col_specific);
+
+ // Finally FLUSH the new privileges
+ $flush_query = "FLUSH PRIVILEGES;";
+ $GLOBALS['dbi']->query($flush_query);
+ }
+ }
+}
+
+/**
+ * Adjust the privileges after copying a table
+ *
+ * @param string $oldDb Database name before table copying
+ * @param string $oldTable Table name before table copying
+ * @param string $newDb Database name after table copying
+ * @param string $newTable Table name after table copying
+ *
+ * @return void
+ */
+function PMA_AdjustPrivileges_copyTable($oldDb, $oldTable, $newDb, $newTable)
+{
+ if (! PMA_DRIZZLE) {
+ if (isset($GLOBALS['table_priv']) && $GLOBALS['table_priv']
+ && isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $GLOBALS['dbi']->selectDb('mysql');
+
+ // For Table Specific privileges
+ $query_table_specific_old = 'SELECT * FROM '
+ . PMA_Util::backquote('tables_priv') . ' where '
+ . 'Db = "' . $oldDb . '" AND Table_name = "' . $oldTable . '";';
+
+ $old_privs_table = $GLOBALS['dbi']->fetchResult(
+ $query_table_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_table as $old_priv) {
+ $newDb_table_privs_query = 'INSERT INTO '
+ . PMA_Util::backquote('tables_priv') . ' VALUES("'
+ . $old_priv[0] . '", "' . $newDb . '", "' . $old_priv[2] . '", "'
+ . $newTable . '", "' . $old_priv[4] . '", "' . $old_priv[5]
+ . '", "' . $old_priv[6] . '", "' . $old_priv[7] . '");';
+
+ $GLOBALS['dbi']->query($newDb_table_privs_query);
+ }
+
+ // For Column Specific privileges
+ $query_col_specific_old = 'SELECT * FROM '
+ . PMA_Util::backquote('columns_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '" AND Table_name = "' . $oldTable . '";';
+
+ $old_privs_col = $GLOBALS['dbi']->fetchResult(
+ $query_col_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_col as $old_priv) {
+ $newDb_col_privs_query = 'INSERT INTO '
+ . PMA_Util::backquote('columns_priv') . ' VALUES("'
+ . $old_priv[0] . '", "' . $newDb . '", "' . $old_priv[2] . '", "'
+ . $newTable . '", "' . $old_priv[4] . '", "' . $old_priv[5]
+ . '", "' . $old_priv[6] . '");';
+
+ $GLOBALS['dbi']->query($newDb_col_privs_query);
+ }
+
+ // Finally FLUSH the new privileges
+ $flush_query = "FLUSH PRIVILEGES;";
+ $GLOBALS['dbi']->query($flush_query);
+ }
+ }
+}
+
+/**
+ * Change all collations and character sets of all columns in table
+ *
+ * @param string $db Database name
+ * @param string $table Table name
+ * @param string $tbl_collation Collation Name
+ *
+ * @return void
+ */
+function PMA_changeAllColumnsCollation($db, $table, $tbl_collation)
+{
+ $GLOBALS['dbi']->selectDb($db);
+
+ $change_all_collations_query = 'ALTER TABLE ' . $table
+ . ' CONVERT TO';
+
+ list($charset) = explode('_', $tbl_collation);
+
+ $change_all_collations_query .= ' CHARACTER SET ' . $charset
+ . ($charset == $tbl_collation ? '' : ' COLLATE ' . $tbl_collation);
+
+ $GLOBALS['dbi']->query($change_all_collations_query);
+}
/**
* Move or copy a table
@@ -1608,15 +2116,47 @@ function PMA_moveOrCopyTable($db, $table)
$_REQUEST['what'], isset($_REQUEST['submit_move']), 'one_table'
);
- if (isset($_REQUEST['submit_move'])) {
- $message = PMA_Message::success(
- __('Table %s has been moved to %s.')
- );
+ if (isset($_REQUEST['adjust_privileges'])
+ && ! empty($_REQUEST['adjust_privileges'])
+ ) {
+ if (isset($_REQUEST['submit_move'])) {
+ PMA_AdjustPrivileges_renameOrMoveTable(
+ $db, $table, $_REQUEST['target_db'], $_REQUEST['new_name']
+ );
+ } else {
+ PMA_AdjustPrivileges_copyTable(
+ $db, $table, $_REQUEST['target_db'], $_REQUEST['new_name']
+ );
+ }
+
+ if (isset($_REQUEST['submit_move'])) {
+ $message = PMA_Message::success(
+ __(
+ 'Table %s has been moved to %s. Privileges have been '
+ . 'adjusted.'
+ )
+ );
+ } else {
+ $message = PMA_Message::success(
+ __(
+ 'Table %s has been copied to %s. Privileges have been '
+ . 'adjusted.'
+ )
+ );
+ }
+
} else {
- $message = PMA_Message::success(
- __('Table %s has been copied to %s.')
- );
+ if (isset($_REQUEST['submit_move'])) {
+ $message = PMA_Message::success(
+ __('Table %s has been moved to %s.')
+ );
+ } else {
+ $message = PMA_Message::success(
+ __('Table %s has been copied to %s.')
+ );
+ }
}
+
$old = PMA_Util::backquote($db) . '.'
. PMA_Util::backquote($table);
$message->addParam($old);
@@ -1648,4 +2188,3 @@ function PMA_moveOrCopyTable($db, $table)
exit;
}
}
-?>
diff --git a/libraries/parse_analyze.inc.php b/libraries/parse_analyze.inc.php
index 1864b010e0..1bd9f46e69 100644
--- a/libraries/parse_analyze.inc.php
+++ b/libraries/parse_analyze.inc.php
@@ -9,136 +9,47 @@ if (! defined('PHPMYADMIN')) {
exit;
}
-/**
- *
- */
$GLOBALS['unparsed_sql'] = $sql_query;
-$parsed_sql = PMA_SQP_parse($sql_query);
-$analyzed_sql = PMA_SQP_analyze($parsed_sql);
-
-// for bug 780516: now that we use case insensitive preg_match
-// or flags from the analyser, do not put back the reformatted query
-// into $sql_query, to make this kind of query work without
-// capitalizing keywords:
-//
-// CREATE TABLE SG_Persons (
-// id int(10) unsigned NOT NULL auto_increment,
-// first varchar(64) NOT NULL default '',
-// PRIMARY KEY (`id`)
-// )
-
-// Fills some variables from the analysed SQL
-// A table has to be created, renamed, dropped:
-// the navigation panel should be reloaded
-$reload = isset($analyzed_sql[0]['queryflags']['reload']);
-
-// check for drop database
-$drop_database = isset($analyzed_sql[0]['queryflags']['drop_database']);
-
-// for the presence of EXPLAIN
-$is_explain = isset($analyzed_sql[0]['queryflags']['is_explain']);
-
-// for the presence of DELETE
-$is_delete = isset($analyzed_sql[0]['queryflags']['is_delete']);
-
-// for the presence of UPDATE, DELETE or INSERT|LOAD DATA|REPLACE
-$is_affected = isset($analyzed_sql[0]['queryflags']['is_affected']);
-
-// for the presence of REPLACE
-$is_replace = isset($analyzed_sql[0]['queryflags']['is_replace']);
-
-// for the presence of INSERT
-$is_insert = isset($analyzed_sql[0]['queryflags']['is_insert']);
-
-// for the presence of CHECK|ANALYZE|REPAIR|OPTIMIZE TABLE
-$is_maint = isset($analyzed_sql[0]['queryflags']['is_maint']);
-
-// for the presence of SHOW
-$is_show = isset($analyzed_sql[0]['queryflags']['is_show']);
-
-// for the presence of PROCEDURE ANALYSE
-$is_analyse = isset($analyzed_sql[0]['queryflags']['is_analyse']);
-// for the presence of INTO OUTFILE
-$is_export = isset($analyzed_sql[0]['queryflags']['is_export']);
+// Get details about the SQL query.
+$analyzed_sql_results = SqlParser\Utils\Query::getAll($sql_query);
-// for the presence of GROUP BY|HAVING|SELECT DISTINCT
-$is_group = isset($analyzed_sql[0]['queryflags']['is_group']);
+// TODO: Refactor this.
+extract($analyzed_sql_results);
-// for the presence of SUM|AVG|STD|STDDEV|MIN|MAX|BIT_OR|BIT_AND
-$is_func = isset($analyzed_sql[0]['queryflags']['is_func']);
-
-// for the presence of SELECT COUNT
-$is_count = isset($analyzed_sql[0]['queryflags']['is_count']);
-
-// check for a real SELECT ... FROM
-$is_select = isset($analyzed_sql[0]['queryflags']['select_from']);
-
-// the query contains a subquery
-$is_subquery = isset($analyzed_sql[0]['queryflags']['is_subquery']);
-
-// check for CALL
-// Since multiple query execution is anyway handled,
-// ignore the WHERE clause of the first sql statement
-// which might contain a phrase like 'call '
-if (isset($analyzed_sql[0]['queryflags']['is_procedure'])
- && empty($analyzed_sql[0]['where_clause'])
-) {
- $is_procedure = true;
-} else {
- $is_procedure = false;
-}
-
-// aggregates all the results into one array
-$analyzed_sql_results = array(
- "parsed_sql" => $parsed_sql,
- "analyzed_sql" => $analyzed_sql,
- "reload" => $reload,
- "drop_database" => $drop_database,
- "is_explain" => $is_explain,
- "is_delete" => $is_delete,
- "is_affected" => $is_affected,
- "is_replace" => $is_replace,
- "is_insert" => $is_insert,
- "is_maint" => $is_maint,
- "is_show" => $is_show,
- "is_analyse" => $is_analyse,
- "is_export" => $is_export,
- "is_group" => $is_group,
- "is_func" => $is_func,
- "is_count" => $is_count,
- "is_select" => $is_select,
- "is_procedure" => $is_procedure,
- "is_subquery" => $is_subquery
-);
+// If the targeted table (and database) are different than the ones that is
+// currently browsed, edit `$db` and `$table` to match them so other elements
+// (page headers, links, navigation panel) can be updated properly.
+if (!empty($analyzed_sql_results['select_tables'])) {
+ // Previous table and database name is stored to check if it changed.
+ $prev_db = $db;
-// If the query is a Select, extract the db and table names and modify
-// $db and $table, to have correct page headers, links and left frame.
-// db and table name may be enclosed with backquotes, db is optional,
-// query may contain aliases.
+ if (count($analyzed_sql_results['select_tables']) > 1) {
-/**
- * @todo if there are more than one table name in the Select:
- * - do not extract the first table name
- * - do not show a table name in the page header
- * - do not display the sub-pages links)
- */
-if ($is_select) {
- $prev_db = $db;
- if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name'])) {
- $table = $analyzed_sql[0]['table_ref'][0]['table_true_name'];
- }
- if (isset($analyzed_sql[0]['table_ref'][0]['db'])
- && /*overload*/mb_strlen($analyzed_sql[0]['table_ref'][0]['db'])
- ) {
- $db = $analyzed_sql[0]['table_ref'][0]['db'];
+ /**
+ * @todo if there are more than one table name in the Select:
+ * - do not extract the first table name
+ * - do not show a table name in the page header
+ * - do not display the sub-pages links)
+ */
+ $table = '';
} else {
- $db = $prev_db;
+ $table = $analyzed_sql_results['select_tables'][0][0];
+ if (!empty($analyzed_sql_results['select_tables'][0][1])) {
+ $db = $analyzed_sql_results['select_tables'][0][1];
+ }
}
- // Don't change reload, if we already decided to reload in import
- if (empty($reload) && empty($GLOBALS['is_ajax_request'])) {
- $reload = ($db == $prev_db) ? 0 : 1;
+
+ // There is no point checking if a reload is required if we already decided
+ // to reload. Also, no reload is required for AJAX requests.
+ if ((empty($reload)) && (empty($GLOBALS['is_ajax_request']))) {
+ // NOTE: Database names are case-insensitive.
+ $reload = strcasecmp($db, $prev_db) != 0;
}
+
+ // Updating the array.
+ $analyzed_sql_results['reload'] = $reload;
}
-?>
+
+return $analyzed_sql_results;
diff --git a/libraries/php-gettext/gettext.php b/libraries/php-gettext/gettext.php
index 3486e92f07..d712deac1c 100644
--- a/libraries/php-gettext/gettext.php
+++ b/libraries/php-gettext/gettext.php
@@ -429,4 +429,3 @@ class gettext_reader {
}
}
-?>
diff --git a/libraries/php-gettext/streams.php b/libraries/php-gettext/streams.php
index ab947194a2..19cd9b2c1d 100644
--- a/libraries/php-gettext/streams.php
+++ b/libraries/php-gettext/streams.php
@@ -164,4 +164,3 @@ class CachedFileReader extends StringReader {
};
-?>
diff --git a/libraries/phpseclib/Crypt/Base.php b/libraries/phpseclib/Crypt/Base.php
index 715ab2a5da..f26561e549 100644
--- a/libraries/phpseclib/Crypt/Base.php
+++ b/libraries/phpseclib/Crypt/Base.php
@@ -957,7 +957,7 @@ abstract class Base
break;
case self::MODE_ECB:
if (!defined('OPENSSL_RAW_DATA')) {
- $ciphetext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
+ $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
}
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
break;
diff --git a/libraries/plugin_interface.lib.php b/libraries/plugin_interface.lib.php
index 16c8bf0320..d48a333611 100644
--- a/libraries/plugin_interface.lib.php
+++ b/libraries/plugin_interface.lib.php
@@ -205,6 +205,7 @@ function PMA_pluginGetChoice($section, $name, &$list, $cfgname = null)
$ret .= ' selected="selected"';
}
+ /** @var PluginPropertyItem $properties */
$properties = $plugin->getProperties();
$text = null;
if ($properties != null) {
@@ -226,8 +227,9 @@ function PMA_pluginGetChoice($section, $name, &$list, $cfgname = null)
);
$ret .= '<input type="hidden" id="force_file_' . $plugin_name
. '" value="';
+ /** @var ExportPluginProperties|SchemaPluginProperties $properties */
$properties = $plugin->getProperties();
- if ( ! strcmp($section, 'Import')
+ if (! strcmp($section, 'Import')
|| ($properties != null && $properties->getForceFile() != null)
) {
$ret .= 'true';
diff --git a/libraries/plugins/AuthenticationPlugin.class.php b/libraries/plugins/AuthenticationPlugin.class.php
index e9a6ee1052..19f4dd21f6 100644
--- a/libraries/plugins/AuthenticationPlugin.class.php
+++ b/libraries/plugins/AuthenticationPlugin.class.php
@@ -75,7 +75,7 @@ abstract class AuthenticationPlugin
);
} else {
$dbi_error = $GLOBALS['dbi']->getError();
- if ( ! empty($dbi_error)) {
+ if (! empty($dbi_error)) {
return PMA_sanitize($dbi_error);
} elseif (isset($GLOBALS['errno'])) {
return '#' . $GLOBALS['errno'] . ' '
@@ -91,10 +91,9 @@ abstract class AuthenticationPlugin
*
* @param string $password New password to set
*
- * @return void
+ * @return void
*/
public function handlePasswordChange($password)
{
}
}
-?>
diff --git a/libraries/plugins/ExportPlugin.class.php b/libraries/plugins/ExportPlugin.class.php
index b74cd66640..f959e39b1a 100644
--- a/libraries/plugins/ExportPlugin.class.php
+++ b/libraries/plugins/ExportPlugin.class.php
@@ -37,14 +37,14 @@ abstract class ExportPlugin
*
* @return bool Whether it succeeded
*/
- abstract public function exportHeader ();
+ abstract public function exportHeader();
/**
* Outputs export footer
*
* @return bool Whether it succeeded
*/
- abstract public function exportFooter ();
+ abstract public function exportFooter();
/**
* Outputs database header
@@ -54,7 +54,7 @@ abstract class ExportPlugin
*
* @return bool Whether it succeeded
*/
- abstract public function exportDBHeader ($db, $db_alias = '');
+ abstract public function exportDBHeader($db, $db_alias = '');
/**
* Outputs database footer
@@ -63,17 +63,18 @@ abstract class ExportPlugin
*
* @return bool Whether it succeeded
*/
- abstract public function exportDBFooter ($db);
+ abstract public function exportDBFooter($db);
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- abstract public function exportDBCreate($db, $db_alias = '');
+ abstract public function exportDBCreate($db, $export_type, $db_alias = '');
/**
* Outputs the content of a table
@@ -87,7 +88,7 @@ abstract class ExportPlugin
*
* @return bool Whether it succeeded
*/
- abstract public function exportData (
+ abstract public function exportData(
$db, $table, $crlf, $error_url, $sql_query, $aliases = array()
);
@@ -112,12 +113,11 @@ abstract class ExportPlugin
/**
* Exports events
*
- * @param string $db Database
- * @param array $aliases Aliases of db/table/columns
+ * @param string $db Database
*
* @return bool Whether it succeeded
*/
- public function exportEvents($db, $aliases = array())
+ public function exportEvents($db)
{
;
}
@@ -161,6 +161,23 @@ abstract class ExportPlugin
}
/**
+ * Exports metadata from Configuration Storage
+ *
+ * @param string $db database being exported
+ * @param string|array $tables table(s) being exported
+ * @param array $metadataTypes types of metadata to export
+ * @param array $targetNames associative array of db and table names of
+ * target configuraton storage
+ *
+ * @return bool Whether it succeeded
+ */
+ public function exportMetadata(
+ $db, $tables, $metadataTypes, $targetNames = array()
+ ) {
+ ;
+ }
+
+ /**
* Returns a stand-in CREATE definition to resolve view dependencies
*
* @param string $db the database name
@@ -203,7 +220,7 @@ abstract class ExportPlugin
/**
* Gets the export specific format plugin properties
*
- * @return array
+ * @return ExportPluginProperties
*/
public function getProperties()
{
@@ -336,4 +353,3 @@ abstract class ExportPlugin
return $relation;
}
}
-?>
diff --git a/libraries/plugins/IOTransformationsPlugin.class.php b/libraries/plugins/IOTransformationsPlugin.class.php
index 4717dc97bd..56ffcc96d2 100644
--- a/libraries/plugins/IOTransformationsPlugin.class.php
+++ b/libraries/plugins/IOTransformationsPlugin.class.php
@@ -37,11 +37,15 @@ abstract class IOTransformationsPlugin extends TransformationsPlugin
* @param array $options transformation options
* @param string $value Current field value
* @param string $text_dir text direction
+ * @param int $tabindex tab index
+ * @param int $tabindex_for_value offset for the values tabindex
+ * @param int $idindex id index
*
* @return string the html for input field
*/
public function getInputHtml(
- $column, $row_id, $column_name_appendix, $options, $value, $text_dir
+ $column, $row_id, $column_name_appendix, $options, $value, $text_dir,
+ $tabindex, $tabindex_for_value, $idindex
) {
return '';
}
@@ -88,4 +92,3 @@ abstract class IOTransformationsPlugin extends TransformationsPlugin
$this->error = '';
}
}
-?>
diff --git a/libraries/plugins/ImportPlugin.class.php b/libraries/plugins/ImportPlugin.class.php
index 26476090a7..5ef5ded6bf 100644
--- a/libraries/plugins/ImportPlugin.class.php
+++ b/libraries/plugins/ImportPlugin.class.php
@@ -38,7 +38,7 @@ abstract class ImportPlugin
/**
* Gets the import specific format plugin properties
*
- * @return array
+ * @return ImportPluginProperties
*/
public function getProperties()
{
@@ -74,4 +74,3 @@ abstract class ImportPlugin
return array($db_name, $options);
}
}
-?>
diff --git a/libraries/plugins/SchemaPlugin.class.php b/libraries/plugins/SchemaPlugin.class.php
index c4774ef620..1fc17f6024 100644
--- a/libraries/plugins/SchemaPlugin.class.php
+++ b/libraries/plugins/SchemaPlugin.class.php
@@ -30,7 +30,7 @@ abstract class SchemaPlugin
/**
* Gets the export specific format plugin properties
*
- * @return array
+ * @return SchemaPluginProperties
*/
public function getProperties()
{
@@ -73,4 +73,3 @@ abstract class SchemaPlugin
$propertyGroup->addProperty($leaf);
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/TransformationsInterface.int.php b/libraries/plugins/TransformationsInterface.int.php
index 1bcb8af450..c0c6720b0d 100644
--- a/libraries/plugins/TransformationsInterface.int.php
+++ b/libraries/plugins/TransformationsInterface.int.php
@@ -46,4 +46,3 @@ interface TransformationsInterface
public static function getName();
}
-?>
diff --git a/libraries/plugins/TransformationsPlugin.class.php b/libraries/plugins/TransformationsPlugin.class.php
index f6fe0694aa..edac01f566 100644
--- a/libraries/plugins/TransformationsPlugin.class.php
+++ b/libraries/plugins/TransformationsPlugin.class.php
@@ -57,7 +57,7 @@ abstract class TransformationsPlugin implements TransformationsInterface
{
$result = array();
foreach ($defaults as $key => $value) {
- if ( isset($options[$key]) && $options[$key] !== '') {
+ if (isset($options[$key]) && $options[$key] !== '') {
$result[$key] = $options[$key];
} else {
$result[$key] = $value;
@@ -66,4 +66,3 @@ abstract class TransformationsPlugin implements TransformationsInterface
return $result;
}
}
-?>
diff --git a/libraries/plugins/UploadInterface.int.php b/libraries/plugins/UploadInterface.int.php
index ab660d610d..f50aa93b35 100644
--- a/libraries/plugins/UploadInterface.int.php
+++ b/libraries/plugins/UploadInterface.int.php
@@ -33,4 +33,3 @@ interface UploadInterface
*/
public static function getUploadStatus($id);
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/auth/AuthenticationConfig.class.php b/libraries/plugins/auth/AuthenticationConfig.class.php
index 19a8ed2a16..f4ffd6e3d8 100644
--- a/libraries/plugins/auth/AuthenticationConfig.class.php
+++ b/libraries/plugins/auth/AuthenticationConfig.class.php
@@ -159,7 +159,9 @@ class AuthenticationConfig extends AuthenticationPlugin
<tr>
<td>' . "\n";
echo '<a href="'
- . $GLOBALS['cfg']['DefaultTabServer']
+ . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabServer'], 'server'
+ )
. PMA_URL_getCommon(array()) . '" class="button disableAjax">'
. __('Retry to connect')
. '</a>' . "\n";
diff --git a/libraries/plugins/auth/AuthenticationCookie.class.php b/libraries/plugins/auth/AuthenticationCookie.class.php
index 3732b6c269..8f82c6e36a 100644
--- a/libraries/plugins/auth/AuthenticationCookie.class.php
+++ b/libraries/plugins/auth/AuthenticationCookie.class.php
@@ -224,7 +224,7 @@ class AuthenticationCookie extends AuthenticationPlugin
} // end if (server choice)
// Add captcha input field if reCaptcha is enabled
- if ( !empty($GLOBALS['cfg']['CaptchaLoginPrivateKey'])
+ if (!empty($GLOBALS['cfg']['CaptchaLoginPrivateKey'])
&& !empty($GLOBALS['cfg']['CaptchaLoginPublicKey'])
) {
// If enabled show captcha to the user on the login screen.
@@ -440,7 +440,6 @@ class AuthenticationCookie extends AuthenticationPlugin
if ($_SESSION['last_access_time'] < $last_access_time
) {
PMA_Util::cacheUnset('is_create_db_priv');
- PMA_Util::cacheUnset('is_process_priv');
PMA_Util::cacheUnset('is_reload_priv');
PMA_Util::cacheUnset('db_to_create');
PMA_Util::cacheUnset('dbs_where_create_table_allowed');
@@ -699,7 +698,7 @@ class AuthenticationCookie extends AuthenticationPlugin
private function _getSessionEncryptionSecret()
{
if (empty($_SESSION['encryption_key'])) {
- if ($this->_useOpenSSL()) {
+ if (self::useOpenSSL()) {
$_SESSION['encryption_key'] = openssl_random_pseudo_bytes(256);
} else {
$_SESSION['encryption_key'] = Crypt\Random::string(256);
@@ -713,7 +712,7 @@ class AuthenticationCookie extends AuthenticationPlugin
*
* @return boolean
*/
- private function _useOpenSSL()
+ public static function useOpenSSL()
{
return (
function_exists('openssl_encrypt')
@@ -734,7 +733,7 @@ class AuthenticationCookie extends AuthenticationPlugin
*/
public function cookieEncrypt($data, $secret)
{
- if ($this->_useOpenSSL()) {
+ if (self::useOpenSSL()) {
return openssl_encrypt(
$data,
'AES-128-CBC',
@@ -762,13 +761,16 @@ class AuthenticationCookie extends AuthenticationPlugin
public function cookieDecrypt($encdata, $secret)
{
if (is_null($this->_cookie_iv)) {
- $this->_cookie_iv = base64_decode($_COOKIE['pma_iv-' . $GLOBALS['server']], true);
+ $this->_cookie_iv = base64_decode(
+ $_COOKIE['pma_iv-' . $GLOBALS['server']],
+ true
+ );
}
if (mb_strlen($this->_cookie_iv,'8bit') < $this->getIVSize()) {
$this->createIV();
}
- if ($this->_useOpenSSL()) {
+ if (self::useOpenSSL()) {
return openssl_decrypt(
$encdata,
'AES-128-CBC',
@@ -791,7 +793,7 @@ class AuthenticationCookie extends AuthenticationPlugin
*/
public function getIVSize()
{
- if ($this->_useOpenSSL()) {
+ if (self::useOpenSSL()) {
return openssl_cipher_iv_length('AES-128-CBC');
}
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
@@ -808,7 +810,7 @@ class AuthenticationCookie extends AuthenticationPlugin
*/
public function createIV()
{
- if ($this->_useOpenSSL()) {
+ if (self::useOpenSSL()) {
$this->_cookie_iv = openssl_random_pseudo_bytes(
$this->getIVSize()
);
diff --git a/libraries/plugins/auth/AuthenticationHttp.class.php b/libraries/plugins/auth/AuthenticationHttp.class.php
index ab205e9d70..5a5a2730dc 100644
--- a/libraries/plugins/auth/AuthenticationHttp.class.php
+++ b/libraries/plugins/auth/AuthenticationHttp.class.php
@@ -263,17 +263,18 @@ class AuthenticationHttp extends AuthenticationPlugin
/**
* User is not allowed to login to MySQL -> authentication failed
*
- * @return boolean always true (no return indeed)
+ * @return bool true
*/
public function authFails()
{
$error = $GLOBALS['dbi']->getError();
if ($error && $GLOBALS['errno'] != 1045) {
PMA_fatalError($error);
- } else {
- $this->authForm();
return true;
}
+
+ $this->authForm();
+ return true;
}
/**
@@ -281,7 +282,7 @@ class AuthenticationHttp extends AuthenticationPlugin
*
* @param string $password New password to set
*
- * @return void
+ * @return void
*/
public function handlePasswordChange($password)
{
diff --git a/libraries/plugins/auth/swekey/swekey.auth.lib.php b/libraries/plugins/auth/swekey/swekey.auth.lib.php
index 76bbc02dbf..1741ca7764 100644
--- a/libraries/plugins/auth/swekey/swekey.auth.lib.php
+++ b/libraries/plugins/auth/swekey/swekey.auth.lib.php
@@ -100,9 +100,9 @@ function Swekey_Auth_error()
function Swekey_GetValidKey()
{
var valids = "<?php
- foreach ($_SESSION['SWEKEY']['VALID_SWEKEYS'] as $key => $value) {
+ foreach ($_SESSION['SWEKEY']['VALID_SWEKEYS'] as $key => $value) {
echo $key . ',';
- }
+ }
?>";
var connected_keys = Swekey_ListKeyIds().split(",");
for (i in connected_keys) {
@@ -136,18 +136,18 @@ function Swekey_Auth_error()
setTimeout("timedCheck()",1000);
</script>
- <?php
+ <?php
- if (! empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
- return null;
- }
+ if (! empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
+ return null;
+ }
- if (count($_SESSION['SWEKEY']['VALID_SWEKEYS']) == 0) {
- return sprintf(
- __('File %s does not contain any key id'),
- $GLOBALS['cfg']['Server']['auth_swekey_config']
- );
- }
+ if (count($_SESSION['SWEKEY']['VALID_SWEKEYS']) == 0) {
+ return sprintf(
+ __('File %s does not contain any key id'),
+ $GLOBALS['cfg']['Server']['auth_swekey_config']
+ );
+ }
include_once "libraries/plugins/auth/swekey/swekey.php";
@@ -315,4 +315,3 @@ if (isset($_GET['swekey_reset'])) {
unset($_SESSION['SWEKEY']);
}
-?>
diff --git a/libraries/plugins/export/ExportCodegen.class.php b/libraries/plugins/export/ExportCodegen.class.php
index aa02369b33..1abf3c6a57 100644
--- a/libraries/plugins/export/ExportCodegen.class.php
+++ b/libraries/plugins/export/ExportCodegen.class.php
@@ -120,7 +120,7 @@ class ExportCodegen extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
return true;
}
@@ -130,7 +130,7 @@ class ExportCodegen extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -143,7 +143,7 @@ class ExportCodegen extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
return true;
}
@@ -155,7 +155,7 @@ class ExportCodegen extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -163,12 +163,13 @@ class ExportCodegen extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -247,6 +248,7 @@ class ExportCodegen extends ExportPlugin
)
);
if ($result) {
+ /** @var TableProperty[] $tableProperties */
$tableProperties = array();
while ($row = $GLOBALS['dbi']->fetchRow($result)) {
$col_as = $this->getAlias($aliases, $row[0], 'col', $db, $table);
@@ -431,4 +433,3 @@ class ExportCodegen extends ExportPlugin
$this->_cgHandlers = $CG_HANDLERS;
}
}
-?>
diff --git a/libraries/plugins/export/ExportCsv.class.php b/libraries/plugins/export/ExportCsv.class.php
index b8a7bb4067..ef36f09225 100644
--- a/libraries/plugins/export/ExportCsv.class.php
+++ b/libraries/plugins/export/ExportCsv.class.php
@@ -106,7 +106,7 @@ class ExportCsv extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
global $what, $csv_terminated, $csv_separator, $csv_enclosed, $csv_escaped;
@@ -151,7 +151,7 @@ class ExportCsv extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -164,7 +164,7 @@ class ExportCsv extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
return true;
}
@@ -176,7 +176,7 @@ class ExportCsv extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -184,12 +184,13 @@ class ExportCsv extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Alias of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -320,4 +321,3 @@ class ExportCsv extends ExportPlugin
return true;
}
}
-?>
diff --git a/libraries/plugins/export/ExportExcel.class.php b/libraries/plugins/export/ExportExcel.class.php
index 0cc61ef75b..83f5486040 100644
--- a/libraries/plugins/export/ExportExcel.class.php
+++ b/libraries/plugins/export/ExportExcel.class.php
@@ -89,4 +89,3 @@ class ExportExcel extends ExportCsv
$this->properties = $exportPluginProperties;
}
}
-?>
diff --git a/libraries/plugins/export/ExportHtmlword.class.php b/libraries/plugins/export/ExportHtmlword.class.php
index 4c78e21adb..93210cf83a 100644
--- a/libraries/plugins/export/ExportHtmlword.class.php
+++ b/libraries/plugins/export/ExportHtmlword.class.php
@@ -102,9 +102,9 @@ class ExportHtmlword extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
- global $charset_of_file;
+ global $charset;
return PMA_exportOutputHandler(
'<html xmlns:o="urn:schemas-microsoft-com:office:office"
@@ -116,7 +116,7 @@ class ExportHtmlword extends ExportPlugin
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset='
- . (isset($charset_of_file) ? $charset_of_file : 'utf-8') . '" />
+ . (isset($charset) ? $charset : 'utf-8') . '" />
</head>
<body>'
);
@@ -127,7 +127,7 @@ class ExportHtmlword extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return PMA_exportOutputHandler('</body></html>');
}
@@ -140,7 +140,7 @@ class ExportHtmlword extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
if (empty($db_alias)) {
$db_alias = $db;
@@ -157,7 +157,7 @@ class ExportHtmlword extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -165,12 +165,13 @@ class ExportHtmlword extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -641,4 +642,3 @@ class ExportHtmlword extends ExportPlugin
return $definition;
}
}
-?>
diff --git a/libraries/plugins/export/ExportJson.class.php b/libraries/plugins/export/ExportJson.class.php
index d659e3fef6..7f5e954b69 100644
--- a/libraries/plugins/export/ExportJson.class.php
+++ b/libraries/plugins/export/ExportJson.class.php
@@ -41,6 +41,7 @@ class ExportJson extends ExportPlugin
include_once "$props/options/groups/OptionsPropertyRootGroup.class.php";
include_once "$props/options/groups/OptionsPropertyMainGroup.class.php";
include_once "$props/options/items/HiddenPropertyItem.class.php";
+ include_once "$props/options/items/BoolPropertyItem.class.php";
$exportPluginProperties = new ExportPluginProperties();
$exportPluginProperties->setText('JSON');
@@ -61,6 +62,17 @@ class ExportJson extends ExportPlugin
$leaf = new HiddenPropertyItem();
$leaf->setName("structure_or_data");
$generalOptions->addProperty($leaf);
+
+ // JSON_PRETTY_PRINT is available since 5.4.0
+ if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
+ $leaf = new BoolPropertyItem();
+ $leaf->setName('pretty_print');
+ $leaf->setText(
+ __('Output pretty-printed JSON (Use human-readable formatting)')
+ );
+ $generalOptions->addProperty($leaf);
+ }
+
// add the main group to the root group
$exportSpecificOptions->addProperty($generalOptions);
@@ -74,7 +86,7 @@ class ExportJson extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
PMA_exportOutputHandler(
'/**' . $GLOBALS['crlf']
@@ -90,7 +102,7 @@ class ExportJson extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -103,7 +115,7 @@ class ExportJson extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
if (empty($db_alias)) {
$db_alias = $db;
@@ -121,7 +133,7 @@ class ExportJson extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -129,12 +141,13 @@ class ExportJson extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -172,7 +185,6 @@ class ExportJson extends ExportPlugin
$columns[$i] = stripslashes($col_as);
}
- $buffer = '';
$record_cnt = 0;
while ($record = $GLOBALS['dbi']->fetchRow($result)) {
@@ -197,7 +209,15 @@ class ExportJson extends ExportPlugin
$data[$columns[$i]] = $record[$i];
}
- if (! PMA_exportOutputHandler(json_encode($data))) {
+ if (isset($GLOBALS['json_pretty_print'])
+ && $GLOBALS['json_pretty_print']
+ ) {
+ $encoded = json_encode($data, JSON_PRETTY_PRINT);
+ } else {
+ $encoded = json_encode($data);
+ }
+
+ if (! PMA_exportOutputHandler($encoded)) {
return false;
}
}
@@ -212,4 +232,3 @@ class ExportJson extends ExportPlugin
return true;
}
}
-?>
diff --git a/libraries/plugins/export/ExportLatex.class.php b/libraries/plugins/export/ExportLatex.class.php
index 7f5ac378d9..f83f094127 100644
--- a/libraries/plugins/export/ExportLatex.class.php
+++ b/libraries/plugins/export/ExportLatex.class.php
@@ -193,7 +193,7 @@ class ExportLatex extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
global $crlf;
global $cfg;
@@ -219,7 +219,7 @@ class ExportLatex extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -232,7 +232,7 @@ class ExportLatex extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
if (empty($db_alias)) {
$db_alias = $db;
@@ -251,7 +251,7 @@ class ExportLatex extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -259,12 +259,13 @@ class ExportLatex extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -653,4 +654,3 @@ class ExportLatex extends ExportPlugin
return $string;
}
}
-?>
diff --git a/libraries/plugins/export/ExportMediawiki.class.php b/libraries/plugins/export/ExportMediawiki.class.php
index ffd47876a8..a40a017c6f 100644
--- a/libraries/plugins/export/ExportMediawiki.class.php
+++ b/libraries/plugins/export/ExportMediawiki.class.php
@@ -102,7 +102,7 @@ class ExportMediawiki extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
return true;
}
@@ -112,7 +112,7 @@ class ExportMediawiki extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -125,7 +125,7 @@ class ExportMediawiki extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
return true;
}
@@ -137,7 +137,7 @@ class ExportMediawiki extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -145,12 +145,13 @@ class ExportMediawiki extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Alias of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -311,7 +312,7 @@ class ExportMediawiki extends ExportPlugin
$column_names = $GLOBALS['dbi']->getColumnNames($db, $table);
// Add column names as table headers
- if ( ! is_null($column_names) ) {
+ if (! is_null($column_names) ) {
// Use '|-' for separating rows
$output .= "|-" . $this->_exportCRLF();
@@ -376,4 +377,3 @@ class ExportMediawiki extends ExportPlugin
return "\n";
}
}
-?>
diff --git a/libraries/plugins/export/ExportOds.class.php b/libraries/plugins/export/ExportOds.class.php
index 7add7f4e36..df2b275915 100644
--- a/libraries/plugins/export/ExportOds.class.php
+++ b/libraries/plugins/export/ExportOds.class.php
@@ -90,7 +90,7 @@ class ExportOds extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
$GLOBALS['ods_buffer'] .= '<?xml version="1.0" encoding="utf-8"?' . '>'
. '<office:document-content '
@@ -145,7 +145,7 @@ class ExportOds extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
$GLOBALS['ods_buffer'] .= '</office:spreadsheet>'
. '</office:body>'
@@ -169,7 +169,7 @@ class ExportOds extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
return true;
}
@@ -181,7 +181,7 @@ class ExportOds extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -189,12 +189,13 @@ class ExportOds extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -331,4 +332,3 @@ class ExportOds extends ExportPlugin
return true;
}
}
-?>
diff --git a/libraries/plugins/export/ExportOdt.class.php b/libraries/plugins/export/ExportOdt.class.php
index 8c5a61cc12..70e82e6923 100644
--- a/libraries/plugins/export/ExportOdt.class.php
+++ b/libraries/plugins/export/ExportOdt.class.php
@@ -143,7 +143,7 @@ class ExportOdt extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
$GLOBALS['odt_buffer'] .= '<?xml version="1.0" encoding="utf-8"?' . '>'
. '<office:document-content '
@@ -158,7 +158,7 @@ class ExportOdt extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
$GLOBALS['odt_buffer'] .= '</office:text>'
. '</office:body>'
@@ -182,7 +182,7 @@ class ExportOdt extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
if (empty($db_alias)) {
$db_alias = $db;
@@ -202,7 +202,7 @@ class ExportOdt extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -210,12 +210,13 @@ class ExportOdt extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -762,4 +763,3 @@ class ExportOdt extends ExportPlugin
return $definition;
}
}
-?>
diff --git a/libraries/plugins/export/ExportPdf.class.php b/libraries/plugins/export/ExportPdf.class.php
index 121c8d1587..272004683d 100644
--- a/libraries/plugins/export/ExportPdf.class.php
+++ b/libraries/plugins/export/ExportPdf.class.php
@@ -22,6 +22,7 @@ if (! file_exists(TCPDF_INC)) {
require_once 'libraries/plugins/ExportPlugin.class.php';
/* Get the PMA_ExportPdf class */
require_once 'libraries/plugins/export/PMA_ExportPdf.class.php';
+require_once 'libraries/transformations.lib.php';
/**
* Handles the export for the PDF class
@@ -80,9 +81,8 @@ class ExportPdf extends ExportPlugin
include_once "$props/plugins/ExportPluginProperties.class.php";
include_once "$props/options/groups/OptionsPropertyRootGroup.class.php";
include_once "$props/options/groups/OptionsPropertyMainGroup.class.php";
- include_once "$props/options/items/MessageOnlyPropertyItem.class.php";
+ include_once "$props/options/items/RadioPropertyItem.class.php";
include_once "$props/options/items/TextPropertyItem.class.php";
- include_once "$props/options/items/HiddenPropertyItem.class.php";
$exportPluginProperties = new ExportPluginProperties();
$exportPluginProperties->setText('PDF');
@@ -101,22 +101,30 @@ class ExportPdf extends ExportPlugin
$generalOptions = new OptionsPropertyMainGroup();
$generalOptions->setName("general_opts");
// create primary items and add them to the group
- $leaf = new MessageOnlyPropertyItem();
- $leaf->setName("explanation");
- $leaf->setText(
- __('(Generates a report containing the data of a single table)')
- );
- $generalOptions->addProperty($leaf);
$leaf = new TextPropertyItem();
$leaf->setName("report_title");
$leaf->setText(__('Report title:'));
$generalOptions->addProperty($leaf);
- $leaf = new HiddenPropertyItem();
- $leaf->setName("structure_or_data");
- $generalOptions->addProperty($leaf);
- // add the main group to the root group
+ // add the group to the root group
$exportSpecificOptions->addProperty($generalOptions);
+ // what to dump (structure/data/both) main group
+ $dumpWhat = new OptionsPropertyMainGroup();
+ $dumpWhat->setName("dump_what");
+ $dumpWhat->setText(__('Dump table'));
+ $leaf = new RadioPropertyItem();
+ $leaf->setName("structure_or_data");
+ $leaf->setValues(
+ array(
+ 'structure' => __('structure'),
+ 'data' => __('data'),
+ 'structure_and_data' => __('structure and data')
+ )
+ );
+ $dumpWhat->addProperty($leaf);
+ // add the group to the root group
+ $exportSpecificOptions->addProperty($dumpWhat);
+
// set the options for the export plugin property item
$exportPluginProperties->setOptions($exportSpecificOptions);
$this->properties = $exportPluginProperties;
@@ -127,7 +135,7 @@ class ExportPdf extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
$pdf_report_title = $this->_getPdfReportTitle();
$pdf = $this->_getPdf();
@@ -145,7 +153,7 @@ class ExportPdf extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
$pdf = $this->_getPdf();
@@ -165,7 +173,7 @@ class ExportPdf extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
return true;
}
@@ -177,7 +185,7 @@ class ExportPdf extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -185,12 +193,13 @@ class ExportPdf extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -213,18 +222,108 @@ class ExportPdf extends ExportPlugin
$table_alias = $table;
$this->initAlias($aliases, $db_alias, $table_alias);
$pdf = $this->_getPdf();
-
$attr = array(
'currentDb' => $db, 'currentTable' => $table,
'dbAlias' => $db_alias, 'tableAlias' => $table_alias,
'aliases' => $aliases
);
$pdf->setAttributes($attr);
+ $pdf->purpose = __('Dumping data');
$pdf->mysqlReport($sql_query);
return true;
} // end of the 'PMA_exportData()' function
+ /**
+ * Outputs table structure
+ *
+ * @param string $db database name
+ * @param string $table table name
+ * @param string $crlf the end of line sequence
+ * @param string $error_url the url to go back in case of error
+ * @param string $export_mode 'create_table', 'triggers', 'create_view',
+ * 'stand_in'
+ * @param string $export_type 'server', 'database', 'table'
+ * @param bool $do_relation whether to include relation comments
+ * @param bool $do_comments whether to include the pmadb-style column
+ * comments as comments in the structure;
+ * this is deprecated but the parameter is
+ * left here because export.php calls
+ * PMA_exportStructure() also for other
+ * export types which use this parameter
+ * @param bool $do_mime whether to include mime comments
+ * @param bool $dates whether to include creation/update/check dates
+ * @param array $aliases aliases for db/table/columns
+ *
+ * @return bool Whether it succeeded
+ */
+ public function exportStructure(
+ $db,
+ $table,
+ $crlf,
+ $error_url,
+ $export_mode,
+ $export_type,
+ $do_relation = false,
+ $do_comments = false,
+ $do_mime = false,
+ $dates = false,
+ $aliases = array()
+ ) {
+ $db_alias = $db;
+ $table_alias = $table;
+ $this->initAlias($aliases, $db_alias, $table_alias);
+ $pdf = $this->_getPdf();
+ // getting purpose to show at top
+ switch($export_mode) {
+ case 'create_table':
+ $purpose = __('Table structure');
+ break;
+ case 'triggers':
+ $purpose = __('Triggers');
+ break;
+ case 'create_view':
+ $purpose = __('View structure');
+ break;
+ case 'stand_in':
+ $purpose = __('Stand in');
+ } // end switch
+
+ $attr = array(
+ 'currentDb' => $db, 'currentTable' => $table,
+ 'dbAlias' => $db_alias, 'tableAlias' => $table_alias,
+ 'aliases' => $aliases, 'purpose' => $purpose
+ );
+ $pdf->setAttributes($attr);
+ /**
+ * comment display set true as presently in pdf
+ * format, no option is present to take user input.
+ */
+ $do_comments = true;
+ switch($export_mode) {
+ case 'create_table':
+ $pdf->getTableDef(
+ $db, $table, $do_relation, $do_comments, $do_mime, false, $aliases
+ );
+ break;
+ case 'triggers':
+ $pdf->getTriggers($db, $table);
+ break;
+ case 'create_view':
+ $pdf->getTableDef(
+ $db, $table, $do_relation, $do_comments, $do_mime, false, $aliases
+ );
+ break;
+ case 'stand_in':
+ /* export a stand-in definition to resolve view dependencies
+ * Yet to develop this function
+ * $pdf->getTableDefStandIn($db, $table, $crlf);
+ */
+ } // end switch
+
+ return true;
+ }
+
/* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
@@ -273,4 +372,3 @@ class ExportPdf extends ExportPlugin
$this->_pdfReportTitle = $pdfReportTitle;
}
}
-?>
diff --git a/libraries/plugins/export/ExportPhparray.class.php b/libraries/plugins/export/ExportPhparray.class.php
index 80a34bed19..8920da001b 100644
--- a/libraries/plugins/export/ExportPhparray.class.php
+++ b/libraries/plugins/export/ExportPhparray.class.php
@@ -74,7 +74,7 @@ class ExportPhparray extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
PMA_exportOutputHandler(
'<?php' . $GLOBALS['crlf']
@@ -91,7 +91,7 @@ class ExportPhparray extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -104,7 +104,7 @@ class ExportPhparray extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
if (empty($db_alias)) {
$db_alias = $db;
@@ -124,7 +124,7 @@ class ExportPhparray extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -132,12 +132,13 @@ class ExportPhparray extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -188,7 +189,7 @@ class ExportPhparray extends ExportPlugin
);
// variable name must not start with a number or dash...
- if (preg_match('/^[a-zA-Z_\x7f-\xff]/', $tablefixed) == false) {
+ if (preg_match('/^[a-zA-Z_\x7f-\xff]/', $tablefixed) === 0) {
$tablefixed = '_' . $tablefixed;
}
} else {
@@ -230,4 +231,3 @@ class ExportPhparray extends ExportPlugin
return true;
}
}
-?>
diff --git a/libraries/plugins/export/ExportSql.class.php b/libraries/plugins/export/ExportSql.class.php
index 123950b953..62e89b4e33 100644
--- a/libraries/plugins/export/ExportSql.class.php
+++ b/libraries/plugins/export/ExportSql.class.php
@@ -155,6 +155,12 @@ class ExportSql extends ExportPlugin
$leaf->setText(__('Export views as tables'));
$generalOptions->addProperty($leaf);
+ // export metadata
+ $leaf = new BoolPropertyItem();
+ $leaf->setName("metadata");
+ $leaf->setText(__('Export metadata'));
+ $generalOptions->addProperty($leaf);
+
// compatibility maximization
$compats = $GLOBALS['dbi']->getCompatibilities();
if (count($compats) > 0) {
@@ -183,16 +189,6 @@ class ExportSql extends ExportPlugin
unset($values);
}
- // server export options
- if ($plugin_param['export_type'] == 'server') {
- $leaf = new BoolPropertyItem();
- $leaf->setName("drop_database");
- $leaf->setText(
- sprintf(__('Add %s statement'), '<code>DROP DATABASE</code>')
- );
- $generalOptions->addProperty($leaf);
- }
-
// what to dump (structure/data/both)
$subgroup = new OptionsPropertySubgroup();
$subgroup->setName("dump_table");
@@ -226,7 +222,17 @@ class ExportSql extends ExportPlugin
$leaf->setText(__('Add statements:'));
$subgroup->setSubgroupHeader($leaf);
- if ($plugin_param['export_type'] != 'table') {
+ // server export options
+ if ($plugin_param['export_type'] == 'server') {
+ $leaf = new BoolPropertyItem();
+ $leaf->setName("drop_database");
+ $leaf->setText(
+ sprintf(__('Add %s statement'), '<code>DROP DATABASE</code>')
+ );
+ $subgroup->addProperty($leaf);
+ }
+
+ if ($plugin_param['export_type'] == 'database') {
$leaf = new BoolPropertyItem();
$leaf->setName('create_database');
$create_clause = '<code>CREATE DATABASE / USE</code>';
@@ -235,7 +241,7 @@ class ExportSql extends ExportPlugin
}
if ($plugin_param['export_type'] == 'table') {
- if (PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])) {
+ if ($GLOBALS['dbi']->getTable($GLOBALS['db'], $GLOBALS['table'])->isView()) {
$drop_clause = '<code>DROP VIEW</code>';
} else {
$drop_clause = '<code>DROP TABLE</code>';
@@ -256,13 +262,34 @@ class ExportSql extends ExportPlugin
$leaf->setText(sprintf(__('Add %s statement'), $drop_clause));
$subgroup->addProperty($leaf);
+ $subgroup_create_table = new OptionsPropertySubgroup();
+
// Add table structure option
$leaf = new BoolPropertyItem();
$leaf->setName('create_table');
$leaf->setText(
sprintf(__('Add %s statement'), '<code>CREATE TABLE</code>')
);
- $subgroup->addProperty($leaf);
+ $subgroup_create_table->setSubgroupHeader($leaf);
+
+ $leaf = new BoolPropertyItem();
+ $leaf->setName('if_not_exists');
+ $leaf->setText(
+ '<code>IF NOT EXISTS</code> ' . __(
+ '(less efficient as indexes will be generated during table '
+ . 'creation)'
+ )
+ );
+ $subgroup_create_table->addProperty($leaf);
+
+ $leaf = new BoolPropertyItem();
+ $leaf->setName('auto_increment');
+ $leaf->setText(
+ sprintf(__('%s value'), '<code>AUTO_INCREMENT</code>')
+ );
+ $subgroup_create_table->addProperty($leaf);
+
+ $subgroup->addProperty($subgroup_create_table);
// Add view option
$leaf = new BoolPropertyItem();
@@ -293,21 +320,6 @@ class ExportSql extends ExportPlugin
);
$subgroup->addProperty($leaf);
- // begin CREATE TABLE statements
- $subgroup_create_table = new OptionsPropertySubgroup();
- $leaf = new BoolPropertyItem();
- $leaf->setName('create_table_statements');
- $leaf->setText(__('<code>CREATE TABLE</code> options:'));
- $subgroup_create_table->setSubgroupHeader($leaf);
- $leaf = new BoolPropertyItem();
- $leaf->setName('if_not_exists');
- $leaf->setText('<code>IF NOT EXISTS</code>');
- $subgroup_create_table->addProperty($leaf);
- $leaf = new BoolPropertyItem();
- $leaf->setName('auto_increment');
- $leaf->setText('<code>AUTO_INCREMENT</code>');
- $subgroup_create_table->addProperty($leaf);
- $subgroup->addProperty($subgroup_create_table);
$structureOptions->addProperty($subgroup);
$leaf = new BoolPropertyItem();
@@ -621,10 +633,10 @@ class ExportSql extends ExportPlugin
}
// restore connection settings
- $charset_of_file = isset($GLOBALS['charset_of_file'])
- ? $GLOBALS['charset_of_file'] : '';
+ $charset = isset($GLOBALS['charset'])
+ ? $GLOBALS['charset'] : '';
if (! empty($GLOBALS['asfile'])
- && isset($mysql_charset_map[$charset_of_file])
+ && isset($mysql_charset_map[$charset])
&& ! PMA_DRIZZLE
) {
$foot .= $crlf
@@ -728,11 +740,11 @@ class ExportSql extends ExportPlugin
// we are saving as file, therefore we provide charset information
// so that a utility like the mysql client can interpret
// the file correctly
- if (isset($GLOBALS['charset_of_file'])
- && isset($mysql_charset_map[$GLOBALS['charset_of_file']])
+ if (isset($GLOBALS['charset'])
+ && isset($mysql_charset_map[$GLOBALS['charset']])
) {
// we got a charset from the export dialog
- $set_names = $mysql_charset_map[$GLOBALS['charset_of_file']];
+ $set_names = $mysql_charset_map[$GLOBALS['charset']];
} else {
// by default we use the connection charset
$set_names = $mysql_charset_map['utf-8'];
@@ -756,12 +768,13 @@ class ExportSql extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
global $crlf;
@@ -784,7 +797,7 @@ class ExportSql extends ExportPlugin
return false;
}
}
- if (!isset($GLOBALS['sql_create_database'])) {
+ if ($export_type == 'database' && !isset($GLOBALS['sql_create_database'])) {
return true;
}
@@ -812,6 +825,22 @@ class ExportSql extends ExportPlugin
if (! PMA_exportOutputHandler($create_query)) {
return false;
}
+
+ return $this->_exportUseStatement($db_alias, $compat);
+ }
+
+ /**
+ * Outputs USE statement
+ *
+ * @param string $db db to use
+ * @param string $compat sql compatibility
+ *
+ * @return bool Whether it succeeded
+ */
+ private function _exportUseStatement($db, $compat)
+ {
+ global $crlf;
+
if ((isset($GLOBALS['sql_compatibility'])
&& $GLOBALS['sql_compatibility'] == 'NONE')
|| PMA_DRIZZLE
@@ -819,12 +848,12 @@ class ExportSql extends ExportPlugin
$result = PMA_exportOutputHandler(
'USE '
. PMA_Util::backquoteCompat(
- $db_alias, $compat, isset($GLOBALS['sql_backquotes'])
+ $db, $compat, isset($GLOBALS['sql_backquotes'])
)
. ';' . $crlf
);
} else {
- $result = PMA_exportOutputHandler('USE ' . $db_alias . ';' . $crlf);
+ $result = PMA_exportOutputHandler('USE ' . $db . ';' . $crlf);
}
return $result;
}
@@ -893,12 +922,11 @@ class ExportSql extends ExportPlugin
/**
* Exports events
*
- * @param string $db Database
- * @param array $aliases Aliases of db/table/columns
+ * @param string $db Database
*
* @return bool Whether it succeeded
*/
- public function exportEvents($db, $aliases = array())
+ public function exportEvents($db)
{
global $crlf;
@@ -940,6 +968,218 @@ class ExportSql extends ExportPlugin
}
/**
+ * Exports metadata from Configuration Storage
+ *
+ * @param string $db database being exported
+ * @param string|array $tables table(s) being exported
+ * @param array $metadataTypes types of metadata to export
+ * @param array $targetNames associative array of db and table names of
+ * target configuraton storage
+ *
+ * @return bool Whether it succeeded
+ */
+ public function exportMetadata(
+ $db, $tables, $metadataTypes, $targetNames = array()
+ ) {
+ $cfgRelation = PMA_getRelationsParam();
+ if (! isset($cfgRelation['db'])) {
+ return true;
+ }
+
+ $comment = $this->_possibleCRLF()
+ . $this->_possibleCRLF()
+ . $this->_exportComment()
+ . $this->_exportComment(__('Metadata'))
+ . $this->_exportComment();
+ if (! PMA_exportOutputHandler($comment)) {
+ return false;
+ }
+
+ if (! $this->_exportUseStatement(
+ $cfgRelation['db'], $GLOBALS['sql_compatibility']
+ )) {
+ return false;
+ }
+
+ $r = true;
+ if (is_array($tables)) {
+ // export metadata for each table
+ foreach ($tables as $table) {
+ $r &= $this->_exportMetadata($db, $table, $metadataTypes);
+ }
+ // export metadata for the database
+ $r &= $this->_exportMetadata($db, null, $metadataTypes);
+ } else {
+ // export metadata for single table
+ $r &= $this->_exportMetadata($db, $tables, $metadataTypes);
+ }
+
+ return $r;
+ }
+
+ /**
+ * Exports metadata from Configuration Storage
+ *
+ * @param string $db database being exported
+ * @param string $table table being exported
+ * @param array $metadataTypes types of metadata to export
+ * @param array $targetNames associative array of db and table names of
+ * target configuraton storage
+ *
+ * @return bool Whether it succeeded
+ */
+ private function _exportMetadata(
+ $db, $table, $metadataTypes, $targetNames = array()
+ ) {
+ $cfgRelation = PMA_getRelationsParam();
+
+ if (isset($table)) {
+ $types = array(
+ 'column_info' => 'db_name',
+ 'table_uiprefs' => 'db_name',
+ 'tracking' => 'db_name',
+ );
+ } else {
+ $types = array(
+ 'bookmark' => 'dbase',
+ 'relation' => 'master_db',
+ 'pdf_pages' => 'db_name',
+ 'savedsearches' => 'db_name',
+ 'central_columns' => 'db_name',
+ );
+ }
+
+ $aliases = array();
+ foreach ($targetNames as $type => $targetName) {
+ if ($type == 'phpmyadmin') {
+ $aliases[$cfgRelation['db']] = $targetName;
+ continue;
+ }
+
+ if (isset($cfgRelation[$type])) {
+ $aliases[$cfgRelation['db']]['tables'][$cfgRelation[$type]]['alias']
+ = $targetName;
+ }
+ }
+
+ $comment = $this->_possibleCRLF()
+ . $this->_exportComment()
+ . $this->_exportComment(
+ sprintf(
+ __('Metadata for %s'),
+ isset($table) ? $table : $db
+ )
+ )
+ . $this->_exportComment();
+ if (! PMA_exportOutputHandler($comment)) {
+ return false;
+ }
+
+ foreach ($types as $type => $dbNameColumn) {
+ if (in_array($type, $metadataTypes) && isset($cfgRelation[$type])) {
+
+ // special case, designer pages and their coordinates
+ if ($type == 'pdf_pages') {
+
+ $sql_query = "SELECT `page_nr`, `page_descr` FROM "
+ . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation[$type])
+ . " WHERE " . PMA_Util::backquote($dbNameColumn)
+ . " = '" . PMA_Util::sqlAddSlashes($db) . "'";
+
+ $result = $GLOBALS['dbi']->fetchResult(
+ $sql_query, 'page_nr', 'page_descr'
+ );
+
+ foreach ($result as $page => $name) {
+ // insert row for pdf_page
+ $sql_query_row = "SELECT `db_name`, `page_descr` FROM "
+ . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation[$type])
+ . " WHERE " . PMA_Util::backquote($dbNameColumn)
+ . " = '" . PMA_Util::sqlAddSlashes($db) . "'"
+ . " AND `page_nr` = '" . $page . "'";
+
+ if (! $this->exportData(
+ $cfgRelation['db'],
+ $cfgRelation[$type],
+ $GLOBALS['crlf'],
+ '',
+ $sql_query_row,
+ $aliases
+ )) {
+ return false;
+ }
+
+ $lastPage = $GLOBALS['crlf']
+ . "SET @LAST_PAGE = LAST_INSERT_ID();"
+ . $GLOBALS['crlf'] ;
+ if (! PMA_exportOutputHandler($lastPage)) {
+ return false;
+ }
+
+ $sql_query_coords = "SELECT `db_name`, `table_name`, "
+ . "'@LAST_PAGE' AS `pdf_page_number`, `x`, `y` FROM "
+ . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['table_coords'])
+ . " WHERE `pdf_page_number` = '" . $page . "'";
+
+ $GLOBALS['exporting_metadata'] = true;
+ if (! $this->exportData(
+ $cfgRelation['db'],
+ $cfgRelation['table_coords'],
+ $GLOBALS['crlf'],
+ '',
+ $sql_query_coords,
+ $aliases
+ )) {
+ $GLOBALS['exporting_metadata'] = false;
+ return false;
+ }
+ $GLOBALS['exporting_metadata'] = false;
+ }
+ continue;
+ }
+
+ // remove auto_incrementing id field for some tables
+ if ($type == 'bookmark') {
+ $sql_query = "SELECT `dbase`, `user`, `label`, `query` FROM ";
+ } elseif ($type == 'column_info') {
+ $sql_query = "SELECT `db_name`, `table_name`, `column_name`,"
+ . " `comment`, `mimetype`, `transformation`,"
+ . " `transformation_options`, `input_transformation`,"
+ . " `input_transformation_options` FROM";
+ } elseif ($type == 'savedsearches') {
+ $sql_query = "SELECT `username`, `db_name`, `search_name`,"
+ . " `search_data` FROM";
+ } else {
+ $sql_query = "SELECT * FROM ";
+ }
+ $sql_query .= PMA_Util::backquote($cfgRelation['db'])
+ . '.' . PMA_Util::backquote($cfgRelation[$type])
+ . " WHERE " . PMA_Util::backquote($dbNameColumn)
+ . " = '" . PMA_Util::sqlAddSlashes($db) . "'";
+ if (isset($table)) {
+ $sql_query .= " AND `table_name` = '"
+ . PMA_Util::sqlAddSlashes($table) . "'";
+ }
+
+ if (! $this->exportData(
+ $cfgRelation['db'],
+ $cfgRelation[$type],
+ $GLOBALS['crlf'],
+ '',
+ $sql_query,
+ $aliases
+ )) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
* Returns a stand-in CREATE definition to resolve view dependencies
*
* @param string $db the database name
@@ -1192,7 +1432,9 @@ class ExportSql extends ExportPlugin
$schema_create .= $new_crlf;
// no need to generate a DROP VIEW here, it was done earlier
- if (! empty($sql_drop_table) && ! PMA_Table::isView($db, $table)) {
+ if (!empty($sql_drop_table)
+ && !$GLOBALS['dbi']->getTable($db, $table)->isView()
+ ) {
$schema_create .= 'DROP TABLE IF EXISTS '
. PMA_Util::backquote($table_alias, $sql_backquotes) . ';'
. $crlf;
@@ -1229,10 +1471,14 @@ class ExportSql extends ExportPlugin
return $this->_exportComment(__('in use') . '(' . $tmp_error . ')');
}
+ // Old mode is stored so it can be restored once exporting is done.
+ $old_mode = SqlParser\Context::$MODE;
+
$warning = '';
if ($result != false && ($row = $GLOBALS['dbi']->fetchRow($result))) {
$create_query = $row[1];
unset($row);
+
// Convert end of line chars to one that we want (note that MySQL
// doesn't return query it will accept in all cases)
if (/*overload*/mb_strpos($create_query, "(\r\n ")) {
@@ -1257,11 +1503,13 @@ class ExportSql extends ExportPlugin
$create_query
);
}
- // substitute aliases in create query
+
+ // Substitute aliases in `CREATE` query.
$create_query = $this->replaceWithAliases(
$create_query, $aliases, $db, $table, $flag
);
- // One warning per view
+
+ // One warning per view.
if ($flag && $view) {
$warning = $this->_exportComment()
. $this->_exportComment(
@@ -1272,7 +1520,8 @@ class ExportSql extends ExportPlugin
)
. $this->_exportComment();
}
- // Should we use IF NOT EXISTS?
+
+ // Adding IF NOT EXISTS, if required.
if (isset($GLOBALS['sql_if_not_exists'])) {
$create_query = preg_replace(
'/^CREATE TABLE/',
@@ -1281,14 +1530,15 @@ class ExportSql extends ExportPlugin
);
}
+ // Making the query MSSQL compatible.
if ($compat == 'MSSQL') {
$create_query = $this->_makeCreateTableMSSQLCompatible(
$create_query
);
}
- // Drizzle (checked on 2011.03.13) returns ROW_FORMAT surrounded
- // with quotes, which is not accepted by parser
+ // Drizzle (checked on 2011.03.13) returns `ROW_FORMAT`'s value
+ // surrounded with quotes, which is not accepted by parser
if (PMA_DRIZZLE) {
$create_query = preg_replace(
'/ROW_FORMAT=\'(\S+)\'/',
@@ -1297,299 +1547,206 @@ class ExportSql extends ExportPlugin
);
}
- //are there any constraints to cut out?
- if (preg_match('@CONSTRAINT|KEY@', $create_query)) {
- $has_constraints = 0;
- $has_indexes = 0;
+ // Views have no constraints, indexes, etc. They do not require any
+ // analysis.
+ if (!$view) {
- //if there are constraints
- if (preg_match(
- '@CONSTRAINT@',
- $create_query
- )) {
- $has_constraints = 1;
- // comments -> constraints for dumped tables
- $sql_constraints = $this->generateComment(
- $crlf, $sql_constraints, __('Constraints for dumped tables'),
- __('Constraints for table'), $table_alias, $compat
- );
-
- $sql_constraints_query .= 'ALTER TABLE '
- . PMA_Util::backquoteCompat(
- $table_alias, $compat, $sql_backquotes
- )
- . $crlf;
- $sql_constraints .= 'ALTER TABLE '
- . PMA_Util::backquoteCompat(
- $table_alias, $compat, $sql_backquotes
- )
- . $crlf;
- $sql_drop_foreign_keys .= 'ALTER TABLE '
- . PMA_Util::backquoteCompat(
- $db_alias, $compat, $sql_backquotes
- )
- . '.'
- . PMA_Util::backquoteCompat(
- $table_alias, $compat, $sql_backquotes
- )
- . $crlf;
+ // Using appropriate quotes.
+ if (($compat === 'MSSQL') || ($sql_backquotes === '"')) {
+ SqlParser\Context::$MODE |= SqlParser\Context::ANSI_QUOTES;
}
- //if there are indexes
- // (look for KEY followed by whitespace to avoid matching
- // keywords like PACK_KEYS)
- if ($update_indexes_increments && preg_match(
- '@KEY[\s]+@',
- $create_query
- )) {
- $has_indexes = 1;
-
- // comments -> indexes for dumped tables
- $sql_indexes = $this->generateComment(
- $crlf, $sql_indexes, __('Indexes for dumped tables'),
- __('Indexes for table'), $table_alias, $compat
- );
- $sql_indexes_query_start = 'ALTER TABLE '
- . PMA_Util::backquoteCompat(
- $table_alias, $compat, $sql_backquotes
- );
- $sql_indexes_query .= $sql_indexes_query_start;
- $sql_indexes_start = 'ALTER TABLE '
- . PMA_Util::backquoteCompat(
- $table_alias, $compat, $sql_backquotes
- );
- $sql_indexes .= $sql_indexes_start;
- }
- if ($update_indexes_increments && preg_match(
- '@AUTO_INCREMENT@',
- $create_query
- )) {
- // comments -> auto increments for dumped tables
- $sql_auto_increments = $this->generateComment(
- $crlf, $sql_auto_increments,
- __('AUTO_INCREMENT for dumped tables'),
- __('AUTO_INCREMENT for table'), $table_alias, $compat
- );
- $sql_auto_increments .= 'ALTER TABLE '
- . PMA_Util::backquoteCompat(
- $table_alias, $compat, $sql_backquotes
- )
- . $crlf;
- }
+ /**
+ * Parser used for analysis.
+ * @var SqlParser
+ */
+ $parser = new SqlParser\Parser($create_query);
+ }
- // Split the query into lines, so we can easily handle it.
- // We know lines are separated by $crlf (done few lines above).
- $sql_lines = explode($crlf, $create_query);
- $sql_count = count($sql_lines);
-
- // lets find first line with constraints
- $first_occur = -1;
- for ($i = 0; $i < $sql_count; $i++) {
- $sql_line = current(explode(' COMMENT ', $sql_lines[$i], 2));
- if (preg_match(
- '@[\s]+(CONSTRAINT|KEY)@',
- $sql_line
- ) && $first_occur == -1) {
- $first_occur = $i;
+ if (!empty($parser->statements[0]->fields)) {
+
+ /**
+ * `CREATE TABLE` statement.
+ * @var SqlParser\Statements\SelectStatement
+ */
+ $statement = $parser->statements[0];
+
+ /**
+ * Fragments containining definition of each constraint.
+ * @var array
+ */
+ $constraints = array();
+
+ /**
+ * Fragments containining definition of each index.
+ * @var array
+ */
+ $indexes = array();
+
+ /**
+ * Fragments containining definition of each FULLTEXT index.
+ * @var array
+ */
+ $indexes_fulltext = array();
+
+ /**
+ * Fragments containining definition of each foreign key that will
+ * be dropped.
+ * @var array
+ */
+ $dropped = array();
+
+ /**
+ * Fragment containining definition of the `AUTO_INCREMENT`.
+ * @var array
+ */
+ $auto_increment = array();
+
+ // Scanning each field of the `CREATE` statement to fill the arrays
+ // above.
+ // If the field is used in any of the arrays above, it is removed
+ // from the original definition.
+ // Also, AUTO_INCREMENT attribute is removed.
+ /** @var SqlParser\Components\CreateDefinition $field */
+ foreach ($statement->fields as $key => $field) {
+
+ if ($field->isConstraint) {
+ // Creating the parts that add constraints.
+ $constraints[] = $field::build($field);
+ unset($statement->fields[$key]);
+ } elseif (!empty($field->key)) {
+ // Creating the parts that add indexes (must not be
+ // constraints).
+ if ($field->key->type === 'FULLTEXT KEY') {
+ $indexes_fulltext[] = $field->build($field);
+ unset($statement->fields[$key]);
+ } else if (empty($GLOBALS['sql_if_not_exists'])) {
+ $indexes[] = $field->build($field);
+ unset($statement->fields[$key]);
+ }
}
- }
- for ($k = 0; $k < $sql_count; $k++) {
- if ($update_indexes_increments && preg_match(
- '( AUTO_INCREMENT | AUTO_INCREMENT,| AUTO_INCREMENT$)',
- $sql_lines[$k]
- )) {
- //creates auto increment code
- $sql_auto_increments .= " MODIFY " . ltrim($sql_lines[$k]);
- //removes auto increment code from table definition
- $sql_lines[$k] = str_replace(
- " AUTO_INCREMENT", "", $sql_lines[$k]
- );
+ // Creating the parts that drop foreign keys.
+ if (!empty($field->key)) {
+ if ($field->key->type === 'FOREIGN KEY') {
+ $dropped[] = 'FOREIGN KEY ' . SqlParser\Context::escape(
+ $field->name
+ );
+ unset($statement->fields[$key]);
+ }
}
- if (isset($GLOBALS['sql_auto_increment'])
- && $update_indexes_increments && preg_match(
- '@[\s]+(AUTO_INCREMENT=)@',
- $sql_lines[$k]
- )) {
- //adds auto increment value
- $increment_value = /*overload*/mb_substr(
- $sql_lines[$k],
- /*overload*/mb_strpos($sql_lines[$k], "AUTO_INCREMENT")
- );
- $increment_value_array = explode(' ', $increment_value);
- $sql_auto_increments .= $increment_value_array[0] . ";";
+ // Dropping AUTO_INCREMENT.
+ if (!empty($field->options)) {
+ if ($field->options->has('AUTO_INCREMENT')
+ && empty($GLOBALS['sql_if_not_exists'])
+ ) {
+
+ $auto_increment[] = $field::build($field);
+ $field->options->remove('AUTO_INCREMENT');
+ }
}
}
- if ($sql_auto_increments != '') {
- $sql_auto_increments = /*overload*/mb_substr(
- $sql_auto_increments, 0, -1
- ) . ';';
- }
- // If we really found a constraint
- if ($first_occur != $sql_count) {
- // lets find first line
- $sql_lines[$first_occur - 1] = preg_replace(
- '@,$@',
- '',
- $sql_lines[$first_occur - 1]
+ /**
+ * The header of the `ALTER` statement (`ALTER TABLE tbl`).
+ * @var string
+ */
+ $alter_header = 'ALTER TABLE ' .
+ PMA_Util::backquoteCompat(
+ $table_alias, $compat, $sql_backquotes
);
- $first = true;
- $sql_index_ended = false;
- for ($j = $first_occur; $j < $sql_count; $j++) {
- //removes extra space at the beginning, if there is
- $sql_lines[$j]=ltrim($sql_lines[$j], ' ');
+ /**
+ * The footer of the `ALTER` statement (usually ';')
+ * @var string
+ */
+ $alter_footer = ';' . $crlf;
- //if it's a constraint
- if (preg_match(
- '@CONSTRAINT|FOREIGN[\s]+KEY@',
- $sql_lines[$j]
- )) {
- if (! $first) {
- $sql_constraints .= $crlf;
- }
- $posConstraint = /*overload*/mb_strpos(
- $sql_lines[$j],
- 'CONSTRAINT'
- );
- $tmp_str = $sql_lines[$j];
- if (! $sql_backquotes) {
- $matches = array();
- $matched = preg_match(
- '/REFERENCES[\s]([\S]*)[\s]\(([\S]*)\)/',
- $tmp_str,
- $matches
- );
- if ($matched) {
- $refTable = PMA_Util::backquoteCompat(
- $matches[1], $compat, $sql_backquotes
- );
- $refColumn = PMA_Util::backquoteCompat(
- $matches[2], $compat, $sql_backquotes
- );
- $tmp_str = preg_replace(
- '/REFERENCES[\s]([\S]*)[\s]\(([\S]*)\)/',
- 'REFERENCES ' . $refTable . ' (' . $refColumn . ')',
- $tmp_str
- );
- }
- }
- if ($posConstraint === false) {
- $tmp_str = preg_replace(
- '/(FOREIGN[\s]+KEY)/',
- ' ADD \1',
- $tmp_str
- );
+ // Generating constraints-related query.
+ if (!empty($constraints)) {
+ $sql_constraints_query = $alter_header . $crlf . ' ADD '
+ . implode(',' . $crlf . ' ADD ', $constraints)
+ . $alter_footer;
- $sql_constraints_query .= $tmp_str;
- $sql_constraints .= $tmp_str;
+ $sql_constraints = $this->generateComment(
+ $crlf, $sql_constraints, __('Constraints for dumped tables'),
+ __('Constraints for table'), $table_alias, $compat
+ ) . $sql_constraints_query;
+ }
- } else {
- $tmp_str = preg_replace(
- '/(CONSTRAINT)/',
- ' ADD \1',
- $tmp_str
- );
+ // Generating indexes-related query.
+ $sql_indexes_query = '';
- $sql_constraints_query .= $tmp_str;
- $sql_constraints .= $tmp_str;
- preg_match(
- '/(CONSTRAINT)([\s])([\S]*)([\s])/',
- $sql_lines[$j],
- $matches
- );
- if (! $first) {
- $sql_drop_foreign_keys .= ', ';
- }
- $sql_drop_foreign_keys .= 'DROP FOREIGN KEY '
- . $matches[3];
- }
- $first = false;
- } else if ($update_indexes_increments && preg_match(
- '@KEY[\s]+@',
- $sql_lines[$j]
- )) {
- //if it's a index
+ if (!empty($indexes)) {
+ $sql_indexes_query .= $alter_header . $crlf . ' ADD '
+ . implode(',' . $crlf . ' ADD ', $indexes)
+ . $alter_footer;
+ }
- // if index query was terminated earlier
- if ($sql_index_ended) {
- // start a new query with ALTER TABLE
- $sql_indexes .= $sql_indexes_start;
- $sql_indexes_query .= $sql_indexes_query_start;
+ if (!empty($indexes_fulltext)) {
+ // InnoDB supports one FULLTEXT index creation at a time.
+ // So FULLTEXT indexes are created one-by-one after other
+ // indexes where created.
+ $sql_indexes_query .= $alter_header .
+ ' ADD ' . implode(
+ $alter_footer . $alter_header . ' ADD ', $indexes_fulltext
+ ) . $alter_footer;
+ }
- $sql_index_ended = false;
- }
+ if ((!empty($indexes)) || (!empty($indexes_fulltext))) {
+ $sql_indexes = $this->generateComment(
+ $crlf, $sql_indexes, __('Indexes for dumped tables'),
+ __('Indexes for table'), $table_alias, $compat
+ ) . $sql_indexes_query;
+ }
- $tmp_str = $crlf . " ADD " . $sql_lines[$j];
- $sql_indexes_query .= $tmp_str;
- $sql_indexes .= $tmp_str;
-
- // InnoDB supports one FULLTEXT index creation at a time
- // So end the query and start over
- if ($update_indexes_increments && preg_match(
- '@FULLTEXT KEY[\s]+@',
- $sql_lines[$j]
- )) {
- //removes superfluous comma at the end
- $sql_indexes = rtrim($sql_indexes, ',');
- $sql_indexes_query = rtrim($sql_indexes_query, ',');
-
- // add ending semicolon
- $sql_indexes .= ';' . $crlf;
- $sql_indexes_query .= ';' . $crlf;
-
- $sql_index_ended = true;
- }
- } else {
- break;
- }
- }
- //removes superfluous comma at the end
- $sql_indexes = rtrim($sql_indexes, ',');
- $sql_indexes_query = rtrim($sql_indexes_query, ',');
- //removes superfluous semicolon at the end
- if ($has_constraints == 1) {
- $sql_constraints .= ';' . $crlf;
- $sql_constraints_query .= ';';
- }
- if ($has_indexes == 1 && ! $sql_index_ended) {
- $sql_indexes .= ';' . $crlf;
- $sql_indexes_query .= ';';
+ // Generating drop foreign keys-related query.
+ if (!empty($dropped)) {
+ $sql_drop_foreign_keys = $alter_header . $crlf . ' DROP '
+ . implode(',' . $crlf . ' DROP ', $dropped)
+ . $alter_footer;
+ }
+
+ // Generating auto-increment-related query.
+ if ((! empty($auto_increment)) && ($update_indexes_increments)) {
+ $sql_auto_increments_query = $alter_header . $crlf . ' MODIFY '
+ . implode(',' . $crlf . ' MODIFY ', $auto_increment);
+ if (isset($GLOBALS['sql_auto_increment'])
+ && ($statement->entityOptions->has('AUTO_INCREMENT') !== false)
+ ) {
+ $sql_auto_increments_query .= ', AUTO_INCREMENT='
+ . $statement->entityOptions->has('AUTO_INCREMENT');
}
- //remove indexes and constraints from the $create_query
- $create_query = implode(
- $crlf,
- array_slice($sql_lines, 0, $first_occur)
- )
- . $crlf
- . implode(
- $crlf,
- array_slice($sql_lines, $j, $sql_count - 1)
- );
- unset($sql_lines);
+ $sql_auto_increments_query .= ';';
+
+ $sql_auto_increments = $this->generateComment(
+ $crlf, $sql_auto_increments,
+ __('AUTO_INCREMENT for dumped tables'),
+ __('AUTO_INCREMENT for table'), $table_alias, $compat
+ ) . $sql_auto_increments_query;
}
- }
- $schema_create .= $create_query;
- }
- // remove a possible "AUTO_INCREMENT = value" clause
- // that could be there starting with MySQL 5.0.24
- // in Drizzle it's useless as it contains the value given at table
- // creation time
- if (preg_match('/AUTO_INCREMENT\s*=\s*([0-9])+/', $schema_create)) {
- if ($compat == 'MSSQL' || $auto_increment == '') {
- $auto_increment = ' ';
+ // Removing the `AUTO_INCREMENT` attribute from the `CREATE TABLE`
+ // too.
+ if (!empty($statement->entityOptions)
+ && empty($GLOBALS['sql_if_not_exists'])
+ ) {
+ $statement->entityOptions->remove('AUTO_INCREMENT');
+ }
+
+ // Rebuilding the query.
+ $create_query = $statement->build();
}
- $schema_create = preg_replace(
- '/\sAUTO_INCREMENT\s*=\s*([0-9])+\s/',
- $auto_increment,
- $schema_create
- );
+
+ $schema_create .= $create_query;
}
$GLOBALS['dbi']->freeResult($result);
+
+ // Restoring old mode.
+ SqlParser\Context::$MODE = $old_mode;
+
return $warning . $schema_create . ($add_semicolon ? ';' . $crlf : '');
} // end of the 'getTableDef()' function
@@ -1923,7 +2080,7 @@ class ExportSql extends ExportPlugin
// Do not export data for a VIEW, unless asked to export the view as a table
// (For a VIEW, this is called only when exporting a single VIEW)
- if (PMA_Table::isView($db, $table)
+ if ($GLOBALS['dbi']->getTable($db, $table)->isView()
&& empty($GLOBALS['sql_views_as_tables'])
) {
$head = $this->_possibleCRLF()
@@ -2150,6 +2307,10 @@ class ExportSql extends ExportPlugin
)
)
. "'";
+ } elseif (! empty($GLOBALS['exporting_metadata'])
+ && $row[$j] == '@LAST_PAGE'
+ ) {
+ $values[] = '@LAST_PAGE';
} else {
// something else -> treat as a string
$values[] = '\''
@@ -2180,10 +2341,13 @@ class ExportSql extends ExportPlugin
list($tmp_unique_condition, $tmp_clause_is_unique)
= PMA_Util::getUniqueCondition(
- $result,
- $fields_cnt,
- $fields_meta,
- $row
+ $result, // handle
+ $fields_cnt, // fields_cnt
+ $fields_meta, // fields_meta
+ $row, // row
+ false, // force_unique
+ false, // restrict_to_table
+ null // analyzed_sql_results
);
$insert_line .= ' WHERE ' . $tmp_unique_condition;
unset($tmp_unique_condition, $tmp_clause_is_unique);
@@ -2379,216 +2543,166 @@ class ExportSql extends ExportPlugin
$sql_query, $aliases, $db, $table = '', &$flag = null
) {
$flag = false;
- // Return original sql query if no aliases are provided.
- if (!is_array($aliases) || empty($aliases) || empty($sql_query)) {
+
+ /**
+ * The parser of this query.
+ * @var SqlParser\Parser $parser
+ */
+ $parser = new SqlParser\Parser($sql_query);
+
+ if (empty($parser->statements[0])) {
return $sql_query;
}
- $supported_query_types = array(
- 'CREATE' => true,
- );
- $supported_query_ons = array(
- 'TABLE' => true,
- 'VIEW' => true,
- 'TRIGGER' => true,
- 'FUNCTION' => true,
- 'PROCEDURE' => true
- );
- $identifier_types = array(
- 'alpha_identifier',
- 'quote_backtick'
- );
- $query_type = '';
- $query_on = '';
- // Adjustment value for each pos value
- // of token after replacement
- $offset = 0;
- $open_braces = 0;
- $in_create_table_fields = false;
- // flag to force end query parsing
- $query_end = false;
- // Convert all line feeds to Unix style
- $sql_query = str_replace("\r\n", "\n", $sql_query);
- $sql_query = str_replace("\r", "\n", $sql_query);
- $tokens = PMA_SQP_parse($sql_query);
- $ref_seen = false;
- $ref_table_seen = false;
- $old_table = $table;
- $on_seen = false;
- $size = $tokens['len'];
-
- for ($i = 0; $i < $size && !$query_end; $i++) {
- $type = $tokens[$i]['type'];
- $data = $tokens[$i]['data'];
- $data_next = isset($tokens[$i+1]['data'])
- ? $tokens[$i+1]['data'] : '';
- $data_prev = ($i > 0) ? $tokens[$i-1]['data'] : '';
- $d_unq = PMA_Util::unQuote($data);
- $d_unq_next = PMA_Util::unQuote($data_next);
- $d_unq_prev = PMA_Util::unQuote($data_prev);
- $d_upper = /*overload*/mb_strtoupper($d_unq);
- $d_upper_next = /*overload*/mb_strtoupper($d_unq_next);
- $d_upper_prev = /*overload*/mb_strtoupper($d_unq_prev);
- $pos = $tokens[$i]['pos'] + $offset;
- if ($type === 'alpha_reservedWord') {
- if ($query_type === ''
- && !empty($supported_query_types[$d_upper])
- ) {
- $query_type = $d_upper;
- } elseif ($query_on === ''
- && !empty($supported_query_ons[$d_upper])
- ) {
- $query_on = $d_upper;
+
+ /**
+ * The statement that represents the query.
+ * @var SqlParser\Statements\CreateStatement $statement
+ */
+ $statement = $parser->statements[0];
+
+ /**
+ * Old database name.
+ * @var string $old_database
+ */
+ $old_database = $db;
+
+ // Replacing aliases in `CREATE TABLE` statement.
+ if ($statement->options->has('TABLE')) {
+
+ // Extracting the name of the old database and table from the
+ // statement to make sure the parameters are corect.
+ if (!empty($statement->name->database)) {
+ $old_database = $statement->name->database;
+ }
+
+ /**
+ * Old table name.
+ * @var string $old_table
+ */
+ $old_table = $statement->name->table;
+
+ // Finding the aliased database name.
+ // The database might be empty so we have to add a few checks.
+ $new_database = null;
+ if (!empty($statement->name->database)) {
+ $new_database = $statement->name->database;
+ if (!empty($aliases[$old_database]['alias'])) {
+ $new_database = $aliases[$old_database]['alias'];
}
}
- // CREATE TABLE - Alias replacement
- if ($query_type === 'CREATE' && $query_on === 'TABLE') {
- // replace create table name
- if (!$in_create_table_fields
- && in_array($type, $identifier_types)
- && !empty($aliases[$db]['tables'][$table]['alias'])
- ) {
- $sql_query = $this->substituteAlias(
- $sql_query, $data,
- $aliases[$db]['tables'][$table]['alias'],
- $pos, $offset
- );
- $flag = true;
- } elseif ($type === 'punct_bracket_open_round') {
- // CREATE TABLE fields started
- if (!$in_create_table_fields) {
- $in_create_table_fields = true;
- }
- $open_braces++;
- } elseif ($type === 'punct_bracket_close_round') {
- // end our parsing after last )
- // no columns appear after that
- if ($in_create_table_fields && $open_braces === 0) {
- $query_end = true;
- }
- // End of Foreign key reference
- if ($ref_seen) {
- $ref_seen = $ref_table_seen = false;
- $table = $old_table;
- }
- $open_braces--;
- // handles Foreign key references
- } elseif ($type === 'alpha_reservedWord'
- && $d_upper === 'REFERENCES'
- ) {
- $ref_seen = true;
- } elseif (in_array($type, $identifier_types)
- && $ref_seen === true && !$ref_table_seen
- ) {
- $table = $d_unq;
- $ref_table_seen = true;
- if (!empty($aliases[$db]['tables'][$table]['alias'])) {
- $sql_query = $this->substituteAlias(
- $sql_query, $data,
- $aliases[$db]['tables'][$table]['alias'],
- $pos, $offset
- );
+
+ // Finding the aliases table name.
+ $new_table = $old_table;
+ if (!empty($aliases[$old_database]['tables'][$old_table]['alias'])) {
+ $new_table = $aliases[$old_database]['tables'][$old_table]['alias'];
+ }
+
+ // Replacing new values.
+ if (($statement->name->database !== $new_database)
+ || ($statement->name->table !== $new_table)
+ ) {
+ $statement->name->database = $new_database;
+ $statement->name->table = $new_table;
+ $statement->name->expr = null; // Force rebuild.
+ $flag = true;
+ }
+
+ foreach ($statement->fields as $field) {
+
+ // Column name.
+ if (!empty($field->type)) {
+ if (!empty($aliases[$old_database]['tables'][$old_table]['columns'][$field->name])) {
+ $field->name = $aliases[$old_database]['tables']
+ [$old_table]['columns'][$field->name];
$flag = true;
}
- // Replace column names
- } elseif (in_array($type, $identifier_types)
- && !empty($aliases[$db]['tables'][$table]['columns'][$d_unq])
- ) {
- $sql_query = $this->substituteAlias(
- $sql_query, $data,
- $aliases[$db]['tables'][$table]['columns'][$d_unq],
- $pos, $offset
- );
- $flag = true;
}
- // CREATE TRIGGER - Alias replacement
- } elseif ($query_type === 'CREATE' && $query_on === 'TRIGGER') {
- // Skip till 'ON' in encountered
- if (!$on_seen && $type === 'alpha_reservedWord'
- && $d_upper === 'ON'
- ) {
- $on_seen = true;
- } elseif ($on_seen && in_array($type, $identifier_types)) {
- if (!$ref_table_seen
- && !empty($aliases[$db]['tables'][$d_unq]['alias'])
- ) {
- $ref_table_seen = true;
- $sql_query = $this->substituteAlias(
- $sql_query, $data,
- $aliases[$db]['tables'][$d_unq]['alias'],
- $pos, $offset
- );
+
+ // Key's columns.
+ if (!empty($field->key)) {
+ foreach ($field->key->columns as $key => $column) {
+ if (!empty($aliases[$old_database]['tables'][$old_table]['columns'][$column])) {
+ $field->key->columns[$key] = $aliases[$old_database]
+ ['tables'][$old_table]['columns'][$column];
+ $flag = true;
+ }
+ }
+ }
+
+ // References.
+ if (!empty($field->references)) {
+ $ref_table = $field->references->table;
+ // Replacing table.
+ if (!empty($aliases[$old_database]['tables'][$ref_table]['alias'])) {
+ $field->references->table
+ = $aliases[$old_database]['tables'][$ref_table]['alias'];
$flag = true;
- } else {
- // search for identifier alias
- $alias = $this->getAlias($aliases, $d_unq);
- if (!empty($alias)) {
- $sql_query = $this->substituteAlias(
- $sql_query, $data, $alias, $pos, $offset
- );
+ }
+ // Replacing column names.
+ foreach ($field->references->columns as $key => $column) {
+ if (!empty($aliases[$old_database]['tables'][$ref_table]['columns'][$column])) {
+ $field->references->columns[$key] = $aliases[$old_database]['tables'][$ref_table]['columns'][$column];
$flag = true;
}
}
}
- // CREATE PROCEDURE|FUNCTION|VIEW - Alias replacement
- } elseif ($query_type === 'CREATE'
- && ($query_on === 'FUNCTION'
- || $query_on === 'PROCEDURE'
- || $query_on === 'VIEW')
- ) {
- // LANGUAGE SQL | (READS|MODIFIES) SQL DATA
- // characteristics are skipped
- if ($type === 'alpha_identifier'
- && (($d_upper === 'LANGUAGE' && $d_upper_next === 'SQL')
- || ($d_upper === 'DATA' && $d_upper_prev === 'SQL'))
- ) {
- continue;
- // No need to process further in case of VIEW
- // when 'WITH' keyword has been detected
- } elseif ($query_on === 'VIEW'
- && $type === 'alpha_reservedWord' && $d_upper === 'WITH'
+ }
+ } elseif ($statement->options->has('TRIGGER')) {
+
+ // Extracting the name of the old database and table from the
+ // statement to make sure the parameters are corect.
+ if (!empty($statement->table->database)) {
+ $old_database = $statement->table->database;
+ }
+
+ /**
+ * Old table name.
+ * @var string $old_table
+ */
+ $old_table = $statement->table->table;
+
+ if (!empty($aliases[$old_database]['tables'][$old_table]['alias'])) {
+ $statement->table->table
+ = $aliases[$old_database]['tables'][$old_table]['alias'];
+ $statement->table->expr = null; // Force rebuild.
+ $flag = true;
+ }
+ }
+
+ if (($statement->options->has('TRIGGER'))
+ || ($statement->options->has('PROCEDURE'))
+ || ($statement->options->has('FUNCTION'))
+ || ($statement->options->has('VIEW'))
+ ) {
+
+ // Repalcing the body.
+ for ($i = 0, $count = count($statement->body); $i < $count; ++$i) {
+
+ /**
+ * Token parsed at this moment.
+ * @var Token $token
+ */
+ $token = $statement->body[$i];
+
+ // Replacing only symbols (that are not variables) and unknown
+ // identifiers.
+ if ((($token->type === SqlParser\Token::TYPE_SYMBOL)
+ && (!($token->flags & SqlParser\Token::FLAG_SYMBOL_VARIABLE)))
+ || ((($token->type === SqlParser\Token::TYPE_KEYWORD)
+ && (!($token->flags & SqlParser\Token::FLAG_KEYWORD_RESERVED)))
+ || ($token->type === SqlParser\Token::TYPE_NONE))
) {
- $query_end = true;
- } elseif (in_array($type, $identifier_types)) {
- // search for identifier alias
- $alias = $this->getAlias($aliases, $d_unq);
+ $alias = $this->getAlias($aliases, $token->value);
if (!empty($alias)) {
- $sql_query = $this->substituteAlias(
- $sql_query, $data, $alias, $pos, $offset
- );
+ // Replacing the token.
+ $token->token = SqlParser\Context::escape($alias);
$flag = true;
- };
+ }
}
}
}
- return $sql_query;
- }
- /**
- * substitutes alias in query at given position
- * Note: pos is the value from PMA_SQP_parse() + offset
- *
- * @param string $sql_query the SQL query
- * @param string $data the data to be replaced
- * @param string $alias the replacement
- * @param string $pos the position of alias
- * @param string &$offset the change in pos occurred after substitution
- *
- * @return string replaced query with alias
- */
- public function substituteAlias($sql_query, $data, $alias, $pos, &$offset = null)
- {
- if (!empty($GLOBALS['sql_backquotes'])) {
- $alias = PMA_Util::backquote($alias);
- }
- $alias_len = /*overload*/mb_strlen($alias);
- $data_len = /*overload*/mb_strlen($data);
- if (isset($offset)) {
- $offset += ($alias_len - $data_len);
- }
- $sql_query = substr_replace(
- $sql_query, $alias, $pos - $data_len, $data_len
- );
- return $sql_query;
+ return $statement->build();
}
/**
diff --git a/libraries/plugins/export/ExportTexytext.class.php b/libraries/plugins/export/ExportTexytext.class.php
index 64f2260b69..e9dc3c33a3 100644
--- a/libraries/plugins/export/ExportTexytext.class.php
+++ b/libraries/plugins/export/ExportTexytext.class.php
@@ -101,7 +101,7 @@ class ExportTexytext extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
return true;
}
@@ -111,7 +111,7 @@ class ExportTexytext extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
return true;
}
@@ -124,7 +124,7 @@ class ExportTexytext extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
if (empty($db_alias)) {
$db_alias = $db;
@@ -141,7 +141,7 @@ class ExportTexytext extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -149,12 +149,13 @@ class ExportTexytext extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Alias of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -313,7 +314,7 @@ class ExportTexytext extends ExportPlugin
*
* @return string resulting schema
*/
- function getTableDef(
+ public function getTableDef(
$db,
$table,
$crlf,
@@ -419,7 +420,7 @@ class ExportTexytext extends ExportPlugin
*
* @return string Formatted triggers list
*/
- function getTriggers($db, $table)
+ public function getTriggers($db, $table)
{
$dump = "|------\n";
$dump .= '|' . __('Name');
@@ -469,7 +470,7 @@ class ExportTexytext extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- function exportStructure(
+ public function exportStructure(
$db,
$table,
$crlf,
@@ -530,7 +531,7 @@ class ExportTexytext extends ExportPlugin
*
* @return string Formatted column definition
*/
- function formatOneColumnDefinition(
+ public function formatOneColumnDefinition(
$column, $unique_keys, $col_alias = ''
) {
if (empty($col_alias)) {
@@ -572,4 +573,3 @@ class ExportTexytext extends ExportPlugin
return $definition;
}
}
-?>
diff --git a/libraries/plugins/export/ExportXml.class.php b/libraries/plugins/export/ExportXml.class.php
index 7d8048bc40..62cb15806d 100644
--- a/libraries/plugins/export/ExportXml.class.php
+++ b/libraries/plugins/export/ExportXml.class.php
@@ -153,7 +153,7 @@ class ExportXml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
$this->initSpecificVariables();
global $crlf, $cfg, $db;
@@ -168,7 +168,7 @@ class ExportXml extends ExportPlugin
$export_data = isset($GLOBALS['xml_export_contents']) ? true : false;
if ($GLOBALS['output_charset_conversion']) {
- $charset = $GLOBALS['charset_of_file'];
+ $charset = $GLOBALS['charset'];
} else {
$charset = 'utf-8';
}
@@ -237,7 +237,7 @@ class ExportXml extends ExportPlugin
);
$tbl = $result[$table][1];
- $is_view = PMA_Table::isView($db, $table);
+ $is_view = $GLOBALS['dbi']->getTable($db, $table)->isView();
if ($is_view) {
$type = 'view';
@@ -393,7 +393,7 @@ class ExportXml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
$foot = '</pma_xml_export>';
@@ -408,7 +408,7 @@ class ExportXml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
global $crlf;
@@ -437,7 +437,7 @@ class ExportXml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
global $crlf;
@@ -453,12 +453,13 @@ class ExportXml extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -581,4 +582,3 @@ class ExportXml extends ExportPlugin
$this->_tables = $tables;
}
}
-?>
diff --git a/libraries/plugins/export/ExportYaml.class.php b/libraries/plugins/export/ExportYaml.class.php
index c1ed28bbc7..ae8d4d6b12 100644
--- a/libraries/plugins/export/ExportYaml.class.php
+++ b/libraries/plugins/export/ExportYaml.class.php
@@ -75,7 +75,7 @@ class ExportYaml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportHeader ()
+ public function exportHeader()
{
PMA_exportOutputHandler(
'%YAML 1.1' . $GLOBALS['crlf'] . '---' . $GLOBALS['crlf']
@@ -88,7 +88,7 @@ class ExportYaml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportFooter ()
+ public function exportFooter()
{
PMA_exportOutputHandler('...' . $GLOBALS['crlf']);
return true;
@@ -102,7 +102,7 @@ class ExportYaml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBHeader ($db, $db_alias = '')
+ public function exportDBHeader($db, $db_alias = '')
{
return true;
}
@@ -114,7 +114,7 @@ class ExportYaml extends ExportPlugin
*
* @return bool Whether it succeeded
*/
- public function exportDBFooter ($db)
+ public function exportDBFooter($db)
{
return true;
}
@@ -122,12 +122,13 @@ class ExportYaml extends ExportPlugin
/**
* Outputs CREATE DATABASE statement
*
- * @param string $db Database name
- * @param string $db_alias Aliases of db
+ * @param string $db Database name
+ * @param string $export_type 'server', 'database', 'table'
+ * @param string $db_alias Aliases of db
*
* @return bool Whether it succeeded
*/
- public function exportDBCreate($db, $db_alias = '')
+ public function exportDBCreate($db, $export_type, $db_alias = '')
{
return true;
}
@@ -209,4 +210,3 @@ class ExportYaml extends ExportPlugin
return true;
} // end getTableYAML
}
-?>
diff --git a/libraries/plugins/export/PMA_ExportPdf.class.php b/libraries/plugins/export/PMA_ExportPdf.class.php
index 39eb59cd74..3d9848f331 100644
--- a/libraries/plugins/export/PMA_ExportPdf.class.php
+++ b/libraries/plugins/export/PMA_ExportPdf.class.php
@@ -35,7 +35,7 @@ class PMA_ExportPdf extends PMA_PDF
*
* @return boolean true in case of page break, false otherwise.
*/
- function checkPageBreak($h = 0, $y = '', $addpage = true)
+ public function checkPageBreak($h = 0, $y = '', $addpage = true)
{
if (TCPDF_STATIC::empty_string($y)) {
$y = $this->y;
@@ -84,7 +84,7 @@ class PMA_ExportPdf extends PMA_PDF
*
* @return void
*/
- function Header()
+ public function Header()
{
global $maxY;
// We don't want automatic page breaks while generating header
@@ -114,7 +114,8 @@ class PMA_ExportPdf extends PMA_PDF
0,
$this->FontSizePt,
__('Database:') . ' ' . $this->dbAlias . ', '
- . __('Table:') . ' ' . $this->tableAlias,
+ . __('Table:') . ' ' . $this->tableAlias . ', '
+ . __('Purpose:') . ' ' . $this->purpose,
0, 1, 'L'
);
$l = ($this->lMargin);
@@ -168,7 +169,7 @@ class PMA_ExportPdf extends PMA_PDF
*
* @return void
*/
- function morepagestable($lineheight = 8)
+ public function morepagestable($lineheight = 8)
{
// some things to set and 'remember'
$l = $this->lMargin;
@@ -253,7 +254,7 @@ class PMA_ExportPdf extends PMA_PDF
*
* @return void
*/
- function setAttributes($attr = array())
+ public function setAttributes($attr = array())
{
foreach ($attr as $key => $val) {
$this->$key = $val ;
@@ -268,19 +269,390 @@ class PMA_ExportPdf extends PMA_PDF
*
* @return void
*/
- function setTopMargin($topMargin)
+ public function setTopMargin($topMargin)
{
$this->tMargin = $topMargin;
}
/**
+ * Prints triggers
+ *
+ * @param string $db database name
+ * @param string $table table name
+ *
+ * @return void
+ */
+ public function getTriggers($db, $table)
+ {
+ $i = 0;
+ $triggers = $GLOBALS['dbi']->getTriggers($db, $table);
+ foreach ($triggers as $trigger) {
+ $i++; break;
+ }
+ if ($i == 0) {
+ return; //prevents printing blank trigger list for any table
+ }
+
+ unset($this->tablewidths);
+ unset($this->colTitles);
+ unset($this->titleWidth);
+ unset($this->colFits);
+ unset($this->display_column);
+ unset($this->colAlign);
+
+ /**
+ * Making table heading
+ * Keeping column width constant
+ */
+ $this->colTitles[0] = __('Name');
+ $this->tablewidths[0] = 90;
+ $this->colTitles[1] = __('Time');
+ $this->tablewidths[1] = 80;
+ $this->colTitles[2] = __('Event');
+ $this->tablewidths[2] = 40;
+ $this->colTitles[3] = __('Definition');
+ $this->tablewidths[3] = 240;
+
+ for ($columns_cnt = 0; $columns_cnt < 4; $columns_cnt++) {
+ $this->colAlign[$columns_cnt] = 'L';
+ $this->display_column[$columns_cnt] = true;
+ }
+
+ // Starting to fill table with required info
+
+ $this->setY($this->tMargin);
+ $this->AddPage();
+ $this->SetFont(PMA_PDF_FONT, '', 9);
+
+ $l = $this->lMargin;
+ $startheight = $h = $this->dataY;
+ $startpage = $currpage = $this->page;
+
+ // calculate the whole width
+ $fullwidth = 0;
+ foreach ($this->tablewidths as $width) {
+ $fullwidth += $width;
+ }
+
+ $row = 0;
+ $tmpheight = array();
+ $maxpage = $this->page;
+ $data = array();
+
+ $triggers = $GLOBALS['dbi']->getTriggers($db, $table);
+
+ foreach ($triggers as $trigger) {
+ $data[] = $trigger['name'];
+ $data[] = $trigger['action_timing'];
+ $data[] = $trigger['event_manipulation'];
+ $data[] = $trigger['definition'];
+ $this->page = $currpage;
+ // write the horizontal borders
+ $this->Line($l, $h, $fullwidth+$l, $h);
+ // write the content and remember the height of the highest col
+ foreach ($data as $col => $txt) {
+ $this->page = $currpage;
+ $this->SetXY($l, $h);
+ if ($this->tablewidths[$col] > 0) {
+ $this->MultiCell(
+ $this->tablewidths[$col],
+ $this->FontSizePt,
+ $txt,
+ 0,
+ $this->colAlign[$col]
+ );
+ $l += $this->tablewidths[$col];
+ }
+
+ if (! isset($tmpheight[$row . '-' . $this->page])) {
+ $tmpheight[$row . '-' . $this->page] = 0;
+ }
+ if ($tmpheight[$row . '-' . $this->page] < $this->GetY()) {
+ $tmpheight[$row . '-' . $this->page] = $this->GetY();
+ }
+ if ($this->page > $maxpage) {
+ $maxpage = $this->page;
+ }
+ }
+ // get the height we were in the last used page
+ $h = $tmpheight[$row . '-' . $maxpage];
+ // set the "pointer" to the left margin
+ $l = $this->lMargin;
+ // set the $currpage to the last page
+ $currpage = $maxpage;
+ unset($data);
+ $row++;
+ }
+ // draw the borders
+ // we start adding a horizontal line on the last page
+ $this->page = $maxpage;
+ $this->Line($l, $h, $fullwidth+$l, $h);
+ // now we start at the top of the document and walk down
+ for ($i = $startpage; $i <= $maxpage; $i++) {
+ $this->page = $i;
+ $l = $this->lMargin;
+ $t = ($i == $startpage) ? $startheight : $this->tMargin;
+ $lh = ($i == $maxpage) ? $h : $this->h-$this->bMargin;
+ $this->Line($l, $t, $l, $lh);
+ foreach ($this->tablewidths as $width) {
+ $l += $width;
+ $this->Line($l, $t, $l, $lh);
+ }
+ }
+ // set it to the last page, if not it'll cause some problems
+ $this->page = $maxpage;
+ }
+
+ /**
+ * Print $table's CREATE definition
+ *
+ * @param string $db the database name
+ * @param string $table the table name
+ * @param bool $do_relation whether to include relation comments
+ * @param bool $do_comments whether to include the pmadb-style column
+ * comments as comments in the structure;
+ * this is deprecated but the parameter is
+ * left here because export.php calls
+ * PMA_exportStructure() also for other
+ * export types which use this parameter
+ * @param bool $do_mime whether to include mime comments
+ * @param bool $view whether we're handling a view
+ * @param array $aliases aliases of db/table/columns
+ *
+ * @return void
+ */
+ public function getTableDef(
+ $db,
+ $table,
+ $do_relation,
+ $do_comments,
+ $do_mime,
+ $view = false,
+ $aliases = array()
+ ) {
+ // set $cfgRelation here, because there is a chance that it's modified
+ // since the class initialization
+ global $cfgRelation;
+
+ unset($this->tablewidths);
+ unset($this->colTitles);
+ unset($this->titleWidth);
+ unset($this->colFits);
+ unset($this->display_column);
+ unset($this->colAlign);
+
+ /**
+ * Gets fields properties
+ */
+ $GLOBALS['dbi']->selectDb($db);
+
+ /**
+ * All these three checks do_relation, do_comment and do_mime is
+ * not required. As presently all are set true by default.
+ * But when, methods to take user input will be developed,
+ * it will be of use
+ */
+ // Check if we can use Relations
+ if ($do_relation) {
+ // Find which tables are related with the current one and write it in
+ // an array
+ $res_rel = PMA_getForeigners($db, $table);
+ $have_rel = !empty($res_rel);
+ } else {
+ $have_rel = false;
+ } // end if
+
+ //column count and table heading
+
+ $this->colTitles[0] = __('Column');
+ $this->tablewidths[0] = 90;
+ $this->colTitles[1] = __('Type');
+ $this->tablewidths[1] = 80;
+ $this->colTitles[2] = __('Null');
+ $this->tablewidths[2] = 40;
+ $this->colTitles[3] = __('Default');
+ $this->tablewidths[3] = 120;
+
+ for ($columns_cnt = 0; $columns_cnt < 4; $columns_cnt++) {
+ $this->colAlign[$columns_cnt] = 'L';
+ $this->display_column[$columns_cnt] = true;
+ }
+
+ if ($do_relation && $have_rel) {
+ $this->colTitles[$columns_cnt] = __('Links to');
+ $this->display_column[$columns_cnt] = true;
+ $this->colAlign[$columns_cnt] = 'L';
+ $this->tablewidths[$columns_cnt] = 120;
+ $columns_cnt++;
+ }
+ if ($do_comments /*&& $cfgRelation['commwork']*/) {
+ $this->colTitles[$columns_cnt] = __('Comments');
+ $this->display_column[$columns_cnt] = true;
+ $this->colAlign[$columns_cnt] = 'L';
+ $this->tablewidths[$columns_cnt] = 120;
+ $columns_cnt++;
+ }
+ if ($do_mime && $cfgRelation['mimework']) {
+ $this->colTitles[$columns_cnt] = __('MIME');
+ $this->display_column[$columns_cnt] = true;
+ $this->colAlign[$columns_cnt] = 'L';
+ $this->tablewidths[$columns_cnt] = 120;
+ $columns_cnt++;
+ }
+
+ // Starting to fill table with required info
+
+ $this->setY($this->tMargin);
+ $this->AddPage();
+ $this->SetFont(PMA_PDF_FONT, '', 9);
+
+ // Now let's start to write the table structure
+
+ if ($do_comments) {
+ $comments = PMA_getComments($db, $table);
+ }
+ if ($do_mime && $cfgRelation['mimework']) {
+ $mime_map = PMA_getMIME($db, $table, true);
+ }
+
+ $columns = $GLOBALS['dbi']->getColumns($db, $table);
+ /**
+ * Get the unique keys in the table.
+ * Presently, this information is not used. We will have to find out
+ * way of displaying it.
+ */
+ $unique_keys = array();
+ $keys = $GLOBALS['dbi']->getTableIndexes($db, $table);
+ foreach ($keys as $key) {
+ if ($key['Non_unique'] == 0) {
+ $unique_keys[] = $key['Column_name'];
+ }
+ }
+
+ // some things to set and 'remember'
+ $l = $this->lMargin;
+ $startheight = $h = $this->dataY;
+ $startpage = $currpage = $this->page;
+ // calculate the whole width
+ $fullwidth = 0;
+ foreach ($this->tablewidths as $width) {
+ $fullwidth += $width;
+ }
+
+ $row = 0;
+ $tmpheight = array();
+ $maxpage = $this->page;
+ $data = array();
+
+ // fun begin
+ foreach ($columns as $column) {
+ $extracted_columnspec
+ = PMA_Util::extractColumnSpec($column['Type']);
+
+ $type = $extracted_columnspec['print_type'];
+ if (empty($type)) {
+ $type = ' ';
+ }
+
+ if (! isset($column['Default'])) {
+ if ($column['Null'] != 'NO') {
+ $column['Default'] = 'NULL';
+ }
+ }
+ $data [] = $column['Field'];
+ $data [] = $type;
+ $data [] = ($column['Null'] == '' || $column['Null'] == 'NO')
+ ? 'No'
+ : 'Yes';
+ $data [] = isset($column['Default']) ? $column['Default'] : '';
+
+ $field_name = $column['Field'];
+
+ if ($do_relation && $have_rel) {
+ $data [] = isset($res_rel[$field_name])
+ ? $res_rel[$field_name]['foreign_table']
+ . ' (' . $res_rel[$field_name]['foreign_field']
+ . ')'
+ : '';
+ }
+ if ($do_comments) {
+ $data [] = isset($comments[$field_name])
+ ? $comments[$field_name]
+ : '';
+ }
+ if ($do_mime) {
+ $data [] = isset($mime_map[$field_name])
+ ? $mime_map[$field_name]['mimetype']
+ : '';
+ }
+
+ $this->page = $currpage;
+ // write the horizontal borders
+ $this->Line($l, $h, $fullwidth+$l, $h);
+ // write the content and remember the height of the highest col
+ foreach ($data as $col => $txt) {
+ $this->page = $currpage;
+ $this->SetXY($l, $h);
+ if ($this->tablewidths[$col] > 0) {
+ $this->MultiCell(
+ $this->tablewidths[$col],
+ $this->FontSizePt,
+ $txt,
+ 0,
+ $this->colAlign[$col]
+ );
+ $l += $this->tablewidths[$col];
+ }
+
+ if (! isset($tmpheight[$row . '-' . $this->page])) {
+ $tmpheight[$row . '-' . $this->page] = 0;
+ }
+ if ($tmpheight[$row . '-' . $this->page] < $this->GetY()) {
+ $tmpheight[$row . '-' . $this->page] = $this->GetY();
+ }
+ if ($this->page > $maxpage) {
+ $maxpage = $this->page;
+ }
+ }
+
+ // get the height we were in the last used page
+ $h = $tmpheight[$row . '-' . $maxpage];
+ // set the "pointer" to the left margin
+ $l = $this->lMargin;
+ // set the $currpage to the last page
+ $currpage = $maxpage;
+ unset($data);
+ $row++;
+
+ }
+ // draw the borders
+ // we start adding a horizontal line on the last page
+ $this->page = $maxpage;
+ $this->Line($l, $h, $fullwidth+$l, $h);
+ // now we start at the top of the document and walk down
+ for ($i = $startpage; $i <= $maxpage; $i++) {
+ $this->page = $i;
+ $l = $this->lMargin;
+ $t = ($i == $startpage) ? $startheight : $this->tMargin;
+ $lh = ($i == $maxpage) ? $h : $this->h-$this->bMargin;
+ $this->Line($l, $t, $l, $lh);
+ foreach ($this->tablewidths as $width) {
+ $l += $width;
+ $this->Line($l, $t, $l, $lh);
+ }
+ }
+ // set it to the last page, if not it'll cause some problems
+ $this->page = $maxpage;
+ }
+
+ /**
* MySQL report
*
* @param string $query Query to execute
*
* @return void
*/
- function mysqlReport($query)
+ public function mysqlReport($query)
{
unset($this->tablewidths);
unset($this->colTitles);
@@ -431,4 +803,3 @@ class PMA_ExportPdf extends PMA_PDF
} // end of mysqlReport function
} // end of PMA_Export_PDF class
-?>
diff --git a/libraries/plugins/export/TableProperty.class.php b/libraries/plugins/export/TableProperty.class.php
index 16d4c5b578..0a21e79671 100644
--- a/libraries/plugins/export/TableProperty.class.php
+++ b/libraries/plugins/export/TableProperty.class.php
@@ -65,7 +65,7 @@ class TableProperty
*
* @param array $row table row
*/
- function __construct($row)
+ public function __construct($row)
{
$this->name = trim($row[0]);
$this->type = trim($row[1]);
@@ -80,7 +80,7 @@ class TableProperty
*
* @return string type
*/
- function getPureType()
+ public function getPureType()
{
$pos = /*overload*/mb_strpos($this->type, "(");
if ($pos > 0) {
@@ -94,7 +94,7 @@ class TableProperty
*
* @return bool true if the key is not null, false otherwise
*/
- function isNotNull()
+ public function isNotNull()
{
return $this->nullable == "NO" ? "true" : "false";
}
@@ -104,7 +104,7 @@ class TableProperty
*
* @return bool true if the key is unique, false otherwise
*/
- function isUnique()
+ public function isUnique()
{
return $this->key == "PRI" || $this->key == "UNI" ? "true" : "false";
}
@@ -114,7 +114,7 @@ class TableProperty
*
* @return string type
*/
- function getDotNetPrimitiveType()
+ public function getDotNetPrimitiveType()
{
if (/*overload*/mb_strpos($this->type, "int") === 0) {
return "int";
@@ -148,7 +148,7 @@ class TableProperty
*
* @return string type
*/
- function getDotNetObjectType()
+ public function getDotNetObjectType()
{
if (/*overload*/mb_strpos($this->type, "int") === 0) {
return "Int32";
@@ -182,7 +182,7 @@ class TableProperty
*
* @return string containing the name of the index
*/
- function getIndexName()
+ public function getIndexName()
{
if (/*overload*/mb_strlen($this->key) > 0) {
return "index=\""
@@ -197,9 +197,9 @@ class TableProperty
*
* @return bool true if the key is primary, false otherwise
*/
- function isPK()
+ public function isPK()
{
- return $this->key=="PRI";
+ return $this->key == "PRI";
}
/**
@@ -209,7 +209,7 @@ class TableProperty
*
* @return string formatted text
*/
- function formatCs($text)
+ public function formatCs($text)
{
$text = str_replace(
"#name#",
@@ -226,7 +226,7 @@ class TableProperty
*
* @return string formatted text
*/
- function formatXml($text)
+ public function formatXml($text)
{
$text = str_replace(
"#name#",
@@ -248,7 +248,7 @@ class TableProperty
*
* @return string formatted text
*/
- function format($text)
+ public function format($text)
{
$text = str_replace(
"#ucfirstName#",
@@ -283,4 +283,3 @@ class TableProperty
return $text;
}
}
-?>
diff --git a/libraries/plugins/import/AbstractImportCsv.class.php b/libraries/plugins/import/AbstractImportCsv.class.php
index 451d245e25..f50ae64c2f 100644
--- a/libraries/plugins/import/AbstractImportCsv.class.php
+++ b/libraries/plugins/import/AbstractImportCsv.class.php
@@ -52,7 +52,12 @@ abstract class AbstractImportCsv extends ImportPlugin
// create common items and add them to the group
$leaf = new BoolPropertyItem();
$leaf->setName("replace");
- $leaf->setText(__('Update data when duplicate keys found on import (add ON DUPLICATE KEY UPDATE)'));
+ $leaf->setText(
+ __(
+ 'Update data when duplicate keys found on import (add ON DUPLICATE '
+ . 'KEY UPDATE)'
+ )
+ );
$generalOptions->addProperty($leaf);
$leaf = new TextPropertyItem();
$leaf->setName("terminated");
@@ -87,4 +92,3 @@ abstract class AbstractImportCsv extends ImportPlugin
return $generalOptions;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/import/ImportCsv.class.php b/libraries/plugins/import/ImportCsv.class.php
index 7ed801a704..1d4196b497 100644
--- a/libraries/plugins/import/ImportCsv.class.php
+++ b/libraries/plugins/import/ImportCsv.class.php
@@ -137,7 +137,11 @@ class ImportCsv extends AbstractImportCsv
$message->addParam(__('Columns enclosed with'), false);
$error = true;
$param_error = true;
- } elseif (/*overload*/mb_strlen($csv_escaped) != 1) {
+ // I could not find a test case where having no escaping characters
+ // confuses this script.
+ // But the parser won't work correctly with strings so we allow just
+ // one character.
+ } elseif (/*overload*/mb_strlen($csv_escaped) > 1) {
$message = PMA_Message::error(
__('Invalid parameter for CSV import: %s')
);
@@ -281,7 +285,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
while ($i < $len) {
@@ -311,7 +315,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
continue;
}
@@ -329,7 +333,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
} else {
$need_end = false;
@@ -357,7 +361,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
if ($csv_enclosed == $csv_escaped
&& ($ch == $csv_terminated
@@ -381,7 +385,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
}
@@ -394,7 +398,7 @@ class ImportCsv extends AbstractImportCsv
$i = $fallbacki;
$ch = mb_substr($buffer, $i, 1);
if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) {
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
break;
}
@@ -408,7 +412,7 @@ class ImportCsv extends AbstractImportCsv
if ($csv_terminated_len > 1
&& $ch == $csv_terminated[0]
) {
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
break;
} else {
@@ -420,7 +424,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
}
}
@@ -439,7 +443,7 @@ class ImportCsv extends AbstractImportCsv
if ($csv_terminated_len > 1
&& $ch == $csv_terminated[0]
) {
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
break;
}
@@ -451,7 +455,7 @@ class ImportCsv extends AbstractImportCsv
$ch = $this->readCsvTerminatedString(
$buffer, $ch, $i, $csv_terminated_len
);
- $i += $csv_terminated_len-1;
+ $i += $csv_terminated_len - 1;
}
}
// If everything went okay, store value
@@ -531,7 +535,8 @@ class ImportCsv extends AbstractImportCsv
$sql .= " ON DUPLICATE KEY UPDATE ";
foreach ($fields as $field) {
$fieldName = PMA_Util::backquote($field['Field']);
- $sql .= $fieldName . " = VALUES(" . $fieldName . "), ";
+ $sql .= $fieldName . " = VALUES(" . $fieldName
+ . "), ";
}
$sql = rtrim($sql, ', ');
}
@@ -578,7 +583,7 @@ class ImportCsv extends AbstractImportCsv
) {
// Fill out column names
for ($i = 0; $i < $max_cols; ++$i) {
- $col_names[] = 'COL ' . ($i+1);
+ $col_names[] = 'COL ' . ($i + 1);
}
}
@@ -650,7 +655,6 @@ class ImportCsv extends AbstractImportCsv
*
* @return string
*/
-
public function readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len)
{
for ($j = 0; $j < $csv_terminated_len - 1; $j++) {
diff --git a/libraries/plugins/import/ImportLdi.class.php b/libraries/plugins/import/ImportLdi.class.php
index c0fabef35d..84200ec5dc 100644
--- a/libraries/plugins/import/ImportLdi.class.php
+++ b/libraries/plugins/import/ImportLdi.class.php
@@ -47,11 +47,11 @@ class ImportLdi extends AbstractImportCsv
$GLOBALS['cfg']['Import']['ldi_local_option'] = false;
$result = $GLOBALS['dbi']->tryQuery(
- 'SHOW VARIABLES LIKE \'local\\_infile\';'
+ 'SELECT @@local_infile;'
);
if ($result != false && $GLOBALS['dbi']->numRows($result) > 0) {
$tmp = $GLOBALS['dbi']->fetchRow($result);
- if ($tmp[1] == 'ON') {
+ if ($tmp[0] == 'ON') {
$GLOBALS['cfg']['Import']['ldi_local_option'] = true;
}
}
diff --git a/libraries/plugins/import/ImportMediawiki.class.php b/libraries/plugins/import/ImportMediawiki.class.php
index a27a054ff1..63c98c78d7 100644
--- a/libraries/plugins/import/ImportMediawiki.class.php
+++ b/libraries/plugins/import/ImportMediawiki.class.php
@@ -134,7 +134,7 @@ class ImportMediawiki extends ImportPlugin
$cur_buffer_line = trim($buffer_lines[$line_nr]);
// If the line is empty, go to the next one
- if ( $cur_buffer_line === '' ) {
+ if ($cur_buffer_line === '' ) {
continue;
}
@@ -216,7 +216,7 @@ class ImportMediawiki extends ImportPlugin
// If the current line contains header cells
// ( marked with '!' ),
// it will be marked as table header
- if ( $in_table_header ) {
+ if ($in_table_header ) {
// Set the header columns
$cur_temp_table_headers = $cur_temp_line;
} else {
@@ -299,7 +299,7 @@ class ImportMediawiki extends ImportPlugin
*
* @return void
*/
- private function _importDataOneTable ($table)
+ private function _importDataOneTable($table)
{
$analyze = $this->_getAnalyze();
if ($analyze) {
@@ -403,8 +403,8 @@ class ImportMediawiki extends ImportPlugin
* Replaces all instances of the '||' separator between delimiters
* in a given string
*
- * @param string $replace the string to be replaced with
- * @param string $subject the text to be replaced
+ * @param string $replace the string to be replaced with
+ * @param string $subject the text to be replaced
*
* @return string with replacements
*/
diff --git a/libraries/plugins/import/ImportOds.class.php b/libraries/plugins/import/ImportOds.class.php
index 8c17914894..b884c13323 100644
--- a/libraries/plugins/import/ImportOds.class.php
+++ b/libraries/plugins/import/ImportOds.class.php
@@ -163,6 +163,7 @@ class ImportOds extends ImportPlugin
);
$GLOBALS['error'] = true;
} else {
+ /** @var SimpleXMLElement $root */
$root = $xml->children('office', true)->{'body'}->{'spreadsheet'};
if (empty($root)) {
$sheets = array();
@@ -187,10 +188,12 @@ class ImportOds extends ImportPlugin
$rows = array();
/* Iterate over tables */
+ /** @var SimpleXMLElement $sheet */
foreach ($sheets as $sheet) {
$col_names_in_first_row = isset($_REQUEST['ods_col_names']);
/* Iterate over rows */
+ /** @var SimpleXMLElement $row */
foreach ($sheet as $row) {
$type = $row->getName();
if (strcmp('table-row', $type)) {
@@ -199,6 +202,7 @@ class ImportOds extends ImportPlugin
/* Iterate over columns */
$cellCount = count($row);
$a = 0;
+ /** @var SimpleXMLElement $cell */
foreach ($row as $cell) {
$a++;
$text = $cell->children('text', true);
@@ -330,9 +334,10 @@ class ImportOds extends ImportPlugin
/**
* Bring accumulated rows into the corresponding table
*/
- $num_tbls = count($tables);
- for ($i = 0; $i < $num_tbls; ++$i) {
- for ($j = 0; $j < count($rows); ++$j) {
+ $num_tables = count($tables);
+ for ($i = 0; $i < $num_tables; ++$i) {
+ $num_rows = count($rows);
+ for ($j = 0; $j < $num_rows; ++$j) {
if (strcmp($tables[$i][TBL_NAME], $rows[$j][TBL_NAME])) {
continue;
}
diff --git a/libraries/plugins/import/ImportShp.class.php b/libraries/plugins/import/ImportShp.class.php
index 6ec26141ef..4149105347 100644
--- a/libraries/plugins/import/ImportShp.class.php
+++ b/libraries/plugins/import/ImportShp.class.php
@@ -208,6 +208,7 @@ class ImportShp extends ImportPlugin
if (isset($gis_type)) {
include_once './libraries/gis/GIS_Factory.class.php';
+ /** @var PMA_GIS_Multilinestring|PMA_GIS_Multipoint|PMA_GIS_Point|PMA_GIS_Polygon $gis_obj */
$gis_obj = PMA_GIS_Factory::factory($gis_type);
} else {
$gis_obj = null;
diff --git a/libraries/plugins/import/ImportSql.class.php b/libraries/plugins/import/ImportSql.class.php
index cf2f098bae..3b080f1797 100644
--- a/libraries/plugins/import/ImportSql.class.php
+++ b/libraries/plugins/import/ImportSql.class.php
@@ -21,103 +21,6 @@ require_once 'libraries/plugins/ImportPlugin.class.php';
*/
class ImportSql extends ImportPlugin
{
- const BIG_VALUE = 2147483647;
- const READ_MB_FALSE = 0;
- const READ_MB_TRUE = 1;
-
- /**
- * @var string SQL delimiter
- */
- private $_delimiter;
-
- /**
- * @var int SQL delimiter length
- */
- private $_delimiterLength;
-
- /**
- * @var bool|int SQL delimiter position or false if not found
- */
- private $_delimiterPosition = false;
-
- /**
- * @var int Query start position
- */
- private $_queryBeginPosition = 0;
-
- /**
- * @var int|false First special chars position or false if not found
- */
- private $_firstSearchChar = null;
-
- /**
- * @var bool Current position is in string
- */
- private $_isInString = false;
-
- /**
- * @var string Quote of current string or null if out of string
- */
- private $_quote = null;
-
- /**
- * @var bool Current position is in comment
- */
- private $_isInComment = false;
-
- /**
- * @var string Current comment opener
- */
- private $_openingComment = null;
-
- /**
- * @var bool Current position is in delimiter definition
- */
- private $_isInDelimiter = false;
-
- /**
- * @var string Delimiter keyword
- */
- private $_delimiterKeyword = 'DELIMITER ';
-
- /**
- * @var int Import should be done using multibytes
- */
- private $_readMb = self::READ_MB_FALSE;
-
- /**
- * @var string Data to parse
- */
- private $_data = null;
-
- /**
- * @var int Length of data to parse
- */
- private $_dataLength = 0;
-
- /**
- * @var array List of string functions
- * @todo Move this part in string functions definition file.
- */
- private $_stringFunctions = array(
- self::READ_MB_FALSE => array(
- 'substr' => 'substr',
- 'strlen' => 'strlen',
- 'strpos' => 'strpos',
- 'strtoupper' => 'strtoupper',
- ),
- self::READ_MB_TRUE => array(
- 'substr' => 'mb_substr',
- 'strlen' => 'mb_strlen',
- 'strpos' => 'mb_strpos',
- 'strtoupper' => 'mb_strtoupper',
- ),
- );
-
- /**
- * @var bool|int List of string functions to use
- */
- private $_stringFctToUse = false;
/**
* Constructor
@@ -189,13 +92,6 @@ class ImportSql extends ImportPlugin
);
$generalOptions->addProperty($leaf);
- $leaf = new BoolPropertyItem();
- $leaf->setName("read_as_multibytes");
- $leaf->setText(
- __('Read as multibytes')
- );
- $generalOptions->addProperty($leaf);
-
// add the main group to the root group
$importSpecificOptions->addProperty($generalOptions);
// set the options for the import plugin property item
@@ -206,181 +102,6 @@ class ImportSql extends ImportPlugin
}
/**
- * Look for end of string
- *
- * @return bool End of string found
- */
- private function _searchStringEnd()
- {
- //Search for closing quote
- $posClosingString = $this->_stringFctToUse['strpos'](
- $this->_data, $this->_quote, $this->_delimiterPosition
- );
-
- if (false === $posClosingString) {
- return false;
- }
-
- //Quotes escaped by quote will be considered as 2 consecutive strings
- //and won't pass in this loop.
- $posEscape = $posClosingString-1;
- while ($this->_stringFctToUse['substr']($this->_data, $posEscape, 1) == '\\'
- ) {
- $posEscape--;
- }
-
- // Odd count means it was escaped
- $quoteEscaped = (((($posClosingString - 1) - $posEscape) % 2) === 1);
-
- //Move after the escaped quote.
- $this->_delimiterPosition = $posClosingString + 1;
-
- if ($quoteEscaped) {
- return true;
- }
-
- $this->_isInString = false;
- $this->_quote = null;
- return true;
- }
-
- /**
- * Return the position of first SQL delimiter or false if no SQL delimiter found.
- *
- * @return int|bool Delimiter position or false if no delimiter found
- */
- private function _findDelimiterPosition()
- {
- $this->_firstSearchChar = null;
- $firstSqlDelimiter = null;
- $matches = null;
-
- /* while not at end of line */
- while ($this->_delimiterPosition < $this->_dataLength) {
- if ($this->_isInString) {
- if (false === $this->_searchStringEnd()) {
- return false;
- }
-
- continue;
- }
-
- if ($this->_isInComment) {
- if (in_array($this->_openingComment, array('#', '-- '))) {
- $posClosingComment = $this->_stringFctToUse['strpos'](
- $this->_data,
- "\n",
- $this->_delimiterPosition
- );
- if (false === $posClosingComment) {
- return false;
- }
- //Move after the end of the line.
- $this->_delimiterPosition = $posClosingComment + 1;
- $this->_isInComment = false;
- $this->_openingComment = null;
- } elseif ('/*' === $this->_openingComment) {
- //Search for closing comment
- $posClosingComment = $this->_stringFctToUse['strpos'](
- $this->_data,
- '*/',
- $this->_delimiterPosition
- );
- if (false === $posClosingComment) {
- return false;
- }
- //Move after closing comment.
- $this->_delimiterPosition = $posClosingComment + 2;
- $this->_isInComment = false;
- $this->_openingComment = null;
- } else {
- //We shouldn't be able to come here.
- //throw new Exception('Unknown case.');
- break;
- }
-
- continue;
- }
-
- if ($this->_isInDelimiter) {
- //Search for new line.
- if (!preg_match(
- "/^(.*)\n/",
- $this->_stringFctToUse['substr'](
- $this->_data,
- $this->_delimiterPosition
- ),
- $matches,
- PREG_OFFSET_CAPTURE
- )) {
- return false;
- }
-
- $this->_setDelimiter($matches[1][0]);
- //Start after delimiter and new line.
- $this->_queryBeginPosition = $this->_delimiterPosition
- + $matches[1][1] + $this->_delimiterLength + 1;
- $this->_delimiterPosition = $this->_queryBeginPosition;
- $this->_isInDelimiter = false;
- $firstSqlDelimiter = null;
- $this->_firstSearchChar = null;
- continue;
- }
-
- $matches = $this->_searchSpecialChars($matches);
-
- $firstSqlDelimiter = $this->_searchSqlDelimiter($firstSqlDelimiter);
-
- if (false === $firstSqlDelimiter && false === $this->_firstSearchChar) {
- return false;
- }
-
- //If first char is delimiter.
- if (false === $this->_firstSearchChar
- || (false !== $firstSqlDelimiter
- && $firstSqlDelimiter < $this->_firstSearchChar)
- ) {
- $this->_delimiterPosition = $firstSqlDelimiter;
- return true;
- }
-
- //Else first char is result of preg_match.
-
- $specialChars = $matches[1][0];
-
- //If string is opened.
- if (in_array($specialChars, array('\'', '"', '`'))) {
- $this->_isInString = true;
- $this->_quote = $specialChars;
- //Move before quote.
- $this->_delimiterPosition = $this->_firstSearchChar + 1;
- continue;
- }
-
- //If comment is opened.
- if (in_array($specialChars, array('#', '-- ', '/*'))) {
- $this->_isInComment = true;
- $this->_openingComment = $specialChars;
- //Move before comment opening.
- $this->_delimiterPosition = $this->_firstSearchChar
- + $this->_stringFctToUse['strlen']($specialChars);
- continue;
- }
-
- //If DELIMITER is found.
- $specialCharsUpper = $this->_stringFctToUse['strtoupper']($specialChars);
- if ($specialCharsUpper === $this->_delimiterKeyword) {
- $this->_isInDelimiter = true;
- $this->_delimiterPosition = $this->_firstSearchChar
- + $this->_stringFctToUse['strlen']($specialChars);
- continue;
- }
- }
-
- return false;
- }
-
- /**
* Handles the whole import logic
*
* @param array &$sql_data 2-element array with sql data
@@ -391,95 +112,64 @@ class ImportSql extends ImportPlugin
{
global $error, $timeout_passed;
- //Manage multibytes or not
- if (isset($_REQUEST['sql_read_as_multibytes'])) {
- $this->_readMb = self::READ_MB_TRUE;
- }
- $this->_stringFctToUse = $this->_stringFunctions[$this->_readMb];
+ // Handle compatibility options.
+ $this->_setSQLMode($GLOBALS['dbi'], $_REQUEST);
+ $bq = new SqlParser\Utils\BufferedQuery();
if (isset($_POST['sql_delimiter'])) {
- $this->_setDelimiter($_POST['sql_delimiter']);
- } else {
- $this->_setDelimiter(';');
+ $bq->setDelimiter($_POST['sql_delimiter']);
}
- // Handle compatibility options
- $this->_setSQLMode($GLOBALS['dbi'], $_REQUEST);
-
- //Initialise data.
- $this->_setData(null);
-
/**
- * will be set in PMA_importGetNextChunk()
- *
- * @global boolean $GLOBALS['finished']
+ * Will be set in PMA_importGetNextChunk().
+ * @global bool $GLOBALS['finished']
*/
$GLOBALS['finished'] = false;
- $delimiterFound = false;
- while (!$error && !$timeout_passed) {
- if (false === $delimiterFound) {
+ while ((!$error) && (!$timeout_passed)) {
+
+ // Getting the first statement, the remaining data and the last
+ // delimiter.
+ $statement = $bq->extract();
+
+ // If there is no full statement, we are looking for more data.
+ if (empty($statement)) {
+
+ // Importing new data.
$newData = PMA_importGetNextChunk();
+
+ // Subtract data we didn't handle yet and stop processing.
if ($newData === false) {
- // subtract data we didn't handle yet and stop processing
- $GLOBALS['offset'] -= $this->_dataLength;
+ $GLOBALS['offset'] -= mb_strlen($bq->query);
break;
}
+ // Checking if the input buffer has finished.
if ($newData === true) {
$GLOBALS['finished'] = true;
break;
}
- //Convert CR (but not CRLF) to LF otherwise all queries
- //may not get executed on some platforms
- $this->_addData(preg_replace("/\r($|[^\n])/", "\n$1", $newData));
- unset($newData);
- }
-
- //Find quotes, comments, delimiter definition or delimiter itself.
- $delimiterFound = $this->_findDelimiterPosition();
+ // Convert CR (but not CRLF) to LF otherwise all queries may
+ // not get executed on some platforms.
+ $bq->query .= preg_replace("/\r($|[^\n])/", "\n$1", $newData);
- //If no delimiter found, restart and get more data.
- if (false === $delimiterFound) {
continue;
}
- PMA_importRunQuery(
- $this->_stringFctToUse['substr'](
- $this->_data,
- $this->_queryBeginPosition,
- $this->_delimiterPosition - $this->_queryBeginPosition
- ), //Query to execute
- $this->_stringFctToUse['substr'](
- $this->_data,
- 0,
- $this->_delimiterPosition + $this->_delimiterLength
- ), //Query to display
- false,
- $sql_data
- );
-
- $this->_setData(
- $this->_stringFctToUse['substr'](
- $this->_data,
- $this->_delimiterPosition + $this->_delimiterLength
- )
- );
+ // Executing the query.
+ PMA_importRunQuery($statement, $statement, false, $sql_data);
}
- if (! $timeout_passed) {
- //Commit any possible data in buffers
- PMA_importRunQuery(
- $this->_stringFctToUse['substr'](
- $this->_data,
- $this->_queryBeginPosition
- ), //Query to execute
- $this->_data,
- false,
- $sql_data
- );
+ // Extracting remaining statements.
+ while ((!$error) && (!$timeout_passed) && (!empty($bq->query))) {
+ $statement = $bq->extract(true);
+ if (!empty($statement)) {
+ PMA_importRunQuery($statement, $statement, false, $sql_data);
+ }
}
+
+ // Finishing.
PMA_importRunQuery('', '', false, $sql_data);
}
@@ -508,113 +198,4 @@ class ImportSql extends ImportPlugin
);
}
}
-
- /**
- * Look for special chars: comment, string or DELIMITER
- *
- * @param array $matches Special chars found in data
- *
- * @return array matches
- */
- private function _searchSpecialChars(
- $matches
- ) {
- //Don't look for a string/comment/"DELIMITER" if not found previously
- //or if it's still after current position.
- if (null === $this->_firstSearchChar
- || (false !== $this->_firstSearchChar
- && $this->_firstSearchChar < $this->_delimiterPosition)
- ) {
- $bFind = preg_match(
- '/(\'|"|#|-- |\/\*|`|(?i)(?<![A-Z0-9_])'
- . $this->_delimiterKeyword . ')/',
- $this->_stringFctToUse['substr'](
- $this->_data,
- $this->_delimiterPosition
- ),
- $matches,
- PREG_OFFSET_CAPTURE
- );
-
- if (1 === $bFind) {
- $this->_firstSearchChar = $matches[1][1] + $this->_delimiterPosition;
- } else {
- $this->_firstSearchChar = false;
- }
- }
- return $matches;
- }
-
- /**
- * Look for SQL delimiter
- *
- * @param int $firstSqlDelimiter First found char position
- *
- * @return int
- */
- private function _searchSqlDelimiter($firstSqlDelimiter)
- {
- //Don't look for the SQL delimiter if not found previously
- //or if it's still after current position.
- if (null === $firstSqlDelimiter
- || (false !== $firstSqlDelimiter
- && $firstSqlDelimiter < $this->_delimiterPosition)
- ) {
- // the cost of doing this one with preg_match() would be too high
- $firstSqlDelimiter = $this->_stringFctToUse['strpos'](
- $this->_data,
- $this->_delimiter,
- $this->_delimiterPosition
- );
- }
-
- return $firstSqlDelimiter;
- }
-
- /**
- * Set new delimiter
- *
- * @param string $delimiter New delimiter
- *
- * @return int delimiter length
- */
- private function _setDelimiter($delimiter)
- {
- $this->_delimiter = $delimiter;
- $this->_delimiterLength = $this->_stringFctToUse['strlen']($delimiter);
-
- return $this->_delimiterLength;
- }
-
- /**
- * Set data to parse
- *
- * @param string $data Data to parse
- *
- * @return int Data length
- */
- private function _setData($data)
- {
- $this->_data = ltrim($data);
- $this->_dataLength = $this->_stringFctToUse['strlen']($this->_data);
- $this->_queryBeginPosition = 0;
- $this->_delimiterPosition = 0;
-
- return $this->_dataLength;
- }
-
- /**
- * Add data to parse
- *
- * @param string $data Data to add to data to parse
- *
- * @return int Data length
- */
- private function _addData($data)
- {
- $this->_data .= $data;
- $this->_dataLength += $this->_stringFctToUse['strlen']($data);
-
- return $this->_dataLength;
- }
}
diff --git a/libraries/plugins/import/ImportXml.class.php b/libraries/plugins/import/ImportXml.class.php
index 6301aa43d7..f6d97170b5 100644
--- a/libraries/plugins/import/ImportXml.class.php
+++ b/libraries/plugins/import/ImportXml.class.php
@@ -193,12 +193,15 @@ class ImportXml extends ImportPlugin
if (isset($namespaces['pma'])) {
/**
* Get structures for all tables
+ * @var SimpleXMLElement $struct
*/
$struct = $xml->children($namespaces['pma']);
$create = array();
+ /** @var SimpleXMLElement $val1 */
foreach ($struct as $val1) {
+ /** @var SimpleXMLElement $val2 */
foreach ($val1 as $val2) {
// Need to select the correct database for the creation of
// tables, views, triggers, etc.
@@ -245,14 +248,15 @@ class ImportXml extends ImportPlugin
$tbl_attr = $v1->attributes();
$isInTables = false;
- for ($i = 0; $i < count($tables); ++$i) {
+ $num_tables = count($tables);
+ for ($i = 0; $i < $num_tables; ++$i) {
if (! strcmp($tables[$i][TBL_NAME], (string)$tbl_attr['name'])) {
$isInTables = true;
break;
}
}
- if ($isInTables == false) {
+ if (!$isInTables) {
$tables[] = array((string)$tbl_attr['name']);
}
@@ -277,9 +281,10 @@ class ImportXml extends ImportPlugin
/**
* Bring accumulated rows into the corresponding table
*/
- $num_tbls = count($tables);
- for ($i = 0; $i < $num_tbls; ++$i) {
- for ($j = 0; $j < count($rows); ++$j) {
+ $num_tables = count($tables);
+ for ($i = 0; $i < $num_tables; ++$i) {
+ $num_rows = count($rows);
+ for ($j = 0; $j < $num_rows; ++$j) {
if (! strcmp($tables[$i][TBL_NAME], $rows[$j][TBL_NAME])) {
if (! isset($tables[$i][COL_NAMES])) {
$tables[$i][] = $rows[$j][COL_NAMES];
diff --git a/libraries/plugins/import/ShapeFile.class.php b/libraries/plugins/import/ShapeFile.class.php
index f807d02775..c3550f9305 100644
--- a/libraries/plugins/import/ShapeFile.class.php
+++ b/libraries/plugins/import/ShapeFile.class.php
@@ -27,7 +27,7 @@ class PMA_ShapeFile extends ShapeFile
*
* @return boolean whether the 'dbase' extension is loaded
*/
- function _isDbaseLoaded()
+ private function _isDbaseLoaded()
{
return extension_loaded('dbase');
}
@@ -41,7 +41,7 @@ class PMA_ShapeFile extends ShapeFile
* @return void
* @see ShapeFile::loadFromFile()
*/
- function loadFromFile($FileName)
+ public function loadFromFile($FileName)
{
$this->_loadHeaders();
$this->_loadRecords();
@@ -56,7 +56,7 @@ class PMA_ShapeFile extends ShapeFile
* @return void
* @see ShapeFile::_loadHeaders()
*/
- function _loadHeaders()
+ public function _loadHeaders()
{
ImportShp::readFromBuffer(24);
$this->fileLength = loadData("N", ImportShp::readFromBuffer(4));
@@ -81,7 +81,7 @@ class PMA_ShapeFile extends ShapeFile
* @return boolean|void
* @see ShapeFile::_loadRecords()
*/
- function _loadRecords()
+ public function _loadRecords()
{
global $eof;
ImportShp::readFromBuffer(32);
@@ -99,4 +99,3 @@ class PMA_ShapeFile extends ShapeFile
}
}
}
-?>
diff --git a/libraries/plugins/import/ShapeRecord.class.php b/libraries/plugins/import/ShapeRecord.class.php
index d73ea76b53..c6d9313b7e 100644
--- a/libraries/plugins/import/ShapeRecord.class.php
+++ b/libraries/plugins/import/ShapeRecord.class.php
@@ -31,7 +31,7 @@ class PMA_ShapeRecord extends ShapeRecord
* @return void
* @see ShapeRecord::loadFromFile()
*/
- function loadFromFile(&$SHPFile, &$DBFFile)
+ public function loadFromFile(&$SHPFile, &$DBFFile)
{
$this->DBFFile = $DBFFile;
$this->_loadHeaders();
@@ -72,7 +72,7 @@ class PMA_ShapeRecord extends ShapeRecord
* @return void
* @see ShapeRecord::_loadHeaders()
*/
- function _loadHeaders()
+ public function _loadHeaders()
{
$this->recordNumber = loadData("N", ImportShp::readFromBuffer(4));
ImportShp::readFromBuffer(4);
@@ -85,7 +85,7 @@ class PMA_ShapeRecord extends ShapeRecord
* @return array
* @see ShapeRecord::_loadPoint()
*/
- function _loadPoint()
+ public function _loadPoint()
{
$data = array();
@@ -101,7 +101,7 @@ class PMA_ShapeRecord extends ShapeRecord
* @return void
* @see ShapeRecord::_loadMultiPointRecord()
*/
- function _loadMultiPointRecord()
+ public function _loadMultiPointRecord()
{
$this->SHPData = array();
$this->SHPData["xmin"] = loadData("d", ImportShp::readFromBuffer(8));
@@ -122,7 +122,7 @@ class PMA_ShapeRecord extends ShapeRecord
* @return void
* @see ShapeRecord::_loadPolyLineRecord()
*/
- function _loadPolyLineRecord()
+ public function _loadPolyLineRecord()
{
$this->SHPData = array();
$this->SHPData["xmin"] = loadData("d", ImportShp::readFromBuffer(8));
@@ -158,4 +158,3 @@ class PMA_ShapeRecord extends ShapeRecord
}
}
}
-?>
diff --git a/libraries/plugins/import/upload/UploadApc.class.php b/libraries/plugins/import/upload/UploadApc.class.php
index 3ddb7a7f84..ab5b579db7 100644
--- a/libraries/plugins/import/upload/UploadApc.class.php
+++ b/libraries/plugins/import/upload/UploadApc.class.php
@@ -81,4 +81,3 @@ class UploadApc implements UploadInterface
return $ret;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/import/upload/UploadNoplugin.class.php b/libraries/plugins/import/upload/UploadNoplugin.class.php
index 90148ded4c..4f5b7e410a 100644
--- a/libraries/plugins/import/upload/UploadNoplugin.class.php
+++ b/libraries/plugins/import/upload/UploadNoplugin.class.php
@@ -61,4 +61,3 @@ class UploadNoplugin implements UploadInterface
return $ret;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/import/upload/UploadProgress.class.php b/libraries/plugins/import/upload/UploadProgress.class.php
index d7647b326a..71af16d48b 100644
--- a/libraries/plugins/import/upload/UploadProgress.class.php
+++ b/libraries/plugins/import/upload/UploadProgress.class.php
@@ -91,4 +91,3 @@ class UploadProgress implements UploadInterface
return $ret;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/import/upload/UploadSession.class.php b/libraries/plugins/import/upload/UploadSession.class.php
index d9bdd53105..2160faddde 100644
--- a/libraries/plugins/import/upload/UploadSession.class.php
+++ b/libraries/plugins/import/upload/UploadSession.class.php
@@ -93,4 +93,3 @@ class UploadSession implements UploadInterface
return $ret;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/Export_Relation_Schema.class.php b/libraries/plugins/schema/Export_Relation_Schema.class.php
index d3618f0568..7faeeb06eb 100644
--- a/libraries/plugins/schema/Export_Relation_Schema.class.php
+++ b/libraries/plugins/schema/Export_Relation_Schema.class.php
@@ -22,14 +22,20 @@ class PMA_Export_Relation_Schema
/**
* Constructor.
*
- * @see PMA_SVG
+ * @param string $db database name
+ * @param object $diagram schema diagram
*/
- function __construct()
+ public function __construct($db, $diagram)
{
+ $this->db = $db;
+ $this->diagram = $diagram;
$this->setPageNumber($_REQUEST['page_number']);
$this->setOffline(isset($_REQUEST['offline_export']));
}
+ protected $db;
+ protected $diagram;
+
protected $showColor;
protected $tableDimension;
protected $sameWide;
@@ -46,8 +52,6 @@ class PMA_Export_Relation_Schema
* @param integer $value Page Number of the document to be created
*
* @return void
- *
- * @access public
*/
public function setPageNumber($value)
{
@@ -92,8 +96,6 @@ class PMA_Export_Relation_Schema
* @param boolean $value show table co-ordinates or not
*
* @return void
- *
- * @access public
*/
public function setTableDimension($value)
{
@@ -116,8 +118,6 @@ class PMA_Export_Relation_Schema
* @param boolean $value set same width of all tables or not
*
* @return void
- *
- * @access public
*/
public function setAllTablesSameWidth($value)
{
@@ -240,7 +240,7 @@ class PMA_Export_Relation_Schema
protected function getTablesFromRequest()
{
$tables = array();
- $dbLength = mb_strlen($GLOBALS['db']);
+ $dbLength = mb_strlen($this->db);
foreach ($_REQUEST['t_h'] as $key => $value) {
if ($value) {
$tables[] = mb_substr($key, $dbLength + 1);
@@ -253,10 +253,12 @@ class PMA_Export_Relation_Schema
* Returns the file name
*
* @param String $extension file extension
+ *
+ * @return string file name
*/
protected function getFileName($extension)
{
- $filename = $GLOBALS['db'] . $extension;
+ $filename = $this->db . $extension;
// Get the name of this page to use as filename
if ($this->pageNumber != -1 && ! $this->offline) {
$_name_sql = 'SELECT page_descr FROM '
@@ -298,4 +300,3 @@ class PMA_Export_Relation_Schema
exit;
}
}
-?>
diff --git a/libraries/plugins/schema/RelationStats.class.php b/libraries/plugins/schema/RelationStats.class.php
index 01b2203905..6e4c2f6715 100644
--- a/libraries/plugins/schema/RelationStats.class.php
+++ b/libraries/plugins/schema/RelationStats.class.php
@@ -21,6 +21,7 @@ if (! defined('PHPMYADMIN')) {
*/
abstract class RelationStats
{
+ protected $diagram;
/**
* Defines properties
*/
@@ -33,14 +34,17 @@ abstract class RelationStats
/**
* The constructor
*
+ * @param object $diagram The diagram
* @param string $master_table The master table name
* @param string $master_field The relation field in the master table
* @param string $foreign_table The foreign table name
* @param string $foreign_field The relation field in the foreign table
*/
- function __construct(
- $master_table, $master_field, $foreign_table, $foreign_field
+ public function __construct(
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
) {
+ $this->diagram = $diagram;
+
$src_pos = $this->_getXy($master_table, $master_field);
$dest_pos = $this->_getXy($foreign_table, $foreign_field);
/*
@@ -105,4 +109,3 @@ abstract class RelationStats
);
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/SchemaDia.class.php b/libraries/plugins/schema/SchemaDia.class.php
index 2b5493bcdb..caec29db63 100644
--- a/libraries/plugins/schema/SchemaDia.class.php
+++ b/libraries/plugins/schema/SchemaDia.class.php
@@ -110,8 +110,7 @@ class SchemaDia extends SchemaPlugin
*/
public function exportSchema($db)
{
- $export = new PMA_Dia_Relation_Schema();
+ $export = new PMA_Dia_Relation_Schema($db);
$export->showOutput();
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/SchemaEps.class.php b/libraries/plugins/schema/SchemaEps.class.php
index c53a778a5b..ce5a848eaa 100644
--- a/libraries/plugins/schema/SchemaEps.class.php
+++ b/libraries/plugins/schema/SchemaEps.class.php
@@ -95,8 +95,7 @@ class SchemaEps extends SchemaPlugin
*/
public function exportSchema($db)
{
- $export = new PMA_Eps_Relation_Schema();
+ $export = new PMA_Eps_Relation_Schema($db);
$export->showOutput();
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/SchemaPdf.class.php b/libraries/plugins/schema/SchemaPdf.class.php
index b9b6ddb240..117c1951f9 100644
--- a/libraries/plugins/schema/SchemaPdf.class.php
+++ b/libraries/plugins/schema/SchemaPdf.class.php
@@ -91,7 +91,19 @@ class SchemaPdf extends SchemaPlugin
$leaf = new BoolPropertyItem();
$leaf->setName('with_doc');
- $leaf->setText(__('Data Dictionary'));
+ $leaf->setText(__('Data dictionary'));
+ $specificOptions->addProperty($leaf);
+
+ $leaf = new SelectPropertyItem();
+ $leaf->setName("table_order");
+ $leaf->setText(__('Order of the tables'));
+ $leaf->setValues(
+ array(
+ '' => __('None'),
+ 'name_asc' => __('Name (Ascending)'),
+ 'name_desc' => __('Name (Descending)'),
+ )
+ );
$specificOptions->addProperty($leaf);
// add the main group to the root group
@@ -125,8 +137,7 @@ class SchemaPdf extends SchemaPlugin
*/
public function exportSchema($db)
{
- $export = new PMA_Pdf_Relation_Schema();
+ $export = new PMA_Pdf_Relation_Schema($db);
$export->showOutput();
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/SchemaSvg.class.php b/libraries/plugins/schema/SchemaSvg.class.php
index e020db06cc..03b20e6007 100644
--- a/libraries/plugins/schema/SchemaSvg.class.php
+++ b/libraries/plugins/schema/SchemaSvg.class.php
@@ -83,8 +83,7 @@ class SchemaSvg extends SchemaPlugin
*/
public function exportSchema($db)
{
- $export = new PMA_Svg_Relation_Schema();
+ $export = new PMA_Svg_Relation_Schema($db);
$export->showOutput();
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/TableStats.class.php b/libraries/plugins/schema/TableStats.class.php
index e81a6a8c13..584874d72f 100644
--- a/libraries/plugins/schema/TableStats.class.php
+++ b/libraries/plugins/schema/TableStats.class.php
@@ -176,4 +176,3 @@ abstract class TableStats
. ' ' . $this->tableName;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/dia/Dia_Relation_Schema.class.php b/libraries/plugins/schema/dia/Dia_Relation_Schema.class.php
index c8619555ee..069a0ed86b 100644
--- a/libraries/plugins/schema/dia/Dia_Relation_Schema.class.php
+++ b/libraries/plugins/schema/dia/Dia_Relation_Schema.class.php
@@ -30,7 +30,7 @@ class PMA_DIA extends XMLWriter
*
* @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument()
*/
- function __construct()
+ public function __construct()
{
$this->openMemory();
/*
@@ -66,7 +66,7 @@ class PMA_DIA extends XMLWriter
* @see XMLWriter::startElement(),XMLWriter::writeAttribute(),
* XMLWriter::writeRaw()
*/
- function startDiaDoc($paper, $topMargin, $bottomMargin, $leftMargin,
+ public function startDiaDoc($paper, $topMargin, $bottomMargin, $leftMargin,
$rightMargin, $orientation
) {
if ($orientation == 'P') {
@@ -153,7 +153,7 @@ class PMA_DIA extends XMLWriter
* @access public
* @see XMLWriter::endElement(),XMLWriter::endDocument()
*/
- function endDiaDoc()
+ public function endDiaDoc()
{
$this->endElement();
$this->endDocument();
@@ -168,7 +168,7 @@ class PMA_DIA extends XMLWriter
* @access public
* @see XMLWriter::flush()
*/
- function showOutput($fileName)
+ public function showOutput($fileName)
{
if (ob_get_clean()) {
ob_end_clean();
@@ -202,9 +202,11 @@ class PMA_DIA extends XMLWriter
class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
{
/**
- * Defines properties
+ * @var Table_Stats_Dia[]|Table_Stats_Eps[]|Table_Stats_Pdf[]|Table_Stats_Svg[]
*/
private $_tables = array();
+
+ /** @var Relation_Stats_Dia[] Relations */
private $_relations = array();
private $_topMargin = 2.8222000598907471;
private $_bottomMargin = 2.8222000598907471;
@@ -218,21 +220,20 @@ class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
* Upon instantiation This outputs the Dia XML document
* that user can download
*
+ * @param string $db database name
+ *
* @see PMA_DIA,Table_Stats_Dia,Relation_Stats_Dia
*/
- function __construct()
+ public function __construct($db)
{
- parent::__construct();
-
- global $dia;
+ parent::__construct($db, new PMA_DIA());
$this->setShowColor(isset($_REQUEST['dia_show_color']));
$this->setShowKeys(isset($_REQUEST['dia_show_keys']));
$this->setOrientation($_REQUEST['dia_orientation']);
$this->setPaper($_REQUEST['dia_paper']);
- $dia = new PMA_DIA();
- $dia->startDiaDoc(
+ $this->diagram->startDiaDoc(
$this->paper, $this->_topMargin, $this->_bottomMargin,
$this->_leftMargin, $this->_rightMargin, $this->orientation
);
@@ -242,14 +243,15 @@ class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
foreach ($alltables as $table) {
if (! isset($this->tables[$table])) {
$this->_tables[$table] = new Table_Stats_Dia(
- $table, $this->pageNumber, $this->showKeys, $this->offline
+ $this->diagram, $this->db, $table, $this->pageNumber,
+ $this->showKeys, $this->offline
);
}
}
$seen_a_relation = false;
foreach ($alltables as $one_table) {
- $exist_rel = PMA_getForeigners($GLOBALS['db'], $one_table, '', 'both');
+ $exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
if (!$exist_rel) {
continue;
}
@@ -290,7 +292,7 @@ class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
if ($seen_a_relation) {
$this->_drawRelations();
}
- $dia->endDiaDoc();
+ $this->diagram->endDiaDoc();
}
/**
@@ -299,10 +301,9 @@ class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
* @return void
* @access public
*/
- function showOutput()
+ public function showOutput()
{
- global $dia;
- $dia->showOutput($this->getFileName('.dia'));
+ $this->diagram->showOutput($this->getFileName('.dia'));
}
/**
@@ -324,17 +325,20 @@ class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
) {
if (! isset($this->_tables[$masterTable])) {
$this->_tables[$masterTable] = new Table_Stats_Dia(
- $masterTable, $this->pageNumber, $showKeys
+ $this->diagram, $this->db, $masterTable, $this->pageNumber, $showKeys
);
}
if (! isset($this->_tables[$foreignTable])) {
$this->_tables[$foreignTable] = new Table_Stats_Dia(
- $foreignTable, $this->pageNumber, $showKeys
+ $this->diagram, $this->db, $foreignTable, $this->pageNumber, $showKeys
);
}
$this->_relations[] = new Relation_Stats_Dia(
- $this->_tables[$masterTable], $masterField,
- $this->_tables[$foreignTable], $foreignField
+ $this->diagram,
+ $this->_tables[$masterTable],
+ $masterField,
+ $this->_tables[$foreignTable],
+ $foreignField
);
}
@@ -375,4 +379,3 @@ class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
}
}
}
-?>
diff --git a/libraries/plugins/schema/dia/RelationStatsDia.class.php b/libraries/plugins/schema/dia/RelationStatsDia.class.php
index 09138056b2..22c104fad2 100644
--- a/libraries/plugins/schema/dia/RelationStatsDia.class.php
+++ b/libraries/plugins/schema/dia/RelationStatsDia.class.php
@@ -23,6 +23,7 @@ if (! defined('PHPMYADMIN')) {
*/
class Relation_Stats_Dia
{
+ protected $diagram;
/**
* Defines properties
*/
@@ -39,6 +40,7 @@ class Relation_Stats_Dia
/**
* The "Relation_Stats_Dia" constructor
*
+ * @param object $diagram The DIA diagram
* @param string $master_table The master table name
* @param string $master_field The relation field in the master table
* @param string $foreign_table The foreign table name
@@ -46,9 +48,10 @@ class Relation_Stats_Dia
*
* @see Relation_Stats_Dia::_getXy
*/
- function __construct($master_table, $master_field, $foreign_table,
- $foreign_field
+ public function __construct(
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
) {
+ $this->diagram = $diagram;
$src_pos = $this->_getXy($master_table, $master_field);
$dest_pos = $this->_getXy($foreign_table, $foreign_field);
$this->srcConnPointsLeft = $src_pos[0];
@@ -101,23 +104,19 @@ class Relation_Stats_Dia
*
* @return boolean|void
*
- * @global object $dia The current Dia document
- *
* @access public
* @see PMA_PDF
*/
public function relationDraw($showColor)
{
- global $dia;
-
PMA_Dia_Relation_Schema::$objectId += 1;
/*
* if source connection points and destination connection
* points are same then return it false and don't draw that
* relation
*/
- if ( $this->srcConnPointsRight == $this->destConnPointsRight) {
- if ( $this->srcConnPointsLeft == $this->destConnPointsLeft) {
+ if ($this->srcConnPointsRight == $this->destConnPointsRight) {
+ if ($this->srcConnPointsLeft == $this->destConnPointsLeft) {
return false;
}
}
@@ -134,7 +133,7 @@ class Relation_Stats_Dia
$this->referenceColor = '#000000';
}
- $dia->writeRaw(
+ $this->diagram->writeRaw(
'<dia:object type="Database - Reference" version="0" id="'
. PMA_Dia_Relation_Schema::$objectId . '">
<dia:attribute name="obj_pos">
@@ -213,4 +212,3 @@ class Relation_Stats_Dia
);
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/dia/TableStatsDia.class.php b/libraries/plugins/schema/dia/TableStatsDia.class.php
index e8f2d4c787..c3bb97d4b9 100644
--- a/libraries/plugins/schema/dia/TableStatsDia.class.php
+++ b/libraries/plugins/schema/dia/TableStatsDia.class.php
@@ -29,22 +29,19 @@ class Table_Stats_Dia extends TableStats
/**
* The "Table_Stats_Dia" constructor
*
+ * @param object $diagram The current dia document
+ * @param string $db The database name
* @param string $tableName The table name
* @param integer $pageNumber The current page number (from the
* $cfg['Servers'][$i]['table_coords'] table)
* @param boolean $showKeys Whether to display ONLY keys or not
* @param boolean $offline Whether the coordinates are sent from the browser
- *
- * @global object $dia The current dia document
- *
- * @see PMA_DIA
*/
- function __construct(
- $tableName, $pageNumber, $showKeys = false, $offline = false
+ public function __construct(
+ $diagram, $db, $tableName, $pageNumber, $showKeys = false, $offline = false
) {
- global $dia;
parent::__construct(
- $dia, $GLOBALS['db'], $pageNumber, $tableName, $showKeys, false, $offline
+ $diagram, $db, $pageNumber, $tableName, $showKeys, false, $offline
);
/**
@@ -84,15 +81,11 @@ class Table_Stats_Dia extends TableStats
*
* @return void
*
- * @global object $dia The current Dia document
- *
* @access public
* @see PMA_DIA
*/
public function tableDraw($showColor)
{
- global $dia;
-
if ($showColor) {
$listOfColors = array(
'FF0000',
@@ -107,11 +100,11 @@ class Table_Stats_Dia extends TableStats
$factor = 0.1;
- $dia->startElement('dia:object');
- $dia->writeAttribute('type', 'Database - Table');
- $dia->writeAttribute('version', '0');
- $dia->writeAttribute('id', '' . $this->tableId . '');
- $dia->writeRaw(
+ $this->diagram->startElement('dia:object');
+ $this->diagram->writeAttribute('type', 'Database - Table');
+ $this->diagram->writeAttribute('version', '0');
+ $this->diagram->writeAttribute('id', '' . $this->tableId . '');
+ $this->diagram->writeRaw(
'<dia:attribute name="obj_pos">
<dia:point val="'
. ($this->x * $factor) . ',' . ($this->y * $factor) . '"/>
@@ -183,11 +176,11 @@ class Table_Stats_Dia extends TableStats
</dia:attribute>'
);
- $dia->startElement('dia:attribute');
- $dia->writeAttribute('name', 'attributes');
+ $this->diagram->startElement('dia:attribute');
+ $this->diagram->writeAttribute('name', 'attributes');
foreach ($this->fields as $field) {
- $dia->writeRaw(
+ $this->diagram->writeRaw(
'<dia:composite type="table_attribute">
<dia:attribute name="name">
<dia:string>#' . $field . '#</dia:string>
@@ -207,7 +200,7 @@ class Table_Stats_Dia extends TableStats
if ($field == $this->displayfield) {
$pm = 'false';
}
- $dia->writeRaw(
+ $this->diagram->writeRaw(
'<dia:attribute name="primary_key">
<dia:boolean val="' . $pm . '"/>
</dia:attribute>
@@ -220,8 +213,7 @@ class Table_Stats_Dia extends TableStats
</dia:composite>'
);
}
- $dia->endElement();
- $dia->endElement();
+ $this->diagram->endElement();
+ $this->diagram->endElement();
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/eps/Eps_Relation_Schema.class.php b/libraries/plugins/schema/eps/Eps_Relation_Schema.class.php
index 45c7966843..8fa1272173 100644
--- a/libraries/plugins/schema/eps/Eps_Relation_Schema.class.php
+++ b/libraries/plugins/schema/eps/Eps_Relation_Schema.class.php
@@ -37,10 +37,8 @@ class PMA_EPS
* it shows/tells that the Post Script document is purely under
* Document Structuring Convention [DSC] and is Compliant
* Encapsulated Post Script Document
- *
- * @access public
*/
- function __construct()
+ public function __construct()
{
$this->stringCommands = "";
$this->stringCommands .= "%!PS-Adobe-3.0 EPSF-3.0 \n";
@@ -52,10 +50,8 @@ class PMA_EPS
* @param string $value sets the title text
*
* @return void
- *
- * @access public
*/
- function setTitle($value)
+ public function setTitle($value)
{
$this->stringCommands .= '%%Title: ' . $value . "\n";
}
@@ -66,10 +62,8 @@ class PMA_EPS
* @param string $value sets the author
*
* @return void
- *
- * @access public
*/
- function setAuthor($value)
+ public function setAuthor($value)
{
$this->stringCommands .= '%%Creator: ' . $value . "\n";
}
@@ -80,10 +74,8 @@ class PMA_EPS
* @param string $value sets the date
*
* @return void
- *
- * @access public
*/
- function setDate($value)
+ public function setDate($value)
{
$this->stringCommands .= '%%CreationDate: ' . $value . "\n";
}
@@ -94,10 +86,8 @@ class PMA_EPS
* @param string $orientation sets the orientation
*
* @return void
- *
- * @access public
*/
- function setOrientation($orientation)
+ public function setOrientation($orientation)
{
$this->stringCommands .= "%%PageOrder: Ascend \n";
if ($orientation == "L") {
@@ -121,10 +111,8 @@ class PMA_EPS
* @param integer $size sets the size of the font e.g 10
*
* @return void
- *
- * @access public
*/
- function setFont($value, $size)
+ public function setFont($value, $size)
{
$this->font = $value;
$this->fontSize = $size;
@@ -139,9 +127,8 @@ class PMA_EPS
* Get the font
*
* @return string return the font name e.g Arial
- * @access public
*/
- function getFont()
+ public function getFont()
{
return $this->font;
}
@@ -150,9 +137,8 @@ class PMA_EPS
* Get the font Size
*
* @return string return the size of the font e.g 10
- * @access public
*/
- function getFontSize()
+ public function getFontSize()
{
return $this->fontSize;
}
@@ -174,11 +160,10 @@ class PMA_EPS
* @param integer $lineWidth Sets the width of the line e.g 2
*
* @return void
- *
- * @access public
*/
- function line($x_from = 0, $y_from = 0, $x_to = 0, $y_to = 0, $lineWidth = 0)
- {
+ public function line($x_from = 0, $y_from = 0, $x_to = 0, $y_to = 0,
+ $lineWidth = 0
+ ) {
$this->stringCommands .= $lineWidth . " setlinewidth \n";
$this->stringCommands .= $x_from . ' ' . $y_from . " moveto \n";
$this->stringCommands .= $x_to . ' ' . $y_to . " lineto \n";
@@ -192,20 +177,18 @@ class PMA_EPS
* width of the line. rectangles drawn around the text shown of fields
*
* @param integer $x_from The x_from attribute defines the start
- left position of the element
+ * left position of the element
* @param integer $y_from The y_from attribute defines the start
- right position of the element
+ * right position of the element
* @param integer $x_to The x_to attribute defines the end
- left position of the element
+ * left position of the element
* @param integer $y_to The y_to attribute defines the end
- right position of the element
+ * right position of the element
* @param integer $lineWidth Sets the width of the line e.g 2
*
* @return void
- *
- * @access public
*/
- function rect($x_from, $y_from, $x_to, $y_to, $lineWidth)
+ public function rect($x_from, $y_from, $x_to, $y_to, $lineWidth)
{
$this->stringCommands .= $lineWidth . " setlinewidth \n";
$this->stringCommands .= "newpath \n";
@@ -228,10 +211,8 @@ class PMA_EPS
* @param integer $y The y attribute defines the right position of the element
*
* @return void
- *
- * @access public
*/
- function moveTo($x, $y)
+ public function moveTo($x, $y)
{
$this->stringCommands .= $x . ' ' . $y . " moveto \n";
}
@@ -242,10 +223,8 @@ class PMA_EPS
* @param string $text The string to be displayed
*
* @return void
- *
- * @access public
*/
- function show($text)
+ public function show($text)
{
$this->stringCommands .= '(' . $text . ") show \n";
}
@@ -258,10 +237,8 @@ class PMA_EPS
* @param integer $y Y attribute defines the right position of the element
*
* @return void
- *
- * @access public
*/
- function showXY($text, $x, $y)
+ public function showXY($text, $x, $y)
{
$this->moveTo($x, $y);
$this->show($text);
@@ -271,9 +248,8 @@ class PMA_EPS
* Ends EPS Document
*
* @return void
- * @access public
*/
- function endEpsDoc()
+ public function endEpsDoc()
{
$this->stringCommands .= "showpage \n";
}
@@ -284,10 +260,8 @@ class PMA_EPS
* @param string $fileName name of the eps document
*
* @return void
- *
- * @access public
*/
- function showOutput($fileName)
+ public function showOutput($fileName)
{
// if(ob_get_clean()){
//ob_end_clean();
@@ -319,7 +293,12 @@ class PMA_EPS
*/
class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
{
+ /**
+ * @var Table_Stats_Dia[]|Table_Stats_Eps[]|Table_Stats_Pdf[]|Table_Stats_Svg[]
+ */
private $_tables = array();
+
+ /** @var Relation_Stats_Dia[] Relations */
private $_relations = array();
/**
@@ -328,13 +307,13 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
* Upon instantiation This starts writing the EPS document
* user will be prompted for download as .eps extension
*
+ * @param string $db database name
+ *
* @see PMA_EPS
*/
- function __construct()
+ public function __construct($db)
{
- parent::__construct();
-
- global $eps;
+ parent::__construct($db, new PMA_EPS());
$this->setShowColor(isset($_REQUEST['eps_show_color']));
$this->setShowKeys(isset($_REQUEST['eps_show_keys']));
@@ -342,25 +321,26 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
$this->setAllTablesSameWidth(isset($_REQUEST['eps_all_tables_same_width']));
$this->setOrientation($_REQUEST['eps_orientation']);
- $eps = new PMA_EPS();
- $eps->setTitle(
+ $this->diagram->setTitle(
sprintf(
__('Schema of the %s database - Page %s'),
- $GLOBALS['db'],
+ $this->db,
$this->pageNumber
)
);
- $eps->setAuthor('phpMyAdmin ' . PMA_VERSION);
- $eps->setDate(date("j F Y, g:i a"));
- $eps->setOrientation($this->orientation);
- $eps->setFont('Verdana', '10');
+ $this->diagram->setAuthor('phpMyAdmin ' . PMA_VERSION);
+ $this->diagram->setDate(date("j F Y, g:i a"));
+ $this->diagram->setOrientation($this->orientation);
+ $this->diagram->setFont('Verdana', '10');
$alltables = $this->getTablesFromRequest();
foreach ($alltables as $table) {
if (! isset($this->_tables[$table])) {
$this->_tables[$table] = new Table_Stats_Eps(
- $table, $eps->getFont(), $eps->getFontSize(), $this->pageNumber,
+ $this->diagram, $this->db,
+ $table, $this->diagram->getFont(),
+ $this->diagram->getFontSize(), $this->pageNumber,
$this->_tablewidth, $this->showKeys,
$this->tableDimension, $this->offline
);
@@ -373,7 +353,7 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
$seen_a_relation = false;
foreach ($alltables as $one_table) {
- $exist_rel = PMA_getForeigners($GLOBALS['db'], $one_table, '', 'both');
+ $exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
if (!$exist_rel) {
continue;
}
@@ -388,7 +368,7 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
if ($master_field != 'foreign_keys_data') {
if (in_array($rel['foreign_table'], $alltables)) {
$this->_addRelation(
- $one_table, $eps->getFont(), $eps->getFontSize(),
+ $one_table, $this->diagram->getFont(), $this->diagram->getFontSize(),
$master_field, $rel['foreign_table'],
$rel['foreign_field'], $this->tableDimension
);
@@ -405,8 +385,8 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
as $index => $one_field
) {
$this->_addRelation(
- $one_table, $eps->getFont(),
- $eps->getFontSize(),
+ $one_table, $this->diagram->getFont(),
+ $this->diagram->getFontSize(),
$one_field, $one_key['ref_table_name'],
$one_key['ref_index_list'][$index],
$this->tableDimension
@@ -420,19 +400,17 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
}
$this->_drawTables();
- $eps->endEpsDoc();
+ $this->diagram->endEpsDoc();
}
/**
* Output Eps Document for download
*
* @return void
- * @access public
*/
- function showOutput()
+ public function showOutput()
{
- global $eps;
- $eps->showOutput($this->getFileName('.eps'));
+ $this->diagram->showOutput($this->getFileName('.eps'));
}
/**
@@ -448,7 +426,6 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
*
* @return void
*
- * @access private
* @see _setMinMax,Table_Stats_Eps::__construct(),
* Relation_Stats_Eps::__construct()
*/
@@ -458,19 +435,22 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
) {
if (! isset($this->_tables[$masterTable])) {
$this->_tables[$masterTable] = new Table_Stats_Eps(
- $masterTable, $font, $fontSize, $this->pageNumber,
- $this->_tablewidth, false, $tableDimension
+ $this->diagram, $this->db, $masterTable, $font, $fontSize,
+ $this->pageNumber, $this->_tablewidth, false, $tableDimension
);
}
if (! isset($this->_tables[$foreignTable])) {
$this->_tables[$foreignTable] = new Table_Stats_Eps(
- $foreignTable, $font, $fontSize, $this->pageNumber,
- $this->_tablewidth, false, $tableDimension
+ $this->diagram, $this->db, $foreignTable, $font, $fontSize,
+ $this->pageNumber, $this->_tablewidth, false, $tableDimension
);
}
$this->_relations[] = new Relation_Stats_Eps(
- $this->_tables[$masterTable], $masterField,
- $this->_tables[$foreignTable], $foreignField
+ $this->diagram,
+ $this->_tables[$masterTable],
+ $masterField,
+ $this->_tables[$foreignTable],
+ $foreignField
);
}
@@ -480,7 +460,6 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
*
* @return void
*
- * @access private
* @see Relation_Stats_Eps::relationDraw()
*/
private function _drawRelations()
@@ -495,7 +474,6 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
*
* @return void
*
- * @access private
* @see Table_Stats_Eps::Table_Stats_tableDraw()
*/
private function _drawTables()
@@ -505,4 +483,3 @@ class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema
}
}
}
-?>
diff --git a/libraries/plugins/schema/eps/RelationStatsEps.class.php b/libraries/plugins/schema/eps/RelationStatsEps.class.php
index 624416bf85..44106faaec 100644
--- a/libraries/plugins/schema/eps/RelationStatsEps.class.php
+++ b/libraries/plugins/schema/eps/RelationStatsEps.class.php
@@ -28,17 +28,18 @@ class Relation_Stats_Eps extends RelationStats
/**
* The "Relation_Stats_Eps" constructor
*
+ * @param object $diagram The EPS diagram
* @param string $master_table The master table name
* @param string $master_field The relation field in the master table
* @param string $foreign_table The foreign table name
* @param string $foreign_field The relation field in the foreign table
*/
- function __construct(
- $master_table, $master_field, $foreign_table, $foreign_field
+ public function __construct(
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
) {
$this->wTick = 10;
parent::__construct(
- $master_table, $master_field, $foreign_table, $foreign_field
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
);
$this->ySrc += 10;
$this->yDest += 10;
@@ -50,17 +51,12 @@ class Relation_Stats_Eps extends RelationStats
*
* @param boolean $showColor Whether to use one color per relation or not
*
- * @global object $eps The current EPS document
- *
- * @access public
* @see PMA_EPS
*
* @return void
*/
public function relationDraw($showColor)
{
- global $eps;
-
/* Commented because $color unused.
if ($showColor) {
$listOfColors = array(
@@ -78,7 +74,7 @@ class Relation_Stats_Eps extends RelationStats
$color = 'black';
}*/
// draw a line like -- to foreign field
- $eps->line(
+ $this->diagram->line(
$this->xSrc,
$this->ySrc,
$this->xSrc + $this->srcDir * $this->wTick,
@@ -86,7 +82,7 @@ class Relation_Stats_Eps extends RelationStats
1
);
// draw a line like -- to master field
- $eps->line(
+ $this->diagram->line(
$this->xDest + $this->destDir * $this->wTick,
$this->yDest,
$this->xDest,
@@ -94,7 +90,7 @@ class Relation_Stats_Eps extends RelationStats
1
);
// draw a line that connects to master field line and foreign field line
- $eps->line(
+ $this->diagram->line(
$this->xSrc + $this->srcDir * $this->wTick,
$this->ySrc,
$this->xDest + $this->destDir * $this->wTick,
@@ -102,28 +98,28 @@ class Relation_Stats_Eps extends RelationStats
1
);
$root2 = 2 * sqrt(2);
- $eps->line(
+ $this->diagram->line(
$this->xSrc + $this->srcDir * $this->wTick * 0.75,
$this->ySrc,
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
$this->ySrc + $this->wTick / $root2,
1
);
- $eps->line(
+ $this->diagram->line(
$this->xSrc + $this->srcDir * $this->wTick * 0.75,
$this->ySrc,
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
$this->ySrc - $this->wTick / $root2,
1
);
- $eps->line(
+ $this->diagram->line(
$this->xDest + $this->destDir * $this->wTick / 2,
$this->yDest,
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
$this->yDest + $this->wTick / $root2,
1
);
- $eps->line(
+ $this->diagram->line(
$this->xDest + $this->destDir * $this->wTick / 2,
$this->yDest,
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
@@ -132,4 +128,3 @@ class Relation_Stats_Eps extends RelationStats
);
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/eps/TableStatsEps.class.php b/libraries/plugins/schema/eps/TableStatsEps.class.php
index 7114410b65..bd5d72cadf 100644
--- a/libraries/plugins/schema/eps/TableStatsEps.class.php
+++ b/libraries/plugins/schema/eps/TableStatsEps.class.php
@@ -32,6 +32,8 @@ class Table_Stats_Eps extends TableStats
/**
* The "Table_Stats_Eps" constructor
*
+ * @param object $diagram The EPS diagram
+ * @param string $db The database name
* @param string $tableName The table name
* @param string $font The font name
* @param integer $fontSize The font size
@@ -42,19 +44,15 @@ class Table_Stats_Eps extends TableStats
* @param boolean $offline Whether the coordinates are sent
* from the browser
*
- * @global object $eps The current eps document
- *
- * @access private
* @see PMA_EPS, Table_Stats_Eps::Table_Stats_setWidth,
* Table_Stats_Eps::Table_Stats_setHeight
*/
- function __construct(
- $tableName, $font, $fontSize, $pageNumber, &$same_wide_width,
+ public function __construct(
+ $diagram, $db, $tableName, $font, $fontSize, $pageNumber, &$same_wide_width,
$showKeys = false, $tableDimension = false, $offline = false
) {
- global $eps;
parent::__construct(
- $eps, $GLOBALS['db'], $pageNumber, $tableName,
+ $diagram, $db, $pageNumber, $tableName,
$showKeys, $tableDimension, $offline
);
@@ -90,7 +88,6 @@ class Table_Stats_Eps extends TableStats
*
* @return void
*
- * @access private
* @see PMA_EPS
*/
private function _setWidthTable($font,$fontSize)
@@ -118,7 +115,6 @@ class Table_Stats_Eps extends TableStats
* @param integer $fontSize The font size
*
* @return void
- * @access private
*/
private function _setHeightTable($fontSize)
{
@@ -131,27 +127,22 @@ class Table_Stats_Eps extends TableStats
*
* @param boolean $showColor Whether to display color
*
- * @global object $eps The current eps document
- *
* @return void
*
- * @access public
* @see PMA_EPS,PMA_EPS::line,PMA_EPS::rect
*/
public function tableDraw($showColor)
{
- global $eps;
//echo $this->tableName.'<br />';
- $eps->rect($this->x, $this->y + 12, $this->width, $this->heightCell, 1);
- $eps->showXY($this->getTitle(), $this->x + 5, $this->y + 14);
+ $this->diagram->rect($this->x, $this->y + 12, $this->width, $this->heightCell, 1);
+ $this->diagram->showXY($this->getTitle(), $this->x + 5, $this->y + 14);
foreach ($this->fields as $field) {
$this->currentCell += $this->heightCell;
- $eps->rect(
+ $this->diagram->rect(
$this->x, $this->y + 12 + $this->currentCell,
$this->width, $this->heightCell, 1
);
- $eps->showXY($field, $this->x + 5, $this->y + 14 + $this->currentCell);
+ $this->diagram->showXY($field, $this->x + 5, $this->y + 14 + $this->currentCell);
}
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/pdf/Pdf_Relation_Schema.class.php b/libraries/plugins/schema/pdf/Pdf_Relation_Schema.class.php
index 994ee43d11..f0ecde580d 100644
--- a/libraries/plugins/schema/pdf/Pdf_Relation_Schema.class.php
+++ b/libraries/plugins/schema/pdf/Pdf_Relation_Schema.class.php
@@ -56,6 +56,7 @@ class PMA_Schema_PDF extends PMA_PDF
private $_offline;
private $_pageNumber;
private $_withDoc;
+ private $_db;
/**
* Constructs PDF for schema export.
@@ -65,15 +66,17 @@ class PMA_Schema_PDF extends PMA_PDF
* @param string $paper the format used for pages
* @param int $pageNumber schema page number that is being exported
* @param boolean $withDoc with document dictionary
+ * @param string $db the database name
*
* @access public
*/
public function __construct(
- $orientation, $unit, $paper, $pageNumber, $withDoc
+ $orientation, $unit, $paper, $pageNumber, $withDoc, $db
) {
parent::__construct($orientation, $unit, $paper);
$this->_pageNumber = $pageNumber;
$this->_withDoc = $withDoc;
+ $this->_db = $db;
}
/**
@@ -97,11 +100,9 @@ class PMA_Schema_PDF extends PMA_PDF
* @param float|int $leftMargin The left margin
* @param float|int $topMargin The top margin
*
- * @access public
- *
* @return void
*/
- function setScale($scale = 1, $xMin = 0, $yMin = 0,
+ public function setScale($scale = 1, $xMin = 0, $yMin = 0,
$leftMargin = -1, $topMargin = -1
) {
$this->scale = $scale;
@@ -127,13 +128,11 @@ class PMA_Schema_PDF extends PMA_PDF
* @param integer $fill Whether to fill the cell with a color or not
* @param string $link Link
*
- * @access public
- *
* @return void
*
* @see TCPDF::Cell()
*/
- function cellScale($w, $h = 0, $txt = '', $border = 0, $ln = 0,
+ public function cellScale($w, $h = 0, $txt = '', $border = 0, $ln = 0,
$align = '', $fill = 0, $link = ''
) {
$h = $h / $this->scale;
@@ -149,13 +148,11 @@ class PMA_Schema_PDF extends PMA_PDF
* @param float $x2 The horizontal position of the ending point
* @param float $y2 The vertical position of the ending point
*
- * @access public
- *
* @return void
*
* @see TCPDF::Line()
*/
- function lineScale($x1, $y1, $x2, $y2)
+ public function lineScale($x1, $y1, $x2, $y2)
{
$x1 = ($x1 - $this->_xMin) / $this->scale + $this->leftMargin;
$y1 = ($y1 - $this->_yMin) / $this->scale + $this->topMargin;
@@ -170,13 +167,11 @@ class PMA_Schema_PDF extends PMA_PDF
* @param float $x The x position
* @param float $y The y position
*
- * @access public
- *
* @return void
*
* @see TCPDF::SetXY()
*/
- function setXyScale($x, $y)
+ public function setXyScale($x, $y)
{
$x = ($x - $this->_xMin) / $this->scale + $this->leftMargin;
$y = ($y - $this->_yMin) / $this->scale + $this->topMargin;
@@ -188,13 +183,11 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @param float $x The x position
*
- * @access public
- *
* @return void
*
* @see TCPDF::SetX()
*/
- function setXScale($x)
+ public function setXScale($x)
{
$x = ($x - $this->_xMin) / $this->scale + $this->leftMargin;
$this->SetX($x);
@@ -205,13 +198,11 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @param float $size The font size (in points)
*
- * @access public
- *
* @return void
*
* @see TCPDF::SetFontSize()
*/
- function setFontSizeScale($size)
+ public function setFontSizeScale($size)
{
// Set font size in points
$size = $size / $this->scale;
@@ -223,13 +214,11 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @param float $width The line width
*
- * @access public
- *
* @return void
*
* @see TCPDF::SetLineWidth()
*/
- function setLineWidthScale($width)
+ public function setLineWidthScale($width)
{
$width = $width / $this->scale;
$this->SetLineWidth($width);
@@ -242,7 +231,7 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @see TCPDF::Header()
*/
- function Header()
+ public function Header()
{
// We only show this if we find something in the new pdf_pages table
@@ -254,7 +243,7 @@ class PMA_Schema_PDF extends PMA_PDF
$test_query = 'SELECT * FROM '
. PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.'
. PMA_Util::backquote($GLOBALS['cfgRelation']['pdf_pages'])
- . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($GLOBALS['db'])
+ . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($this->_db)
. '\' AND page_nr = \'' . $this->_pageNumber . '\'';
$test_rs = PMA_queryAsControlUser($test_query);
$pages = @$GLOBALS['dbi']->fetchAssoc($test_rs);
@@ -275,7 +264,7 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @see PMA_PDF::Footer()
*/
- function Footer()
+ public function Footer()
{
if ($this->_withDoc) {
parent::Footer();
@@ -289,7 +278,7 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @return void
*/
- function SetWidths($w)
+ public function SetWidths($w)
{
// column widths
$this->widths = $w;
@@ -303,7 +292,7 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @return void
*/
- function Row($data, $links)
+ public function Row($data, $links)
{
// line height
$nb = 0;
@@ -344,7 +333,7 @@ class PMA_Schema_PDF extends PMA_PDF
*
* @return int
*/
- function NbLines($w, $txt)
+ public function NbLines($w, $txt)
{
$cw = &$this->CurrentFont['cw'];
if ($w == 0) {
@@ -428,6 +417,11 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
*/
private $_showGrid;
private $_withDoc;
+ private $_tableOrder;
+
+ /**
+ * @var Table_Stats_Pdf[]
+ */
private $_tables = array();
private $_ff = PMA_PDF_FONT;
private $_xMax = 0;
@@ -440,62 +434,71 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
private $_leftMargin = 10;
private $_rightMargin = 10;
private $_tablewidth;
+
+ /**
+ * @var Relation_Stats_Pdf[]
+ */
protected $relations = array();
/**
* The "PMA_Pdf_Relation_Schema" constructor
*
- * @global object $pdf The current PDF Schema document
- * @access private
+ * @param string $db database name
+ *
* @see PMA_Schema_PDF
*/
- function __construct()
+ public function __construct($db)
{
- parent::__construct();
-
- global $pdf;
-
$this->setShowGrid(isset($_REQUEST['pdf_show_grid']));
$this->setShowColor(isset($_REQUEST['pdf_show_color']));
$this->setShowKeys(isset($_REQUEST['pdf_show_keys']));
$this->setTableDimension(isset($_REQUEST['pdf_show_table_dimension']));
$this->setAllTablesSameWidth(isset($_REQUEST['pdf_all_tables_same_width']));
$this->setWithDataDictionary(isset($_REQUEST['pdf_with_doc']));
+ $this->setTableOrder($_REQUEST['pdf_table_order']);
$this->setOrientation($_REQUEST['pdf_orientation']);
$this->setPaper($_REQUEST['pdf_paper']);
- // Initializes a new document
- $pdf = new PMA_Schema_PDF(
- $this->orientation, 'mm', $this->paper,
- $this->pageNumber, $this->_withDoc
+ // Initializes a new document
+ parent::__construct(
+ $db,
+ new PMA_Schema_PDF(
+ $this->orientation, 'mm', $this->paper,
+ $this->pageNumber, $this->_withDoc, $db
+ )
);
- $pdf->SetTitle(
+ $this->diagram->SetTitle(
sprintf(
__('Schema of the %s database'),
- $GLOBALS['db']
+ $this->db
)
);
- $pdf->setCMargin(0);
- $pdf->Open();
- $pdf->SetAutoPageBreak('auto');
- $pdf->setOffline($this->offline);
+ $this->diagram->setCMargin(0);
+ $this->diagram->Open();
+ $this->diagram->SetAutoPageBreak('auto');
+ $this->diagram->setOffline($this->offline);
$alltables = $this->getTablesFromRequest();
+ if ($this->getTableOrder() == 'name_asc') {
+ sort($alltables);
+ } else if ($this->getTableOrder() == 'name_desc') {
+ rsort($alltables);
+ }
if ($this->_withDoc) {
- $pdf->SetAutoPageBreak('auto', 15);
- $pdf->setCMargin(1);
+ $this->diagram->SetAutoPageBreak('auto', 15);
+ $this->diagram->setCMargin(1);
$this->dataDictionaryDoc($alltables);
- $pdf->SetAutoPageBreak('auto');
- $pdf->setCMargin(0);
+ $this->diagram->SetAutoPageBreak('auto');
+ $this->diagram->setCMargin(0);
}
- $pdf->Addpage();
+ $this->diagram->Addpage();
if ($this->_withDoc) {
- $pdf->SetLink($pdf->PMA_links['RT']['-'], -1);
- $pdf->Bookmark(__('Relational schema'));
- $pdf->SetAlias('{00}', $pdf->PageNo());
+ $this->diagram->SetLink($this->diagram->PMA_links['RT']['-'], -1);
+ $this->diagram->Bookmark(__('Relational schema'));
+ $this->diagram->SetAlias('{00}', $this->diagram->PageNo());
$this->_topMargin = 28;
$this->_bottomMargin = 28;
}
@@ -504,6 +507,8 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
foreach ($alltables as $table) {
if (! isset($this->_tables[$table])) {
$this->_tables[$table] = new Table_Stats_Pdf(
+ $this->diagram,
+ $this->db,
$table,
null,
$this->pageNumber,
@@ -520,16 +525,18 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
}
// Defines the scale factor
+ $innerWidth = $this->diagram->getPageWidth() - $this->_rightMargin
+ - $this->_leftMargin;
+ $innerHeight = $this->diagram->getPageHeight() - $this->_topMargin
+ - $this->_bottomMargin;
$this->_scale = ceil(
max(
- ($this->_xMax - $this->_xMin)
- / ($pdf->getPageWidth() - $this->_rightMargin - $this->_leftMargin),
- ($this->_yMax - $this->_yMin)
- / ($pdf->getPageHeight() - $this->_topMargin - $this->_bottomMargin)
+ ($this->_xMax - $this->_xMin) / $innerWidth,
+ ($this->_yMax - $this->_yMin) / $innerHeight
) * 100
) / 100;
- $pdf->setScale(
+ $this->diagram->setScale(
$this->_scale,
$this->_xMin,
$this->_yMin,
@@ -537,19 +544,19 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
$this->_topMargin
);
// Builds and save the PDF document
- $pdf->setLineWidthScale(0.1);
+ $this->diagram->setLineWidthScale(0.1);
if ($this->_showGrid) {
- $pdf->SetFontSize(10);
+ $this->diagram->SetFontSize(10);
$this->_strokeGrid();
}
- $pdf->setFontSizeScale(14);
+ $this->diagram->setFontSizeScale(14);
// previous logic was checking master tables and foreign tables
// but I think that looping on every table of the pdf page as a master
// and finding its foreigns is OK (then we can support innodb)
$seen_a_relation = false;
foreach ($alltables as $one_table) {
- $exist_rel = PMA_getForeigners($GLOBALS['db'], $one_table, '', 'both');
+ $exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
if (!$exist_rel) {
continue;
}
@@ -603,8 +610,6 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
* @param boolean $value show grid of the document or not
*
* @return void
- *
- * @access public
*/
public function setShowGrid($value)
{
@@ -627,8 +632,6 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
* @param boolean $value show selected database data dictionary or not
*
* @return void
- *
- * @access public
*/
public function setWithDataDictionary($value)
{
@@ -646,25 +649,43 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
}
/**
+ * Sets the order of the table in data dictionary
+ *
+ * @param string $value table order
+ *
+ * @return void
+ */
+ public function setTableOrder($value)
+ {
+ $this->_tableOrder = $value;
+ }
+
+ /**
+ * Returns the order of the table in data dictionary
+ *
+ * @return string table order
+ */
+ public function getTableOrder()
+ {
+ return $this->_tableOrder;
+ }
+
+ /**
* Output Pdf Document for download
*
* @return void
- * @access public
*/
- function showOutput()
+ public function showOutput()
{
- global $pdf;
- $pdf->Download($this->getFileName('.pdf'));
+ $this->diagram->Download($this->getFileName('.pdf'));
}
/**
* Sets X and Y minimum and maximum for a table cell
*
- * @param object $table The table name of which sets XY co-ordinates
+ * @param Table_Stats_Pdf $table The table name of which sets XY co-ordinates
*
* @return void
- *
- * @access private
*/
private function _setMinMax($table)
{
@@ -682,8 +703,6 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
* @param string $foreignTable The foreign table name
* @param string $foreignField The relation field in the foreign table
*
- * @access private
- *
* @return void
*
* @see _setMinMax
@@ -693,7 +712,11 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
) {
if (! isset($this->_tables[$masterTable])) {
$this->_tables[$masterTable] = new Table_Stats_Pdf(
- $masterTable, null, $this->pageNumber,
+ $this->diagram,
+ $this->db,
+ $masterTable,
+ null,
+ $this->pageNumber,
$this->_tablewidth,
$this->showKeys,
$this->tableDimension
@@ -702,7 +725,11 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
}
if (! isset($this->_tables[$foreignTable])) {
$this->_tables[$foreignTable] = new Table_Stats_Pdf(
- $foreignTable, null, $this->pageNumber,
+ $this->diagram,
+ $this->db,
+ $foreignTable,
+ null,
+ $this->pageNumber,
$this->_tablewidth,
$this->showKeys,
$this->tableDimension
@@ -710,26 +737,23 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
$this->_setMinMax($this->_tables[$foreignTable]);
}
$this->relations[] = new Relation_Stats_Pdf(
- $this->_tables[$masterTable], $masterField,
- $this->_tables[$foreignTable], $foreignField
+ $this->diagram,
+ $this->_tables[$masterTable],
+ $masterField,
+ $this->_tables[$foreignTable],
+ $foreignField
);
}
/**
* Draws the grid
*
- * @global object $pdf the current PMA_Schema_PDF instance
- *
- * @access private
- *
* @return void
*
* @see PMA_Schema_PDF
*/
private function _strokeGrid()
{
- global $pdf;
-
$gridSize = 10;
$labelHeight = 4;
$labelWidth = 5;
@@ -741,61 +765,56 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
$bottomSpace = 0;
}
- $pdf->SetMargins(0, 0);
- $pdf->SetDrawColor(200, 200, 200);
+ $this->diagram->SetMargins(0, 0);
+ $this->diagram->SetDrawColor(200, 200, 200);
// Draws horizontal lines
+ $innerHeight = $this->diagram->getPageHeight() - $topSpace - $bottomSpace;
for ($l = 0,
- $size = intval(
- ($pdf->getPageHeight() - $topSpace - $bottomSpace) / $gridSize
- );
+ $size = intval($innerHeight / $gridSize);
$l <= $size;
- $l++) {
- $pdf->line(
+ $l++
+ ) {
+ $this->diagram->line(
0, $l * $gridSize + $topSpace,
- $pdf->getPageWidth(), $l * $gridSize + $topSpace
+ $this->diagram->getPageWidth(), $l * $gridSize + $topSpace
);
// Avoid duplicates
if ($l > 0
- && $l <= intval(
- ($pdf->getPageHeight() - $topSpace - $bottomSpace - $labelHeight)
- / $gridSize
- )
+ && $l <= intval(($innerHeight - $labelHeight) / $gridSize)
) {
- $pdf->SetXY(0, $l * $gridSize + $topSpace);
+ $this->diagram->SetXY(0, $l * $gridSize + $topSpace);
$label = (string) sprintf(
'%.0f',
($l * $gridSize + $topSpace - $this->_topMargin)
* $this->_scale + $this->_yMin
);
- $pdf->Cell($labelWidth, $labelHeight, ' ' . $label);
+ $this->diagram->Cell($labelWidth, $labelHeight, ' ' . $label);
} // end if
} // end for
// Draws vertical lines
for (
- $j = 0, $size = intval($pdf->getPageWidth() / $gridSize);
+ $j = 0, $size = intval($this->diagram->getPageWidth() / $gridSize);
$j <= $size;
$j++
) {
- $pdf->line(
+ $this->diagram->line(
$j * $gridSize,
$topSpace,
$j * $gridSize,
- $pdf->getPageHeight() - $bottomSpace
+ $this->diagram->getPageHeight() - $bottomSpace
);
- $pdf->SetXY($j * $gridSize, $topSpace);
+ $this->diagram->SetXY($j * $gridSize, $topSpace);
$label = (string) sprintf(
'%.0f',
($j * $gridSize - $this->_leftMargin) * $this->_scale + $this->_xMin
);
- $pdf->Cell($labelWidth, $labelHeight, $label);
+ $this->diagram->Cell($labelWidth, $labelHeight, $label);
}
}
/**
* Draws relation arrows
*
- * @access private
- *
* @return void
*
* @see Relation_Stats_Pdf::relationdraw()
@@ -812,8 +831,6 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
/**
* Draws tables
*
- * @access private
- *
* @return void
*
* @see Table_Stats_Pdf::tableDraw()
@@ -834,76 +851,83 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
*/
public function dataDictionaryDoc($alltables)
{
- global $pdf;
- // TOC
- $pdf->addpage($this->orientation);
- $pdf->Cell(0, 9, __('Table of contents'), 1, 0, 'C');
- $pdf->Ln(15);
+ // TOC
+ $this->diagram->addpage($this->orientation);
+ $this->diagram->Cell(0, 9, __('Table of contents'), 1, 0, 'C');
+ $this->diagram->Ln(15);
$i = 1;
foreach ($alltables as $table) {
- $pdf->PMA_links['doc'][$table]['-'] = $pdf->AddLink();
- $pdf->SetX(10);
- // $pdf->Ln(1);
- $pdf->Cell(
+ $this->diagram->PMA_links['doc'][$table]['-']
+ = $this->diagram->AddLink();
+ $this->diagram->SetX(10);
+ // $this->diagram->Ln(1);
+ $this->diagram->Cell(
0, 6, __('Page number:') . ' {' . sprintf("%02d", $i) . '}', 0, 0,
- 'R', 0, $pdf->PMA_links['doc'][$table]['-']
+ 'R', 0, $this->diagram->PMA_links['doc'][$table]['-']
);
- $pdf->SetX(10);
- $pdf->Cell(
+ $this->diagram->SetX(10);
+ $this->diagram->Cell(
0, 6, $i . ' ' . $table, 0, 1,
- 'L', 0, $pdf->PMA_links['doc'][$table]['-']
+ 'L', 0, $this->diagram->PMA_links['doc'][$table]['-']
);
- // $pdf->Ln(1);
- $fields = $GLOBALS['dbi']->getColumns($GLOBALS['db'], $table);
+ // $this->diagram->Ln(1);
+ $fields = $GLOBALS['dbi']->getColumns($this->db, $table);
foreach ($fields as $row) {
- $pdf->SetX(20);
+ $this->diagram->SetX(20);
$field_name = $row['Field'];
- $pdf->PMA_links['doc'][$table][$field_name] = $pdf->AddLink();
- //$pdf->Cell(
+ $this->diagram->PMA_links['doc'][$table][$field_name]
+ = $this->diagram->AddLink();
+ //$this->diagram->Cell(
// 0, 6, $field_name, 0, 1,
- // 'L', 0, $pdf->PMA_links['doc'][$table][$field_name]
+ // 'L', 0, $this->diagram->PMA_links['doc'][$table][$field_name]
//);
}
$i++;
}
- $pdf->PMA_links['RT']['-'] = $pdf->AddLink();
- $pdf->SetX(10);
- $pdf->Cell(
+ $this->diagram->PMA_links['RT']['-'] = $this->diagram->AddLink();
+ $this->diagram->SetX(10);
+ $this->diagram->Cell(
0, 6, __('Page number:') . ' {00}', 0, 0,
- 'R', 0, $pdf->PMA_links['RT']['-']
+ 'R', 0, $this->diagram->PMA_links['RT']['-']
);
- $pdf->SetX(10);
- $pdf->Cell(
+ $this->diagram->SetX(10);
+ $this->diagram->Cell(
0, 6, $i . ' ' . __('Relational schema'), 0, 1,
- 'L', 0, $pdf->PMA_links['RT']['-']
+ 'L', 0, $this->diagram->PMA_links['RT']['-']
);
$z = 0;
foreach ($alltables as $table) {
$z++;
- $pdf->SetAutoPageBreak(true, 15);
- $pdf->addpage($this->orientation);
- $pdf->Bookmark($table);
- $pdf->SetAlias('{' . sprintf("%02d", $z) . '}', $pdf->PageNo());
- $pdf->PMA_links['RT'][$table]['-'] = $pdf->AddLink();
- $pdf->SetLink($pdf->PMA_links['doc'][$table]['-'], -1);
- $pdf->SetFont($this->_ff, 'B', 18);
- $pdf->Cell(
+ $this->diagram->SetAutoPageBreak(true, 15);
+ $this->diagram->addpage($this->orientation);
+ $this->diagram->Bookmark($table);
+ $this->diagram->SetAlias(
+ '{' . sprintf("%02d", $z) . '}', $this->diagram->PageNo()
+ );
+ $this->diagram->PMA_links['RT'][$table]['-']
+ = $this->diagram->AddLink();
+ $this->diagram->SetLink(
+ $this->diagram->PMA_links['doc'][$table]['-'], -1
+ );
+ $this->diagram->SetFont($this->_ff, 'B', 18);
+ $this->diagram->Cell(
0, 8, $z . ' ' . $table, 1, 1,
- 'C', 0, $pdf->PMA_links['RT'][$table]['-']
+ 'C', 0, $this->diagram->PMA_links['RT'][$table]['-']
);
- $pdf->SetFont($this->_ff, '', 8);
- $pdf->ln();
+ $this->diagram->SetFont($this->_ff, '', 8);
+ $this->diagram->ln();
$cfgRelation = PMA_getRelationsParam();
- $comments = PMA_getComments($GLOBALS['db'], $table);
+ $comments = PMA_getComments($this->db, $table);
if ($cfgRelation['mimework']) {
- $mime_map = PMA_getMIME($GLOBALS['db'], $table, true);
+ $mime_map = PMA_getMIME($this->db, $table, true);
}
/**
* Gets table information
*/
- $showtable = PMA_Table::sGetStatusInfo($GLOBALS['db'], $table);
+ $showtable = $GLOBALS['dbi']->getTable($this->db, $table)
+ ->getStatusInfo();
$show_comment = isset($showtable['Comment'])
? $showtable['Comment']
: '';
@@ -926,12 +950,12 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
/**
* Gets fields properties
*/
- $columns = $GLOBALS['dbi']->getColumns($GLOBALS['db'], $table);
+ $columns = $GLOBALS['dbi']->getColumns($this->db, $table);
// Check if we can use Relations
if (!empty($cfgRelation['relation'])) {
// Find which tables are related with the current one and write it in
// an array
- $res_rel = PMA_getForeigners($GLOBALS['db'], $table);
+ $res_rel = PMA_getForeigners($this->db, $table);
} // end if
/**
@@ -940,39 +964,47 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
$break = false;
if (! empty($show_comment)) {
- $pdf->Cell(0, 3, __('Table comments:') . ' ' . $show_comment, 0, 1);
+ $this->diagram->Cell(
+ 0, 3, __('Table comments:') . ' ' . $show_comment, 0, 1
+ );
$break = true;
}
if (! empty($create_time)) {
- $pdf->Cell(0, 3, __('Creation:') . ' ' . $create_time, 0, 1);
+ $this->diagram->Cell(
+ 0, 3, __('Creation:') . ' ' . $create_time, 0, 1
+ );
$break = true;
}
if (! empty($update_time)) {
- $pdf->Cell(0, 3, __('Last update:') . ' ' . $update_time, 0, 1);
+ $this->diagram->Cell(
+ 0, 3, __('Last update:') . ' ' . $update_time, 0, 1
+ );
$break = true;
}
if (! empty($check_time)) {
- $pdf->Cell(0, 3, __('Last check:') . ' ' . $check_time, 0, 1);
+ $this->diagram->Cell(
+ 0, 3, __('Last check:') . ' ' . $check_time, 0, 1
+ );
$break = true;
}
if ($break == true) {
- $pdf->Cell(0, 3, '', 0, 1);
- $pdf->Ln();
+ $this->diagram->Cell(0, 3, '', 0, 1);
+ $this->diagram->Ln();
}
- $pdf->SetFont($this->_ff, 'B');
+ $this->diagram->SetFont($this->_ff, 'B');
if (isset($this->orientation) && $this->orientation == 'L') {
- $pdf->Cell(25, 8, __('Column'), 1, 0, 'C');
- $pdf->Cell(20, 8, __('Type'), 1, 0, 'C');
- $pdf->Cell(20, 8, __('Attributes'), 1, 0, 'C');
- $pdf->Cell(10, 8, __('Null'), 1, 0, 'C');
- $pdf->Cell(20, 8, __('Default'), 1, 0, 'C');
- $pdf->Cell(25, 8, __('Extra'), 1, 0, 'C');
- $pdf->Cell(45, 8, __('Links to'), 1, 0, 'C');
+ $this->diagram->Cell(25, 8, __('Column'), 1, 0, 'C');
+ $this->diagram->Cell(20, 8, __('Type'), 1, 0, 'C');
+ $this->diagram->Cell(20, 8, __('Attributes'), 1, 0, 'C');
+ $this->diagram->Cell(10, 8, __('Null'), 1, 0, 'C');
+ $this->diagram->Cell(20, 8, __('Default'), 1, 0, 'C');
+ $this->diagram->Cell(25, 8, __('Extra'), 1, 0, 'C');
+ $this->diagram->Cell(45, 8, __('Links to'), 1, 0, 'C');
if ($this->paper == 'A4') {
$comments_width = 67;
@@ -983,24 +1015,24 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
*/
$comments_width = 50;
}
- $pdf->Cell($comments_width, 8, __('Comments'), 1, 0, 'C');
- $pdf->Cell(45, 8, 'MIME', 1, 1, 'C');
- $pdf->SetWidths(
+ $this->diagram->Cell($comments_width, 8, __('Comments'), 1, 0, 'C');
+ $this->diagram->Cell(45, 8, 'MIME', 1, 1, 'C');
+ $this->diagram->SetWidths(
array(25, 20, 20, 10, 20, 25, 45, $comments_width, 45)
);
} else {
- $pdf->Cell(20, 8, __('Column'), 1, 0, 'C');
- $pdf->Cell(20, 8, __('Type'), 1, 0, 'C');
- $pdf->Cell(20, 8, __('Attributes'), 1, 0, 'C');
- $pdf->Cell(10, 8, __('Null'), 1, 0, 'C');
- $pdf->Cell(15, 8, __('Default'), 1, 0, 'C');
- $pdf->Cell(15, 8, __('Extra'), 1, 0, 'C');
- $pdf->Cell(30, 8, __('Links to'), 1, 0, 'C');
- $pdf->Cell(30, 8, __('Comments'), 1, 0, 'C');
- $pdf->Cell(30, 8, 'MIME', 1, 1, 'C');
- $pdf->SetWidths(array(20, 20, 20, 10, 15, 15, 30, 30, 30));
+ $this->diagram->Cell(20, 8, __('Column'), 1, 0, 'C');
+ $this->diagram->Cell(20, 8, __('Type'), 1, 0, 'C');
+ $this->diagram->Cell(20, 8, __('Attributes'), 1, 0, 'C');
+ $this->diagram->Cell(10, 8, __('Null'), 1, 0, 'C');
+ $this->diagram->Cell(15, 8, __('Default'), 1, 0, 'C');
+ $this->diagram->Cell(15, 8, __('Extra'), 1, 0, 'C');
+ $this->diagram->Cell(30, 8, __('Links to'), 1, 0, 'C');
+ $this->diagram->Cell(30, 8, __('Comments'), 1, 0, 'C');
+ $this->diagram->Cell(30, 8, 'MIME', 1, 1, 'C');
+ $this->diagram->SetWidths(array(20, 20, 20, 10, 15, 15, 30, 30, 30));
}
- $pdf->SetFont($this->_ff, '');
+ $this->diagram->SetFont($this->_ff, '');
foreach ($columns as $row) {
$extracted_columnspec
@@ -1013,16 +1045,19 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
}
}
$field_name = $row['Field'];
- // $pdf->Ln();
- $pdf->PMA_links['RT'][$table][$field_name] = $pdf->AddLink();
- $pdf->Bookmark($field_name, 1, -1);
- $pdf->SetLink($pdf->PMA_links['doc'][$table][$field_name], -1);
+ // $this->diagram->Ln();
+ $this->diagram->PMA_links['RT'][$table][$field_name]
+ = $this->diagram->AddLink();
+ $this->diagram->Bookmark($field_name, 1, -1);
+ $this->diagram->SetLink(
+ $this->diagram->PMA_links['doc'][$table][$field_name], -1
+ );
$foreigner = PMA_searchColumnInForeigners($res_rel, $field_name);
$linksTo = '';
if ($foreigner) {
$linksTo = '-> ';
- if ($foreigner['foreign_db'] != $GLOBALS['db']) {
+ if ($foreigner['foreign_db'] != $this->db) {
$linksTo .= $foreigner['foreign_db'] . '.';
}
$linksTo .= $foreigner['foreign_table']
@@ -1034,7 +1069,7 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
}
}
- $pdf_row = array(
+ $this->diagram_row = array(
$field_name,
$type,
$attribute,
@@ -1052,19 +1087,18 @@ class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
: '')
);
$links = array();
- $links[0] = $pdf->PMA_links['RT'][$table][$field_name];
+ $links[0] = $this->diagram->PMA_links['RT'][$table][$field_name];
if ($foreigner
- && isset($pdf->PMA_links['doc'][$foreigner['foreign_table']][$foreigner['foreign_field']])
+ && isset($this->diagram->PMA_links['doc'][$foreigner['foreign_table']][$foreigner['foreign_field']])
) {
- $links[6] = $pdf->PMA_links['doc'][$foreigner['foreign_table']]
- [$foreigner['foreign_field']];
+ $links[6] = $this->diagram->PMA_links['doc']
+ [$foreigner['foreign_table']][$foreigner['foreign_field']];
} else {
unset($links[6]);
}
- $pdf->Row($pdf_row, $links);
+ $this->diagram->Row($this->diagram_row, $links);
} // end foreach
- $pdf->SetFont($this->_ff, '', 14);
+ $this->diagram->SetFont($this->_ff, '', 14);
} //end each
}
}
-?>
diff --git a/libraries/plugins/schema/pdf/RelationStatsPdf.class.php b/libraries/plugins/schema/pdf/RelationStatsPdf.class.php
index 5e438859b0..9328a5c4ed 100644
--- a/libraries/plugins/schema/pdf/RelationStatsPdf.class.php
+++ b/libraries/plugins/schema/pdf/RelationStatsPdf.class.php
@@ -29,17 +29,19 @@ class Relation_Stats_Pdf extends RelationStats
/**
* The "Relation_Stats_Pdf" constructor
*
+ * @param object $diagram The PDF diagram
* @param string $master_table The master table name
* @param string $master_field The relation field in the master table
* @param string $foreign_table The foreign table name
* @param string $foreign_field The relation field in the foreign table
*/
- function __construct($master_table, $master_field, $foreign_table,
+ public function __construct(
+ $diagram, $master_table, $master_field, $foreign_table,
$foreign_field
) {
$this->wTick = 5;
parent::__construct(
- $master_table, $master_field, $foreign_table, $foreign_field
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
);
}
@@ -49,8 +51,6 @@ class Relation_Stats_Pdf extends RelationStats
* @param boolean $showColor Whether to use one color per relation or not
* @param integer $i The id of the link to draw
*
- * @global object $pdf The current PDF document
- *
* @access public
*
* @return void
@@ -59,8 +59,6 @@ class Relation_Stats_Pdf extends RelationStats
*/
public function relationDraw($showColor, $i)
{
- global $pdf;
-
if ($showColor) {
$d = $i % 6;
$j = ($i - $d) / 6;
@@ -76,25 +74,25 @@ class Relation_Stats_Pdf extends RelationStats
);
list ($a, $b, $c) = $case[$d];
$e = (1 - ($j - 1) / 6);
- $pdf->SetDrawColor($a * 255 * $e, $b * 255 * $e, $c * 255 * $e);
+ $this->diagram->SetDrawColor($a * 255 * $e, $b * 255 * $e, $c * 255 * $e);
} else {
- $pdf->SetDrawColor(0);
+ $this->diagram->SetDrawColor(0);
}
- $pdf->setLineWidthScale(0.2);
- $pdf->lineScale(
+ $this->diagram->setLineWidthScale(0.2);
+ $this->diagram->lineScale(
$this->xSrc,
$this->ySrc,
$this->xSrc + $this->srcDir * $this->wTick,
$this->ySrc
);
- $pdf->lineScale(
+ $this->diagram->lineScale(
$this->xDest + $this->destDir * $this->wTick,
$this->yDest,
$this->xDest,
$this->yDest
);
- $pdf->setLineWidthScale(0.1);
- $pdf->lineScale(
+ $this->diagram->setLineWidthScale(0.1);
+ $this->diagram->lineScale(
$this->xSrc + $this->srcDir * $this->wTick,
$this->ySrc,
$this->xDest + $this->destDir * $this->wTick,
@@ -104,32 +102,31 @@ class Relation_Stats_Pdf extends RelationStats
* Draws arrows ->
*/
$root2 = 2 * sqrt(2);
- $pdf->lineScale(
+ $this->diagram->lineScale(
$this->xSrc + $this->srcDir * $this->wTick * 0.75,
$this->ySrc,
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
$this->ySrc + $this->wTick / $root2
);
- $pdf->lineScale(
+ $this->diagram->lineScale(
$this->xSrc + $this->srcDir * $this->wTick * 0.75,
$this->ySrc,
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
$this->ySrc - $this->wTick / $root2
);
- $pdf->lineScale(
+ $this->diagram->lineScale(
$this->xDest + $this->destDir * $this->wTick / 2,
$this->yDest,
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
$this->yDest + $this->wTick / $root2
);
- $pdf->lineScale(
+ $this->diagram->lineScale(
$this->xDest + $this->destDir * $this->wTick / 2,
$this->yDest,
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
$this->yDest - $this->wTick / $root2
);
- $pdf->SetDrawColor(0);
+ $this->diagram->SetDrawColor(0);
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/pdf/TableStatsPdf.class.php b/libraries/plugins/schema/pdf/TableStatsPdf.class.php
index 961142e139..1005bb8936 100644
--- a/libraries/plugins/schema/pdf/TableStatsPdf.class.php
+++ b/libraries/plugins/schema/pdf/TableStatsPdf.class.php
@@ -33,6 +33,8 @@ class Table_Stats_Pdf extends TableStats
/**
* The "Table_Stats_Pdf" constructor
*
+ * @param object $diagram The PDF diagram
+ * @param string $db The database name
* @param string $tableName The table name
* @param integer $fontSize The font size
* @param integer $pageNumber The current page number (from the
@@ -43,17 +45,15 @@ class Table_Stats_Pdf extends TableStats
* @param boolean $offline Whether the coordinates are sent
* from the browser
*
- * @global object $pdf The current PDF document
- *
* @see PMA_Schema_PDF, Table_Stats_Pdf::Table_Stats_setWidth,
* Table_Stats_Pdf::Table_Stats_setHeight
*/
- function __construct($tableName, $fontSize, $pageNumber, &$sameWideWidth,
+ public function __construct(
+ $diagram, $db, $tableName, $fontSize, $pageNumber, &$sameWideWidth,
$showKeys = false, $tableDimension = false, $offline = false
) {
- global $pdf;
parent::__construct(
- $pdf, $GLOBALS['db'], $pageNumber, $tableName,
+ $diagram, $db, $pageNumber, $tableName,
$showKeys, $tableDimension, $offline
);
@@ -103,8 +103,6 @@ class Table_Stats_Pdf extends TableStats
*
* @param integer $fontSize The font size
*
- * @global object $pdf The current PDF document
- *
* @access private
*
* @return void
@@ -113,21 +111,19 @@ class Table_Stats_Pdf extends TableStats
*/
private function _setWidth($fontSize)
{
- global $pdf;
-
foreach ($this->fields as $field) {
- $this->width = max($this->width, $pdf->GetStringWidth($field));
+ $this->width = max($this->width, $this->diagram->GetStringWidth($field));
}
- $this->width += $pdf->GetStringWidth(' ');
- $pdf->SetFont($this->_ff, 'B', $fontSize);
+ $this->width += $this->diagram->GetStringWidth(' ');
+ $this->diagram->SetFont($this->_ff, 'B', $fontSize);
/*
* it is unknown what value must be added, because
* table title is affected by the table width value
*/
- while ($this->width < $pdf->GetStringWidth($this->getTitle())) {
+ while ($this->width < $this->diagram->GetStringWidth($this->getTitle())) {
$this->width += 5;
}
- $pdf->SetFont($this->_ff, '', $fontSize);
+ $this->diagram->SetFont($this->_ff, '', $fontSize);
}
/**
@@ -149,8 +145,6 @@ class Table_Stats_Pdf extends TableStats
* @param boolean $withDoc Whether to include links to documentation
* @param boolean|integer $setColor Whether to display color
*
- * @global object $pdf The current PDF document
- *
* @access public
*
* @return void
@@ -159,21 +153,19 @@ class Table_Stats_Pdf extends TableStats
*/
public function tableDraw($fontSize, $withDoc, $setColor = 0)
{
- global $pdf;
-
- $pdf->setXyScale($this->x, $this->y);
- $pdf->SetFont($this->_ff, 'B', $fontSize);
+ $this->diagram->setXyScale($this->x, $this->y);
+ $this->diagram->SetFont($this->_ff, 'B', $fontSize);
if ($setColor) {
- $pdf->SetTextColor(200);
- $pdf->SetFillColor(0, 0, 128);
+ $this->diagram->SetTextColor(200);
+ $this->diagram->SetFillColor(0, 0, 128);
}
if ($withDoc) {
- $pdf->SetLink($pdf->PMA_links['RT'][$this->tableName]['-'], -1);
+ $this->diagram->SetLink($this->diagram->PMA_links['RT'][$this->tableName]['-'], -1);
} else {
- $pdf->PMA_links['doc'][$this->tableName]['-'] = '';
+ $this->diagram->PMA_links['doc'][$this->tableName]['-'] = '';
}
- $pdf->cellScale(
+ $this->diagram->cellScale(
$this->width,
$this->heightCell,
$this->getTitle(),
@@ -181,29 +173,29 @@ class Table_Stats_Pdf extends TableStats
1,
'C',
$setColor,
- $pdf->PMA_links['doc'][$this->tableName]['-']
+ $this->diagram->PMA_links['doc'][$this->tableName]['-']
);
- $pdf->setXScale($this->x);
- $pdf->SetFont($this->_ff, '', $fontSize);
- $pdf->SetTextColor(0);
- $pdf->SetFillColor(255);
+ $this->diagram->setXScale($this->x);
+ $this->diagram->SetFont($this->_ff, '', $fontSize);
+ $this->diagram->SetTextColor(0);
+ $this->diagram->SetFillColor(255);
foreach ($this->fields as $field) {
if ($setColor) {
if (in_array($field, $this->primary)) {
- $pdf->SetFillColor(215, 121, 123);
+ $this->diagram->SetFillColor(215, 121, 123);
}
if ($field == $this->displayfield) {
- $pdf->SetFillColor(142, 159, 224);
+ $this->diagram->SetFillColor(142, 159, 224);
}
}
if ($withDoc) {
- $pdf->SetLink($pdf->PMA_links['RT'][$this->tableName][$field], -1);
+ $this->diagram->SetLink($this->diagram->PMA_links['RT'][$this->tableName][$field], -1);
} else {
- $pdf->PMA_links['doc'][$this->tableName][$field] = '';
+ $this->diagram->PMA_links['doc'][$this->tableName][$field] = '';
}
- $pdf->cellScale(
+ $this->diagram->cellScale(
$this->width,
$this->heightCell,
' ' . $field,
@@ -211,12 +203,11 @@ class Table_Stats_Pdf extends TableStats
1,
'L',
$setColor,
- $pdf->PMA_links['doc'][$this->tableName][$field]
+ $this->diagram->PMA_links['doc'][$this->tableName][$field]
);
- $pdf->setXScale($this->x);
- $pdf->SetFillColor(255);
+ $this->diagram->setXScale($this->x);
+ $this->diagram->SetFillColor(255);
}
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/svg/RelationStatsSvg.class.php b/libraries/plugins/schema/svg/RelationStatsSvg.class.php
index 870fdc4e53..ed30c05ce8 100644
--- a/libraries/plugins/schema/svg/RelationStatsSvg.class.php
+++ b/libraries/plugins/schema/svg/RelationStatsSvg.class.php
@@ -28,17 +28,18 @@ class Relation_Stats_Svg extends RelationStats
/**
* The "Relation_Stats_Svg" constructor
*
+ * @param object $diagram The SVG diagram
* @param string $master_table The master table name
* @param string $master_field The relation field in the master table
* @param string $foreign_table The foreign table name
* @param string $foreign_field The relation field in the foreign table
*/
- function __construct($master_table, $master_field, $foreign_table,
- $foreign_field
+ public function __construct(
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
) {
$this->wTick = 10;
parent::__construct(
- $master_table, $master_field, $foreign_table, $foreign_field
+ $diagram, $master_table, $master_field, $foreign_table, $foreign_field
);
}
@@ -47,8 +48,6 @@ class Relation_Stats_Svg extends RelationStats
*
* @param boolean $showColor Whether to use one color per relation or not
*
- * @global object $svg The current SVG image document
- *
* @return void
* @access public
*
@@ -56,64 +55,61 @@ class Relation_Stats_Svg extends RelationStats
*/
public function relationDraw($showColor)
{
- global $svg;
-
if ($showColor) {
$listOfColors = array(
- 'red',
- 'grey',
- 'black',
- 'yellow',
- 'green',
- 'cyan',
- ' orange'
+ '#c00',
+ '#bbb',
+ '#333',
+ '#cb0',
+ '#0b0',
+ '#0bf',
+ '#b0b'
);
shuffle($listOfColors);
$color = $listOfColors[0];
} else {
- $color = 'black';
+ $color = '#333';
}
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xSrc, $this->ySrc,
$this->xSrc + $this->srcDir * $this->wTick, $this->ySrc,
- 'fill:' . $color . ';stroke:black;stroke-width:2;'
+ 'stroke:' . $color . ';stroke-width:1;'
);
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xDest + $this->destDir * $this->wTick,
$this->yDest, $this->xDest, $this->yDest,
- 'fill:' . $color . ';stroke:black;stroke-width:2;'
+ 'stroke:' . $color . ';stroke-width:1;'
);
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xSrc + $this->srcDir * $this->wTick, $this->ySrc,
$this->xDest + $this->destDir * $this->wTick, $this->yDest,
- 'fill:' . $color . ';stroke:' . $color . ';stroke-width:1;'
+ 'stroke:' . $color . ';stroke-width:1;'
);
$root2 = 2 * sqrt(2);
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc,
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
$this->ySrc + $this->wTick / $root2,
- 'fill:' . $color . ';stroke:black;stroke-width:2;'
+ 'stroke:' . $color . ';stroke-width:2;'
);
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc,
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
$this->ySrc - $this->wTick / $root2,
- 'fill:' . $color . ';stroke:black;stroke-width:2;'
+ 'stroke:' . $color . ';stroke-width:2;'
);
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xDest + $this->destDir * $this->wTick / 2, $this->yDest,
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
$this->yDest + $this->wTick / $root2,
- 'fill:' . $color . ';stroke:black;stroke-width:2;'
+ 'stroke:' . $color . ';stroke-width:2;'
);
- $svg->printElementLine(
+ $this->diagram->printElementLine(
'line', $this->xDest + $this->destDir * $this->wTick / 2, $this->yDest,
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
$this->yDest - $this->wTick / $root2,
- 'fill:' . $color . ';stroke:black;stroke-width:2;'
+ 'stroke:' . $color . ';stroke-width:2;'
);
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/schema/svg/Svg_Relation_Schema.class.php b/libraries/plugins/schema/svg/Svg_Relation_Schema.class.php
index ef6af6d43d..c22bfd64d2 100644
--- a/libraries/plugins/schema/svg/Svg_Relation_Schema.class.php
+++ b/libraries/plugins/schema/svg/Svg_Relation_Schema.class.php
@@ -36,7 +36,7 @@ class PMA_SVG extends XMLWriter
*
* @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument()
*/
- function __construct()
+ public function __construct()
{
$this->openMemory();
/*
@@ -64,9 +64,8 @@ class PMA_SVG extends XMLWriter
* @param string $value sets the title text
*
* @return void
- * @access public
*/
- function setTitle($value)
+ public function setTitle($value)
{
$this->title = $value;
}
@@ -77,9 +76,8 @@ class PMA_SVG extends XMLWriter
* @param string $value sets the author
*
* @return void
- * @access public
*/
- function setAuthor($value)
+ public function setAuthor($value)
{
$this->author = $value;
}
@@ -90,9 +88,8 @@ class PMA_SVG extends XMLWriter
* @param string $value sets the font e.g Arial, Sans-serif etc
*
* @return void
- * @access public
*/
- function setFont($value)
+ public function setFont($value)
{
$this->font = $value;
}
@@ -101,9 +98,8 @@ class PMA_SVG extends XMLWriter
* Get document font
*
* @return string returns the font name
- * @access public
*/
- function getFont()
+ public function getFont()
{
return $this->font;
}
@@ -114,9 +110,8 @@ class PMA_SVG extends XMLWriter
* @param string $value sets the font size in pixels
*
* @return void
- * @access public
*/
- function setFontSize($value)
+ public function setFontSize($value)
{
$this->fontSize = $value;
}
@@ -125,9 +120,8 @@ class PMA_SVG extends XMLWriter
* Get document font size
*
* @return string returns the font size
- * @access public
*/
- function getFontSize()
+ public function getFontSize()
{
return $this->fontSize;
}
@@ -141,17 +135,30 @@ class PMA_SVG extends XMLWriter
*
* @param integer $width total width of the Svg document
* @param integer $height total height of the Svg document
+ * @param integer $x min-x of the view box
+ * @param integer $y min-y of the view box
*
* @return void
- * @access public
*
* @see XMLWriter::startElement(),XMLWriter::writeAttribute()
*/
- function startSvgDoc($width,$height)
+ public function startSvgDoc($width, $height, $x = 0, $y = 0)
{
$this->startElement('svg');
- $this->writeAttribute('width', $width);
- $this->writeAttribute('height', $height);
+
+ if (!is_int($width)) {
+ $width = intval($width);
+ }
+
+ if (!is_int($height)) {
+ $height = intval($height);
+ }
+
+ if ($x != 0 || $y != 0) {
+ $this->writeAttribute('viewBox', "$x $y $width $height");
+ }
+ $this->writeAttribute('width', ($width - $x) . 'px');
+ $this->writeAttribute('height', ($height - $y) . 'px');
$this->writeAttribute('xmlns', 'http://www.w3.org/2000/svg');
$this->writeAttribute('version', '1.1');
}
@@ -160,10 +167,9 @@ class PMA_SVG extends XMLWriter
* Ends Svg Document
*
* @return void
- * @access public
* @see XMLWriter::endElement(),XMLWriter::endDocument()
*/
- function endSvgDoc()
+ public function endSvgDoc()
{
$this->endElement();
$this->endDocument();
@@ -179,10 +185,9 @@ class PMA_SVG extends XMLWriter
* @param string $fileName file name
*
* @return void
- * @access public
* @see XMLWriter::startElement(),XMLWriter::writeAttribute()
*/
- function showOutput($fileName)
+ public function showOutput($fileName)
{
//ob_get_clean();
$output = $this->flush();
@@ -215,12 +220,11 @@ class PMA_SVG extends XMLWriter
* styles can be defined like CSS styles
*
* @return void
- * @access public
*
* @see XMLWriter::startElement(), XMLWriter::writeAttribute(),
* XMLWriter::text(), XMLWriter::endElement()
*/
- function printElement($name, $x, $y, $width = '', $height = '',
+ public function printElement($name, $x, $y, $width = '', $height = '',
$text = '', $styles = ''
) {
$this->startElement($name);
@@ -253,12 +257,11 @@ class PMA_SVG extends XMLWriter
* styles can be defined like CSS styles
*
* @return void
- * @access public
*
* @see XMLWriter::startElement(), XMLWriter::writeAttribute(),
* XMLWriter::endElement()
*/
- function printElementLine($name,$x1,$y1,$x2,$y2,$styles)
+ public function printElementLine($name,$x1,$y1,$x2,$y2,$styles)
{
$this->startElement($name);
$this->writeAttribute('x1', $x1);
@@ -287,8 +290,12 @@ class PMA_SVG extends XMLWriter
*/
class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
{
-
+ /**
+ * @var Table_Stats_Dia[]|Table_Stats_Eps[]|Table_Stats_Pdf[]|Table_Stats_Svg[]
+ */
private $_tables = array();
+
+ /** @var Relation_Stats_Dia[] Relations */
private $_relations = array();
private $_xMax = 0;
private $_yMax = 0;
@@ -302,51 +309,60 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
* Upon instantiation This starts writing the SVG XML document
* user will be prompted for download as .svg extension
*
+ * @param string $db database name
+ *
* @see PMA_SVG
*/
- function __construct()
+ function __construct($db)
{
- parent::__construct();
-
- global $svg;
+ parent::__construct($db, new PMA_SVG());
$this->setShowColor(isset($_REQUEST['svg_show_color']));
$this->setShowKeys(isset($_REQUEST['svg_show_keys']));
$this->setTableDimension(isset($_REQUEST['svg_show_table_dimension']));
$this->setAllTablesSameWidth(isset($_REQUEST['svg_all_tables_same_width']));
- $svg = new PMA_SVG();
- $svg->setTitle(
+ $this->diagram->setTitle(
sprintf(
__('Schema of the %s database - Page %s'),
- $GLOBALS['db'],
+ $this->db,
$this->pageNumber
)
);
- $svg->SetAuthor('phpMyAdmin ' . PMA_VERSION);
- $svg->setFont('Arial');
- $svg->setFontSize('16px');
- $svg->startSvgDoc('1000px', '1000px');
+ $this->diagram->SetAuthor('phpMyAdmin ' . PMA_VERSION);
+ $this->diagram->setFont('Arial');
+ $this->diagram->setFontSize('16px');
$alltables = $this->getTablesFromRequest();
foreach ($alltables as $table) {
if (! isset($this->_tables[$table])) {
$this->_tables[$table] = new Table_Stats_Svg(
- $table, $svg->getFont(), $svg->getFontSize(), $this->pageNumber,
+ $this->diagram, $this->db,
+ $table, $this->diagram->getFont(),
+ $this->diagram->getFontSize(), $this->pageNumber,
$this->_tablewidth, $this->showKeys, $this->tableDimension,
$this->offline
);
}
if ($this->sameWide) {
- $this->_tables[$table]->width = $this->_tablewidth;
+ $this->_tables[$table]->width = &$this->_tablewidth;
}
$this->_setMinMax($this->_tables[$table]);
}
+
+ $border = 15;
+ $this->diagram->startSvgDoc(
+ $this->_xMax + $border,
+ $this->_yMax + $border,
+ $this->_xMin - $border,
+ $this->_yMin - $border
+ );
+
$seen_a_relation = false;
foreach ($alltables as $one_table) {
- $exist_rel = PMA_getForeigners($GLOBALS['db'], $one_table, '', 'both');
+ $exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
if (!$exist_rel) {
continue;
}
@@ -361,9 +377,13 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
if ($master_field != 'foreign_keys_data') {
if (in_array($rel['foreign_table'], $alltables)) {
$this->_addRelation(
- $one_table, $svg->getFont(), $svg->getFontSize(),
- $master_field, $rel['foreign_table'],
- $rel['foreign_field'], $this->tableDimension
+ $one_table,
+ $this->diagram->getFont(),
+ $this->diagram->getFontSize(),
+ $master_field,
+ $rel['foreign_table'],
+ $rel['foreign_field'],
+ $this->tableDimension
);
}
continue;
@@ -378,8 +398,8 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
as $index => $one_field
) {
$this->_addRelation(
- $one_table, $svg->getFont(),
- $svg->getFontSize(),
+ $one_table, $this->diagram->getFont(),
+ $this->diagram->getFontSize(),
$one_field, $one_key['ref_table_name'],
$one_key['ref_index_list'][$index],
$this->tableDimension
@@ -393,19 +413,17 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
}
$this->_drawTables();
- $svg->endSvgDoc();
+ $this->diagram->endSvgDoc();
}
/**
* Output Svg Document for download
*
* @return void
- * @access public
*/
- function showOutput()
+ public function showOutput()
{
- global $svg;
- $svg->showOutput($this->getFileName('.svg'));
+ $this->diagram->showOutput($this->getFileName('.svg'));
}
@@ -415,7 +433,6 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
* @param string $table The table name
*
* @return void
- * @access private
*/
private function _setMinMax($table)
{
@@ -436,7 +453,6 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
* @param string $foreignField The relation field in the foreign table
* @param boolean $tableDimension Whether to display table position or not
*
- * @access private
* @return void
*
* @see _setMinMax,Table_Stats_Svg::__construct(),
@@ -448,6 +464,7 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
) {
if (! isset($this->_tables[$masterTable])) {
$this->_tables[$masterTable] = new Table_Stats_Svg(
+ $this->diagram, $this->db,
$masterTable, $font, $fontSize, $this->pageNumber,
$this->_tablewidth, false, $tableDimension
);
@@ -455,14 +472,18 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
}
if (! isset($this->_tables[$foreignTable])) {
$this->_tables[$foreignTable] = new Table_Stats_Svg(
+ $this->diagram, $this->db,
$foreignTable, $font, $fontSize, $this->pageNumber,
$this->_tablewidth, false, $tableDimension
);
$this->_setMinMax($this->_tables[$foreignTable]);
}
$this->_relations[] = new Relation_Stats_Svg(
- $this->_tables[$masterTable], $masterField,
- $this->_tables[$foreignTable], $foreignField
+ $this->diagram,
+ $this->_tables[$masterTable],
+ $masterField,
+ $this->_tables[$foreignTable],
+ $foreignField
);
}
@@ -472,7 +493,6 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
* foreign table's foreign field
*
* @return void
- * @access private
*
* @see Relation_Stats_Svg::relationDraw()
*/
@@ -487,7 +507,6 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
* Draws tables
*
* @return void
- * @access private
*
* @see Table_Stats_Svg::Table_Stats_tableDraw()
*/
@@ -498,4 +517,3 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
}
}
}
-?>
diff --git a/libraries/plugins/schema/svg/TableStatsSvg.class.php b/libraries/plugins/schema/svg/TableStatsSvg.class.php
index c82f039926..5494f8ab67 100644
--- a/libraries/plugins/schema/svg/TableStatsSvg.class.php
+++ b/libraries/plugins/schema/svg/TableStatsSvg.class.php
@@ -32,6 +32,8 @@ class Table_Stats_Svg extends TableStats
/**
* The "Table_Stats_Svg" constructor
*
+ * @param object $diagram The current SVG image document
+ * @param string $db The database name
* @param string $tableName The table name
* @param string $font Font face
* @param integer $fontSize The font size
@@ -40,22 +42,17 @@ class Table_Stats_Svg extends TableStats
* @param boolean $showKeys Whether to display keys or not
* @param boolean $tableDimension Whether to display table position or not
* @param boolean $offline Whether the coordinates are sent
- * from the browser
*
- * @global object $svg The current SVG image document
- *
- * @access private
*
* @see PMA_SVG, Table_Stats_Svg::Table_Stats_setWidth,
* Table_Stats_Svg::Table_Stats_setHeight
*/
- function __construct(
- $tableName, $font, $fontSize, $pageNumber, &$same_wide_width,
+ public function __construct(
+ $diagram, $db, $tableName, $font, $fontSize, $pageNumber, &$same_wide_width,
$showKeys = false, $tableDimension = false, $offline = false
) {
- global $svg;
parent::__construct(
- $svg, $GLOBALS['db'], $pageNumber, $tableName,
+ $diagram, $db, $pageNumber, $tableName,
$showKeys, $tableDimension, $offline
);
@@ -89,8 +86,6 @@ class Table_Stats_Svg extends TableStats
* @param string $font The font size
* @param integer $fontSize The font size
*
- * @global object $svg The current SVG image document
- *
* @return void
* @access private
*
@@ -123,9 +118,8 @@ class Table_Stats_Svg extends TableStats
* @param integer $fontSize font size
*
* @return void
- * @access private
*/
- function _setHeightTable($fontSize)
+ private function _setHeightTable($fontSize)
{
$this->heightCell = $fontSize + 4;
$this->height = (count($this->fields) + 1) * $this->heightCell;
@@ -136,8 +130,6 @@ class Table_Stats_Svg extends TableStats
*
* @param boolean $showColor Whether to display color
*
- * @global object $svg The current SVG image document
- *
* @access public
* @return void
*
@@ -145,36 +137,33 @@ class Table_Stats_Svg extends TableStats
*/
public function tableDraw($showColor)
{
- global $svg;
-
- $svg->printElement(
+ $this->diagram->printElement(
'rect', $this->x, $this->y, $this->width,
- $this->heightCell, null, 'fill:red;stroke:black;'
+ $this->heightCell, null, 'fill:#007;stroke:black;'
);
- $svg->printElement(
+ $this->diagram->printElement(
'text', $this->x + 5, $this->y+ 14, $this->width, $this->heightCell,
- $this->getTitle(), 'fill:none;stroke:black;'
+ $this->getTitle(), 'fill:#fff;'
);
foreach ($this->fields as $field) {
$this->currentCell += $this->heightCell;
$fillColor = 'none';
if ($showColor) {
if (in_array($field, $this->primary)) {
- $fillColor = '#0c0';
+ $fillColor = '#aea';
}
if ($field == $this->displayfield) {
$fillColor = 'none';
}
}
- $svg->printElement(
+ $this->diagram->printElement(
'rect', $this->x, $this->y + $this->currentCell, $this->width,
$this->heightCell, null, 'fill:' . $fillColor . ';stroke:black;'
);
- $svg->printElement(
+ $this->diagram->printElement(
'text', $this->x + 5, $this->y + 14 + $this->currentCell,
- $this->width, $this->heightCell, $field, 'fill:none;stroke:black;'
+ $this->width, $this->heightCell, $field, 'fill:black;'
);
}
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/Text_Plain_Link.class.php b/libraries/plugins/transformations/Text_Plain_Link.class.php
index d1b17d5ec8..de080bf930 100644
--- a/libraries/plugins/transformations/Text_Plain_Link.class.php
+++ b/libraries/plugins/transformations/Text_Plain_Link.class.php
@@ -41,4 +41,3 @@ class Text_Plain_Link extends TextLinkTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/Text_Plain_Longtoipv4.class.php b/libraries/plugins/transformations/Text_Plain_Longtoipv4.class.php
index 9f58a45eb3..ba08d4405f 100644
--- a/libraries/plugins/transformations/Text_Plain_Longtoipv4.class.php
+++ b/libraries/plugins/transformations/Text_Plain_Longtoipv4.class.php
@@ -41,4 +41,3 @@ class Text_Plain_Longtoipv4 extends LongToIPv4TransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/Text_Plain_Preappend.class.php b/libraries/plugins/transformations/Text_Plain_Preappend.class.php
index 7423ee6c15..165a7c611e 100644
--- a/libraries/plugins/transformations/Text_Plain_Preappend.class.php
+++ b/libraries/plugins/transformations/Text_Plain_Preappend.class.php
@@ -42,4 +42,3 @@ class Text_Plain_PreApPend extends PreApPendTransformationsPlugin
return "Plain";
}
}
-?>
diff --git a/libraries/plugins/transformations/Text_Plain_Substring.class.php b/libraries/plugins/transformations/Text_Plain_Substring.class.php
index 051ae51cd3..50e3a7450f 100644
--- a/libraries/plugins/transformations/Text_Plain_Substring.class.php
+++ b/libraries/plugins/transformations/Text_Plain_Substring.class.php
@@ -41,4 +41,3 @@ class Text_Plain_Substring extends SubstringTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/abstract/Bool2TextTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/Bool2TextTransformationsPlugin.class.php
index 11a0a586be..3517996a2a 100644
--- a/libraries/plugins/transformations/abstract/Bool2TextTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/Bool2TextTransformationsPlugin.class.php
@@ -66,4 +66,3 @@ abstract class Bool2TextTransformationsPlugin extends TransformationsPlugin
return "Bool2Text";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/CodeMirrorEditorTransformationPlugin.class.php b/libraries/plugins/transformations/abstract/CodeMirrorEditorTransformationPlugin.class.php
index 9efeb188ad..a47ca0b468 100644
--- a/libraries/plugins/transformations/abstract/CodeMirrorEditorTransformationPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/CodeMirrorEditorTransformationPlugin.class.php
@@ -43,11 +43,15 @@ abstract class CodeMirrorEditorTransformationsPlugin extends IOTransformationsPl
* @param array $options transformation options
* @param string $value Current field value
* @param string $text_dir text direction
+ * @param int $tabindex tab index
+ * @param int $tabindex_for_value offset for the values tabindex
+ * @param int $idindex id index
*
* @return string the html for input field
*/
public function getInputHtml(
- $column, $row_id, $column_name_appendix, $options, $value, $text_dir
+ $column, $row_id, $column_name_appendix, $options, $value, $text_dir,
+ $tabindex, $tabindex_for_value, $idindex
) {
$html = '';
if (! empty($value)) {
@@ -61,4 +65,3 @@ abstract class CodeMirrorEditorTransformationsPlugin extends IOTransformationsPl
return $html;
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/abstract/DateFormatTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/DateFormatTransformationsPlugin.class.php
index f039eb7773..c522134d6c 100644
--- a/libraries/plugins/transformations/abstract/DateFormatTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/DateFormatTransformationsPlugin.class.php
@@ -161,4 +161,3 @@ abstract class DateFormatTransformationsPlugin extends TransformationsPlugin
return "Date Format";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/DownloadTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/DownloadTransformationsPlugin.class.php
index f7b10e1f80..8b044c48e7 100644
--- a/libraries/plugins/transformations/abstract/DownloadTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/DownloadTransformationsPlugin.class.php
@@ -92,4 +92,3 @@ abstract class DownloadTransformationsPlugin extends TransformationsPlugin
return "Download";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/ExternalTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/ExternalTransformationsPlugin.class.php
index da0c59fb98..5c887d5788 100644
--- a/libraries/plugins/transformations/abstract/ExternalTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/ExternalTransformationsPlugin.class.php
@@ -152,4 +152,3 @@ abstract class ExternalTransformationsPlugin extends TransformationsPlugin
return "External";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/FormattedTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/FormattedTransformationsPlugin.class.php
index 13fba35a35..b2610ecaf2 100644
--- a/libraries/plugins/transformations/abstract/FormattedTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/FormattedTransformationsPlugin.class.php
@@ -62,4 +62,3 @@ abstract class FormattedTransformationsPlugin extends TransformationsPlugin
return "Formatted";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/HexTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/HexTransformationsPlugin.class.php
index 8625f87102..a437c149e4 100644
--- a/libraries/plugins/transformations/abstract/HexTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/HexTransformationsPlugin.class.php
@@ -69,4 +69,3 @@ abstract class HexTransformationsPlugin extends TransformationsPlugin
return "Hex";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/ImageLinkTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/ImageLinkTransformationsPlugin.class.php
index 2cd3bbb0c9..6a63652198 100644
--- a/libraries/plugins/transformations/abstract/ImageLinkTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/ImageLinkTransformationsPlugin.class.php
@@ -71,4 +71,3 @@ abstract class ImageLinkTransformationsPlugin extends TransformationsPlugin
return "ImageLink";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/ImageUploadTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/ImageUploadTransformationsPlugin.class.php
index 8cfd04c402..1ef234ed73 100644
--- a/libraries/plugins/transformations/abstract/ImageUploadTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/ImageUploadTransformationsPlugin.class.php
@@ -58,11 +58,15 @@ abstract class ImageUploadTransformationsPlugin extends IOTransformationsPlugin
* @param array $options transformation options
* @param string $value Current field value
* @param string $text_dir text direction
+ * @param int $tabindex tab index
+ * @param int $tabindex_for_value offset for the values tabindex
+ * @param int $idindex id index
*
* @return string the html for input field
*/
public function getInputHtml(
- $column, $row_id, $column_name_appendix, $options, $value, $text_dir
+ $column, $row_id, $column_name_appendix, $options, $value, $text_dir,
+ $tabindex, $tabindex_for_value, $idindex
) {
$html = '';
$src = '';
@@ -107,4 +111,3 @@ abstract class ImageUploadTransformationsPlugin extends IOTransformationsPlugin
return "Image upload";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/InlineTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/InlineTransformationsPlugin.class.php
index 72fbf7bb50..40540d7a0f 100644
--- a/libraries/plugins/transformations/abstract/InlineTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/InlineTransformationsPlugin.class.php
@@ -83,4 +83,3 @@ abstract class InlineTransformationsPlugin extends TransformationsPlugin
return "Inline";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/LongToIPv4TransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/LongToIPv4TransformationsPlugin.class.php
index d32c6d28f2..2014a6db31 100644
--- a/libraries/plugins/transformations/abstract/LongToIPv4TransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/LongToIPv4TransformationsPlugin.class.php
@@ -28,8 +28,8 @@ abstract class LongToIPv4TransformationsPlugin extends TransformationsPlugin
public static function getInfo()
{
return __(
- 'Converts an (IPv4) Internet network address into a string in'
- . ' Internet standard dotted format.'
+ 'Converts an (IPv4) Internet network address stored as a BIGINT'
+ . ' into a string in Internet standard dotted format.'
);
}
@@ -65,4 +65,3 @@ abstract class LongToIPv4TransformationsPlugin extends TransformationsPlugin
return "Long To IPv4";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/PreApPendTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/PreApPendTransformationsPlugin.class.php
index f9cfe65af6..8bb04e898a 100644
--- a/libraries/plugins/transformations/abstract/PreApPendTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/PreApPendTransformationsPlugin.class.php
@@ -68,4 +68,3 @@ abstract class PreApPendTransformationsPlugin extends TransformationsPlugin
return "PreApPend";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/RegexValidationTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/RegexValidationTransformationsPlugin.class.php
index c01b53a486..d427c73cff 100644
--- a/libraries/plugins/transformations/abstract/RegexValidationTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/RegexValidationTransformationsPlugin.class.php
@@ -71,4 +71,3 @@ abstract class RegexValidationTransformationsPlugin extends IOTransformationsPlu
return "Regex Validation";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/SQLTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/SQLTransformationsPlugin.class.php
index 09804f7ef7..c525f2f496 100644
--- a/libraries/plugins/transformations/abstract/SQLTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/SQLTransformationsPlugin.class.php
@@ -45,8 +45,6 @@ abstract class SQLTransformationsPlugin extends TransformationsPlugin
{
// see PMA_highlightSQL()
$result = PMA_Util::formatSql($buffer);
- // Need to clear error state not to break subsequent queries display.
- PMA_SQP_resetError();
return $result;
}
@@ -64,4 +62,3 @@ abstract class SQLTransformationsPlugin extends TransformationsPlugin
return "SQL";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/SubstringTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/SubstringTransformationsPlugin.class.php
index 05097fa6de..1547ef1cae 100644
--- a/libraries/plugins/transformations/abstract/SubstringTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/SubstringTransformationsPlugin.class.php
@@ -89,4 +89,3 @@ abstract class SubstringTransformationsPlugin extends TransformationsPlugin
return "Substring";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/TextFileUploadTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/TextFileUploadTransformationsPlugin.class.php
index f7e3ee1427..6276bbecf0 100644
--- a/libraries/plugins/transformations/abstract/TextFileUploadTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/TextFileUploadTransformationsPlugin.class.php
@@ -59,11 +59,15 @@ abstract class TextFileUploadTransformationsPlugin extends IOTransformationsPlug
* @param array $options transformation options
* @param string $value Current field value
* @param string $text_dir text direction
+ * @param int $tabindex tab index
+ * @param int $tabindex_for_value offset for the values tabindex
+ * @param int $idindex id index
*
* @return string the html for input field
*/
public function getInputHtml(
- $column, $row_id, $column_name_appendix, $options, $value, $text_dir
+ $column, $row_id, $column_name_appendix, $options, $value, $text_dir,
+ $tabindex, $tabindex_for_value, $idindex
) {
$html = '';
if (!empty($value)) {
@@ -90,4 +94,3 @@ abstract class TextFileUploadTransformationsPlugin extends IOTransformationsPlug
return "Text file upload";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/TextImageLinkTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/TextImageLinkTransformationsPlugin.class.php
index 08e5646cea..27faf67c41 100644
--- a/libraries/plugins/transformations/abstract/TextImageLinkTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/TextImageLinkTransformationsPlugin.class.php
@@ -78,4 +78,3 @@ abstract class TextImageLinkTransformationsPlugin extends TransformationsPlugin
return "Image Link";
}
}
-?>
diff --git a/libraries/plugins/transformations/abstract/TextLinkTransformationsPlugin.class.php b/libraries/plugins/transformations/abstract/TextLinkTransformationsPlugin.class.php
index 92e34920a7..64ae2d53c6 100644
--- a/libraries/plugins/transformations/abstract/TextLinkTransformationsPlugin.class.php
+++ b/libraries/plugins/transformations/abstract/TextLinkTransformationsPlugin.class.php
@@ -79,4 +79,3 @@ abstract class TextLinkTransformationsPlugin extends TransformationsPlugin
return "TextLink";
}
}
-?>
diff --git a/libraries/plugins/transformations/input/Image_JPEG_Upload.class.php b/libraries/plugins/transformations/input/Image_JPEG_Upload.class.php
index 3c87ffc7d5..ebeb1a68e4 100644
--- a/libraries/plugins/transformations/input/Image_JPEG_Upload.class.php
+++ b/libraries/plugins/transformations/input/Image_JPEG_Upload.class.php
@@ -43,4 +43,3 @@ class Image_JPEG_Upload extends ImageUploadTransformationsPlugin
return "JPEG";
}
}
-?>
diff --git a/libraries/plugins/transformations/input/Text_Plain_Fileupload.class.php b/libraries/plugins/transformations/input/Text_Plain_Fileupload.class.php
index 6b0e6379f8..223356860e 100644
--- a/libraries/plugins/transformations/input/Text_Plain_Fileupload.class.php
+++ b/libraries/plugins/transformations/input/Text_Plain_Fileupload.class.php
@@ -42,4 +42,3 @@ class Text_Plain_FileUpload extends TextFileUploadTransformationsPlugin
return "Plain";
}
}
-?>
diff --git a/libraries/plugins/transformations/input/Text_Plain_Iptobinary.class.php b/libraries/plugins/transformations/input/Text_Plain_Iptobinary.class.php
new file mode 100644
index 0000000000..152e256323
--- /dev/null
+++ b/libraries/plugins/transformations/input/Text_Plain_Iptobinary.class.php
@@ -0,0 +1,133 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Handles the IPv4/IPv6 to binary transformation for text plain
+ *
+ * @package PhpMyAdmin-Transformations
+ * @subpackage IPToBinary
+ */
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+/* Get the transformations class */
+require_once 'libraries/plugins/IOTransformationsPlugin.class.php';
+
+/**
+ * Handles the IPv4/IPv6 to binary transformation for text plain
+ *
+ * @package PhpMyAdmin-Transformations
+ * @subpackage IPToBinary
+ */
+class Text_Plain_Iptobinary extends IOTransformationsPlugin
+{
+ /**
+ * Gets the transformation description of the plugin
+ *
+ * @return string
+ */
+ public static function getInfo()
+ {
+ return __(
+ 'Converts an Internet network address in (IPv4/IPv6) format to binary'
+ );
+ }
+
+ /**
+ * 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 string $meta meta information
+ *
+ * @return string IP address
+ */
+ public function applyTransformation($buffer, $options = array(), $meta = '')
+ {
+ $val = @inet_pton($buffer);
+ if ($val !== false) {
+ return $val;
+ }
+ return $buffer;
+ }
+
+ /**
+ * Returns the html for input field to override default textarea.
+ * Note: Return empty string if default textarea is required.
+ *
+ * @param array $column column details
+ * @param int $row_id row number
+ * @param string $column_name_appendix the name attribute
+ * @param array $options transformation options
+ * @param string $value Current field value
+ * @param string $text_dir text direction
+ * @param int $tabindex tab index
+ * @param int $tabindex_for_value offset for the values tabindex
+ * @param int $idindex id index
+ *
+ * @return string the html for input field
+ */
+ public function getInputHtml(
+ $column, $row_id, $column_name_appendix, $options, $value, $text_dir,
+ $tabindex, $tabindex_for_value, $idindex
+ ) {
+ $html = '';
+ $val = '';
+ if (! empty($value)) {
+ $length = strlen($value);
+ if ($length == 4 || $length == 16) {
+ $ip = @inet_ntop(pack('A' . $length, $value));
+ if ($ip !== false) {
+ $val = $ip;
+ }
+ }
+ $html = '<input type="hidden" name="fields_prev' . $column_name_appendix
+ . '" value="' . htmlspecialchars($val) . '"/>';
+ }
+ $class = 'transform_IPToBin';
+ $html .= '<input type="text" name="fields' . $column_name_appendix . '"'
+ . ' value="' . htmlspecialchars($val) . '"'
+ . ' size="40"'
+ . ' dir="' . $text_dir . '"'
+ . ' class="' . $class . '"'
+ . ' id="field_' . ($idindex) . '_3"'
+ . ' tabindex="' . ($tabindex + $tabindex_for_value) . '">'
+ . '</input>';
+ return $html;
+ }
+
+ /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
+
+
+ /**
+ * Gets the transformation name of the plugin
+ *
+ * @return string
+ */
+ public static function getName()
+ {
+ return "IPv4/IPv6 To Binary";
+ }
+
+ /**
+ * Gets the plugin`s MIME type
+ *
+ * @return string
+ */
+ public static function getMIMEType()
+ {
+ return "Text";
+ }
+
+ /**
+ * Gets the plugin`s MIME subtype
+ *
+ * @return string
+ */
+ public static function getMIMESubtype()
+ {
+ return "Plain";
+ }
+}
diff --git a/libraries/plugins/transformations/input/Text_Plain_JsonEditor.class.php b/libraries/plugins/transformations/input/Text_Plain_JsonEditor.class.php
index 1af1330bea..93ab6d6894 100644
--- a/libraries/plugins/transformations/input/Text_Plain_JsonEditor.class.php
+++ b/libraries/plugins/transformations/input/Text_Plain_JsonEditor.class.php
@@ -83,4 +83,3 @@ class Text_Plain_JsonEditor extends CodeMirrorEditorTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/input/Text_Plain_Regexvalidation.class.php b/libraries/plugins/transformations/input/Text_Plain_Regexvalidation.class.php
index d8b6bdd6e9..8f7bf961ef 100644
--- a/libraries/plugins/transformations/input/Text_Plain_Regexvalidation.class.php
+++ b/libraries/plugins/transformations/input/Text_Plain_Regexvalidation.class.php
@@ -43,4 +43,3 @@ class Text_Plain_RegexValidation extends RegexValidationTransformationsPlugin
return "Plain";
}
}
-?>
diff --git a/libraries/plugins/transformations/input/Text_Plain_SqlEditor.class.php b/libraries/plugins/transformations/input/Text_Plain_SqlEditor.class.php
index 61146b053d..df62239d01 100644
--- a/libraries/plugins/transformations/input/Text_Plain_SqlEditor.class.php
+++ b/libraries/plugins/transformations/input/Text_Plain_SqlEditor.class.php
@@ -83,4 +83,3 @@ class Text_Plain_SqlEditor extends CodeMirrorEditorTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/input/Text_Plain_XmlEditor.class.php b/libraries/plugins/transformations/input/Text_Plain_XmlEditor.class.php
index e203ef5d13..df216d0510 100644
--- a/libraries/plugins/transformations/input/Text_Plain_XmlEditor.class.php
+++ b/libraries/plugins/transformations/input/Text_Plain_XmlEditor.class.php
@@ -83,4 +83,3 @@ class Text_Plain_XmlEditor extends CodeMirrorEditorTransformationsPlugin
return "Plain";
}
}
-?>
diff --git a/libraries/plugins/transformations/output/Application_Octetstream_Download.class.php b/libraries/plugins/transformations/output/Application_Octetstream_Download.class.php
index 7ba73e32e9..70a7afe219 100644
--- a/libraries/plugins/transformations/output/Application_Octetstream_Download.class.php
+++ b/libraries/plugins/transformations/output/Application_Octetstream_Download.class.php
@@ -41,4 +41,3 @@ class Application_Octetstream_Download extends DownloadTransformationsPlugin
return "OctetStream";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Application_Octetstream_Hex.class.php b/libraries/plugins/transformations/output/Application_Octetstream_Hex.class.php
index 61e6cc9f5b..b70d5a645c 100644
--- a/libraries/plugins/transformations/output/Application_Octetstream_Hex.class.php
+++ b/libraries/plugins/transformations/output/Application_Octetstream_Hex.class.php
@@ -42,4 +42,3 @@ class Application_Octetstream_Hex extends HexTransformationsPlugin
return "OctetStream";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Image_JPEG_Inline.class.php b/libraries/plugins/transformations/output/Image_JPEG_Inline.class.php
index 9c7d23880c..2a05daf655 100644
--- a/libraries/plugins/transformations/output/Image_JPEG_Inline.class.php
+++ b/libraries/plugins/transformations/output/Image_JPEG_Inline.class.php
@@ -42,4 +42,3 @@ class Image_JPEG_Inline extends InlineTransformationsPlugin
return "JPEG";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Image_JPEG_Link.class.php b/libraries/plugins/transformations/output/Image_JPEG_Link.class.php
index 94897efa04..6c46745cb2 100644
--- a/libraries/plugins/transformations/output/Image_JPEG_Link.class.php
+++ b/libraries/plugins/transformations/output/Image_JPEG_Link.class.php
@@ -42,4 +42,3 @@ class Image_JPEG_Link extends ImageLinkTransformationsPlugin
return "JPEG";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Image_PNG_Inline.class.php b/libraries/plugins/transformations/output/Image_PNG_Inline.class.php
index b22dfdc6a0..c2ea7eeee3 100644
--- a/libraries/plugins/transformations/output/Image_PNG_Inline.class.php
+++ b/libraries/plugins/transformations/output/Image_PNG_Inline.class.php
@@ -42,4 +42,3 @@ class Image_PNG_Inline extends InlineTransformationsPlugin
return "PNG";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Octetstream_Sql.class.php b/libraries/plugins/transformations/output/Text_Octetstream_Sql.class.php
index d8e07bd3d6..4329cfdd88 100644
--- a/libraries/plugins/transformations/output/Text_Octetstream_Sql.class.php
+++ b/libraries/plugins/transformations/output/Text_Octetstream_Sql.class.php
@@ -42,4 +42,3 @@ class Text_Octetstream_Sql extends SQLTransformationsPlugin
return "Octetstream";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_Binarytoip.class.php b/libraries/plugins/transformations/output/Text_Plain_Binarytoip.class.php
new file mode 100644
index 0000000000..4730e6f7d0
--- /dev/null
+++ b/libraries/plugins/transformations/output/Text_Plain_Binarytoip.class.php
@@ -0,0 +1,93 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Handles the binary to IPv4/IPv6 transformation for text plain
+ *
+ * @package PhpMyAdmin-Transformations
+ * @subpackage BinaryToIP
+ */
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+/* Get the transformations interface */
+require_once 'libraries/plugins/TransformationsPlugin.class.php';
+
+/**
+ * Handles the binary to IPv4/IPv6 transformation for text plain
+ *
+ * @package PhpMyAdmin-Transformations
+ * @subpackage BinaryToIP
+ */
+class Text_Plain_Binarytoip extends TransformationsPlugin
+{
+ /**
+ * Gets the transformation description of the plugin
+ *
+ * @return string
+ */
+ public static function getInfo()
+ {
+ return __(
+ 'Converts an Internet network address stored as a binary string'
+ . ' into a string in Internet standard (IPv4/IPv6) format.'
+ );
+ }
+
+ /**
+ * 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 string $meta meta information
+ *
+ * @return string IP address
+ */
+ public function applyTransformation($buffer, $options = array(), $meta = '')
+ {
+ $length = strlen($buffer);
+ if ($length == 4 || $length == 16) {
+ $val = @inet_ntop(pack('A' . $length, $buffer));
+ if ($val !== false) {
+ return $val;
+ }
+ }
+ return $buffer;
+ }
+
+
+ /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
+
+
+ /**
+ * Gets the transformation name of the plugin
+ *
+ * @return string
+ */
+ public static function getName()
+ {
+ return "Binary To IPv4/IPv6";
+ }
+
+ /**
+ * Gets the plugin`s MIME type
+ *
+ * @return string
+ */
+ public static function getMIMEType()
+ {
+ return "Text";
+ }
+
+ /**
+ * Gets the plugin`s MIME subtype
+ *
+ * @return string
+ */
+ public static function getMIMESubtype()
+ {
+ return "Plain";
+ }
+}
diff --git a/libraries/plugins/transformations/output/Text_Plain_Bool2text.class.php b/libraries/plugins/transformations/output/Text_Plain_Bool2text.class.php
index d02c15c151..cab9abf34d 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Bool2text.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Bool2text.class.php
@@ -44,4 +44,3 @@ class Text_Plain_Bool2Text extends Bool2TextTransformationsPlugin
return "Plain";
}
}
-?>
diff --git a/libraries/plugins/transformations/output/Text_Plain_Dateformat.class.php b/libraries/plugins/transformations/output/Text_Plain_Dateformat.class.php
index 41f3da00a8..4e12900e01 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Dateformat.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Dateformat.class.php
@@ -42,4 +42,3 @@ class Text_Plain_Dateformat extends DateFormatTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_External.class.php b/libraries/plugins/transformations/output/Text_Plain_External.class.php
index 9383a8d6bf..7252991437 100644
--- a/libraries/plugins/transformations/output/Text_Plain_External.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_External.class.php
@@ -42,4 +42,3 @@ class Text_Plain_External extends ExternalTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_Formatted.class.php b/libraries/plugins/transformations/output/Text_Plain_Formatted.class.php
index 1c1a3407fe..1088a1b098 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Formatted.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Formatted.class.php
@@ -42,4 +42,3 @@ class Text_Plain_Formatted extends FormattedTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_Imagelink.class.php b/libraries/plugins/transformations/output/Text_Plain_Imagelink.class.php
index 5afffe3281..f445033d82 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Imagelink.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Imagelink.class.php
@@ -42,4 +42,3 @@ class Text_Plain_Imagelink extends TextImageLinkTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_Json.class.php b/libraries/plugins/transformations/output/Text_Plain_Json.class.php
index 621cd1903e..9522b26c9c 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Json.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Json.class.php
@@ -21,6 +21,9 @@ require_once 'libraries/plugins/TransformationsPlugin.class.php';
*/
class Text_Plain_Json extends TransformationsPlugin
{
+ /**
+ * No-arg constructor
+ */
public function __construct()
{
if (! empty($GLOBALS['cfg']['CodemirrorEnable'])) {
@@ -93,4 +96,3 @@ class Text_Plain_Json extends TransformationsPlugin
return "JSON";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_Sql.class.php b/libraries/plugins/transformations/output/Text_Plain_Sql.class.php
index 472acf39f0..6491a87446 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Sql.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Sql.class.php
@@ -22,6 +22,9 @@ require_once 'libraries/plugins/transformations/abstract/'
*/
class Text_Plain_Sql extends SQLTransformationsPlugin
{
+ /**
+ * No-arg constructor
+ */
public function __construct()
{
if (! empty($GLOBALS['cfg']['CodemirrorEnable'])) {
@@ -54,4 +57,3 @@ class Text_Plain_Sql extends SQLTransformationsPlugin
return "Plain";
}
}
-?> \ No newline at end of file
diff --git a/libraries/plugins/transformations/output/Text_Plain_Xml.class.php b/libraries/plugins/transformations/output/Text_Plain_Xml.class.php
index d41880d44b..54a66f86d5 100644
--- a/libraries/plugins/transformations/output/Text_Plain_Xml.class.php
+++ b/libraries/plugins/transformations/output/Text_Plain_Xml.class.php
@@ -21,6 +21,9 @@ require_once 'libraries/plugins/TransformationsPlugin.class.php';
*/
class Text_Plain_Xml extends TransformationsPlugin
{
+ /**
+ * No-arg constructor
+ */
public function __construct()
{
if (! empty($GLOBALS['cfg']['CodemirrorEnable'])) {
@@ -93,4 +96,3 @@ class Text_Plain_Xml extends TransformationsPlugin
return "XML";
}
}
-?>
diff --git a/libraries/pmd_common.php b/libraries/pmd_common.php
index 19f492c056..f451fbc85f 100644
--- a/libraries/pmd_common.php
+++ b/libraries/pmd_common.php
@@ -139,7 +139,7 @@ function PMA_getScriptContr()
//echo "<br> INNO ";
//print_r($row);
if ($row !== false) {
- foreach ($row['foreign_keys_data'] as $key => $one_key) {
+ foreach ($row['foreign_keys_data'] as $one_key) {
foreach ($one_key['index_list'] as $index => $one_field) {
$con['C_NAME'][$i] = '';
$con['DTN'][$i] = urlencode($GLOBALS['db'] . "." . $val[0]);
@@ -312,7 +312,7 @@ function PMA_deletePage($pg)
{
$cfgRelation = PMA_getRelationsParam();
if (! $cfgRelation['pdfwork']) {
- return null;
+ return false;
}
$query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
@@ -331,36 +331,82 @@ function PMA_deletePage($pg)
);
}
- return $success;
+ return (boolean) $success;
}
/**
- * Returns the id of the first pdf page of the database
+ * Returns the id of the default pdf page of the database.
+ * Default page is the one which has the same name as the database.
*
* @param string $db database
*
- * @return int id of the first pdf page, default is -1
+ * @return int id of the default pdf page for the database
*/
-function PMA_getFirstPage($db)
+function PMA_getDefaultPage($db)
{
$cfgRelation = PMA_getRelationsParam();
if (! $cfgRelation['pdfwork']) {
return null;
}
- $query = "SELECT MIN(`page_nr`)"
+ $query = "SELECT `page_nr`"
. " FROM " . PMA_Util::backquote($cfgRelation['db'])
. "." . PMA_Util::backquote($cfgRelation['pdf_pages'])
- . " WHERE `db_name` = '" . $db . "'";
+ . " WHERE `db_name` = '" . PMA_Util::sqlAddSlashes($db) . "'"
+ . " AND `page_descr` = '" . PMA_Util::sqlAddSlashes($db) . "'";
- $min_page_no = $GLOBALS['dbi']->fetchResult(
+ $default_page_no = $GLOBALS['dbi']->fetchResult(
$query,
null,
null,
$GLOBALS['controllink'],
PMA_DatabaseInterface::QUERY_STORE
);
- return count($min_page_no[0]) ? $min_page_no[0] : -1;
+
+ if (count($default_page_no)) {
+ return $default_page_no[0];
+ }
+ return -1;
+}
+
+/**
+ * Get the id of the page to load. If a default page exists it will be returned.
+ * If no such exists, returns the id of the first page of the database.
+ *
+ * @param string $db database
+ *
+ * @return int id of the page to load
+ */
+function PMA_getLoadingPage($db)
+{
+ $cfgRelation = PMA_getRelationsParam();
+ if (! $cfgRelation['pdfwork']) {
+ return null;
+ }
+
+ $page_no = -1;
+
+ $default_page_no = PMA_getDefaultPage($db);
+ if ($default_page_no != -1) {
+ $page_no = $default_page_no;
+ } else {
+ $query = "SELECT MIN(`page_nr`)"
+ . " FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['pdf_pages'])
+ . " WHERE `db_name` = '" . PMA_Util::sqlAddSlashes($db) . "'";
+
+ $min_page_no = $GLOBALS['dbi']->fetchResult(
+ $query,
+ null,
+ null,
+ $GLOBALS['controllink'],
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+ if (count($min_page_no[0])) {
+ $page_no = $min_page_no[0];
+ }
+ }
+ return $page_no;
}
/**
@@ -396,21 +442,21 @@ function PMA_saveTablePositions($pg)
{
$cfgRelation = PMA_getRelationsParam();
if (! $cfgRelation['pdfwork']) {
- return null;
+ return false;
}
- $queury = "DELETE FROM " . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
+ $query = "DELETE FROM " . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
. "." . PMA_Util::backquote($GLOBALS['cfgRelation']['table_coords'])
. " WHERE `db_name` = '" . PMA_Util::sqlAddSlashes($_REQUEST['db']) . "'"
. " AND `pdf_page_number` = '" . PMA_Util::sqlAddSlashes($pg) . "'";
- $res = PMA_queryAsControlUser($queury, true, PMA_DatabaseInterface::QUERY_STORE);
+ $res = PMA_queryAsControlUser($query, true, PMA_DatabaseInterface::QUERY_STORE);
if ($res) {
foreach ($_REQUEST['t_h'] as $key => $value) {
list($DB, $TAB) = explode(".", $key);
if ($value) {
- $queury = "INSERT INTO "
+ $query = "INSERT INTO "
. PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . "."
. PMA_Util::backquote($GLOBALS['cfgRelation']['table_coords'])
. " (`db_name`, `table_name`, `pdf_page_number`, `x`, `y`)"
@@ -422,13 +468,13 @@ function PMA_saveTablePositions($pg)
. "'" . PMA_Util::sqlAddSlashes($_REQUEST['t_y'][$key]) . "')";
$res = PMA_queryAsControlUser(
- $queury, true, PMA_DatabaseInterface::QUERY_STORE
+ $query, true, PMA_DatabaseInterface::QUERY_STORE
);
}
}
}
- return $res;
+ return (boolean) $res;
}
/**
@@ -452,8 +498,8 @@ function PMA_saveDisplayField($db, $table, $field)
$field = '';
}
- include_once 'libraries/tbl_relation.lib.php';
- PMA_handleUpdateForDisplayField($disp, $field, $db, $table, $cfgRelation);
+ $upd_query = new PMA_Table($table, $db, $GLOBALS['dbi']);
+ $upd_query->updateDisplayField($disp, $field, $cfgRelation);
return true;
}
@@ -654,4 +700,61 @@ function PMA_removeRelation($T1, $F1, $T2, $F2)
return array(true, __('Internal relation has been removed.'));
}
-?>
+
+/**
+ * Save value for a designer setting
+ *
+ * @param string $index setting
+ * @param string $value value
+ *
+ * @return bool whether the operation succeeded
+ */
+function PMA_saveDesignerSetting($index, $value)
+{
+ $cfgRelation = PMA_getRelationsParam();
+ $cfgDesigner = array(
+ 'user' => $GLOBALS['cfg']['Server']['user'],
+ 'db' => $cfgRelation['db'],
+ 'table' => $cfgRelation['designer_settings']
+ );
+
+ $success = true;
+ if ($GLOBALS['cfgRelation']['designersettingswork']) {
+
+ $orig_data_query = "SELECT settings_data"
+ . " FROM " . PMA_Util::backquote($cfgDesigner['db'])
+ . "." . PMA_Util::backquote($cfgDesigner['table'])
+ . " WHERE username = '"
+ . PMA_Util::sqlAddSlashes($cfgDesigner['user']) . "';";
+
+ $orig_data = $GLOBALS['dbi']->fetchSingleRow(
+ $orig_data_query, $GLOBALS['controllink']
+ );
+
+ if (! empty($orig_data)) {
+ $orig_data = json_decode($orig_data['settings_data'], true);
+ $orig_data[$index] = $value;
+ $orig_data = json_encode($orig_data);
+
+ $save_query = "UPDATE " . PMA_Util::backquote($cfgDesigner['db'])
+ . "." . PMA_Util::backquote($cfgDesigner['table'])
+ . " SET settings_data = '" . $orig_data . "'"
+ . " WHERE username = '"
+ . PMA_Util::sqlAddSlashes($cfgDesigner['user']) . "';";
+
+ $success = PMA_queryAsControlUser($save_query);
+ } else {
+ $save_data = array($index => $value);
+
+ $query = "INSERT INTO " . PMA_Util::backquote($cfgDesigner['db'])
+ . "." . PMA_Util::backquote($cfgDesigner['table'])
+ . " (username, settings_data)"
+ . " VALUES('" . $cfgDesigner['user'] . "',"
+ . " '" . json_encode($save_data) . "');";
+
+ $success = PMA_queryAsControlUser($query);
+ }
+ }
+
+ return $success;
+}
diff --git a/libraries/properties/PropertyItem.class.php b/libraries/properties/PropertyItem.class.php
index 83a5b26326..8c6906a24c 100644
--- a/libraries/properties/PropertyItem.class.php
+++ b/libraries/properties/PropertyItem.class.php
@@ -46,4 +46,3 @@ abstract class PropertyItem
return null;
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/OptionsPropertyGroup.class.php b/libraries/properties/options/OptionsPropertyGroup.class.php
index 0e4ed357af..1872c16d43 100644
--- a/libraries/properties/options/OptionsPropertyGroup.class.php
+++ b/libraries/properties/options/OptionsPropertyGroup.class.php
@@ -96,4 +96,3 @@ abstract class OptionsPropertyGroup extends OptionsPropertyItem
return count($this->_properties);
}
}
-?>
diff --git a/libraries/properties/options/OptionsPropertyItem.class.php b/libraries/properties/options/OptionsPropertyItem.class.php
index 0c995148e3..57dba3d546 100644
--- a/libraries/properties/options/OptionsPropertyItem.class.php
+++ b/libraries/properties/options/OptionsPropertyItem.class.php
@@ -124,4 +124,3 @@ abstract class OptionsPropertyItem extends PropertyItem
return "options";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/OptionsPropertyOneItem.class.php b/libraries/properties/options/OptionsPropertyOneItem.class.php
index cb62341821..a22ac8b354 100644
--- a/libraries/properties/options/OptionsPropertyOneItem.class.php
+++ b/libraries/properties/options/OptionsPropertyOneItem.class.php
@@ -169,4 +169,3 @@ abstract class OptionsPropertyOneItem extends OptionsPropertyItem
$this->_size = $size;
}
}
-?>
diff --git a/libraries/properties/options/groups/OptionsPropertyMainGroup.class.php b/libraries/properties/options/groups/OptionsPropertyMainGroup.class.php
index 4e69aa7ac8..6e36ab18c1 100644
--- a/libraries/properties/options/groups/OptionsPropertyMainGroup.class.php
+++ b/libraries/properties/options/groups/OptionsPropertyMainGroup.class.php
@@ -32,4 +32,3 @@ class OptionsPropertyMainGroup extends OptionsPropertyGroup
return "main";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/groups/OptionsPropertyRootGroup.class.php b/libraries/properties/options/groups/OptionsPropertyRootGroup.class.php
index a081744fad..404040537d 100644
--- a/libraries/properties/options/groups/OptionsPropertyRootGroup.class.php
+++ b/libraries/properties/options/groups/OptionsPropertyRootGroup.class.php
@@ -32,4 +32,3 @@ class OptionsPropertyRootGroup extends OptionsPropertyGroup
return "root";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/groups/OptionsPropertySubgroup.class.php b/libraries/properties/options/groups/OptionsPropertySubgroup.class.php
index 0eeb524378..1b08f26deb 100644
--- a/libraries/properties/options/groups/OptionsPropertySubgroup.class.php
+++ b/libraries/properties/options/groups/OptionsPropertySubgroup.class.php
@@ -65,4 +65,3 @@ class OptionsPropertySubgroup extends OptionsPropertyGroup
$this->_subgroupHeader = $subgroupHeader;
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/BoolPropertyItem.class.php b/libraries/properties/options/items/BoolPropertyItem.class.php
index f33067fcd6..f8efab240b 100644
--- a/libraries/properties/options/items/BoolPropertyItem.class.php
+++ b/libraries/properties/options/items/BoolPropertyItem.class.php
@@ -32,4 +32,3 @@ class BoolPropertyItem extends OptionsPropertyOneItem
return "bool";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/DocPropertyItem.class.php b/libraries/properties/options/items/DocPropertyItem.class.php
index 55aff6147b..89678d240c 100644
--- a/libraries/properties/options/items/DocPropertyItem.class.php
+++ b/libraries/properties/options/items/DocPropertyItem.class.php
@@ -32,4 +32,3 @@ class DocPropertyItem extends OptionsPropertyOneItem
return "doc";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/HiddenPropertyItem.class.php b/libraries/properties/options/items/HiddenPropertyItem.class.php
index 53bfe465af..711d45c5da 100644
--- a/libraries/properties/options/items/HiddenPropertyItem.class.php
+++ b/libraries/properties/options/items/HiddenPropertyItem.class.php
@@ -32,4 +32,3 @@ class HiddenPropertyItem extends OptionsPropertyOneItem
return "hidden";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/MessageOnlyPropertyItem.class.php b/libraries/properties/options/items/MessageOnlyPropertyItem.class.php
index 98f2e709fc..aea108055b 100644
--- a/libraries/properties/options/items/MessageOnlyPropertyItem.class.php
+++ b/libraries/properties/options/items/MessageOnlyPropertyItem.class.php
@@ -32,4 +32,3 @@ class MessageOnlyPropertyItem extends OptionsPropertyOneItem
return "messageOnly";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/NumberPropertyItem.class.php b/libraries/properties/options/items/NumberPropertyItem.class.php
index 7c687c756e..a325ec7db0 100644
--- a/libraries/properties/options/items/NumberPropertyItem.class.php
+++ b/libraries/properties/options/items/NumberPropertyItem.class.php
@@ -32,4 +32,3 @@ class NumberPropertyItem extends OptionsPropertyOneItem
return "number";
}
}
-?>
diff --git a/libraries/properties/options/items/RadioPropertyItem.class.php b/libraries/properties/options/items/RadioPropertyItem.class.php
index 4d8ed7a21e..8feb191db5 100644
--- a/libraries/properties/options/items/RadioPropertyItem.class.php
+++ b/libraries/properties/options/items/RadioPropertyItem.class.php
@@ -32,4 +32,3 @@ class RadioPropertyItem extends OptionsPropertyOneItem
return "radio";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/SelectPropertyItem.class.php b/libraries/properties/options/items/SelectPropertyItem.class.php
index 28460c95ab..431b51777b 100644
--- a/libraries/properties/options/items/SelectPropertyItem.class.php
+++ b/libraries/properties/options/items/SelectPropertyItem.class.php
@@ -32,4 +32,3 @@ class SelectPropertyItem extends OptionsPropertyOneItem
return "select";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/options/items/TextPropertyItem.class.php b/libraries/properties/options/items/TextPropertyItem.class.php
index 9339cdf070..fc0ed146b6 100644
--- a/libraries/properties/options/items/TextPropertyItem.class.php
+++ b/libraries/properties/options/items/TextPropertyItem.class.php
@@ -32,4 +32,3 @@ class TextPropertyItem extends OptionsPropertyOneItem
return "text";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/plugins/ExportPluginProperties.class.php b/libraries/properties/plugins/ExportPluginProperties.class.php
index 64ce593c06..b61e584aa3 100644
--- a/libraries/properties/plugins/ExportPluginProperties.class.php
+++ b/libraries/properties/plugins/ExportPluginProperties.class.php
@@ -65,4 +65,3 @@ class ExportPluginProperties extends PluginPropertyItem
$this->_forceFile = $forceFile;
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/plugins/PluginPropertyItem.class.php b/libraries/properties/plugins/PluginPropertyItem.class.php
index 2a8db73d83..3f6a3323f4 100644
--- a/libraries/properties/plugins/PluginPropertyItem.class.php
+++ b/libraries/properties/plugins/PluginPropertyItem.class.php
@@ -180,4 +180,3 @@ abstract class PluginPropertyItem extends PropertyItem
return "plugin";
}
}
-?> \ No newline at end of file
diff --git a/libraries/properties/plugins/SchemaPluginProperties.class.php b/libraries/properties/plugins/SchemaPluginProperties.class.php
index 5eb9a3416b..0dba5b041a 100644
--- a/libraries/properties/plugins/SchemaPluginProperties.class.php
+++ b/libraries/properties/plugins/SchemaPluginProperties.class.php
@@ -44,4 +44,3 @@ class SchemaPluginProperties extends PluginPropertyItem
return true;
}
}
-?> \ No newline at end of file
diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php
index 1e191c321f..338565fe98 100644
--- a/libraries/relation.lib.php
+++ b/libraries/relation.lib.php
@@ -16,7 +16,7 @@ if (! defined('PHPMYADMIN')) {
* @param boolean $show_error whether to display SQL error messages or not
* @param int $options query options
*
- * @return integer the result set, or false if no result set
+ * @return resource|boolean the result set, or false if no result set
*
* @access public
*
@@ -59,7 +59,10 @@ function PMA_queryAsControlUser($sql, $show_error = true, $options = 0)
*/
function PMA_getRelationsParam()
{
- if (empty($_SESSION['relation'][$GLOBALS['server']])) {
+ if (empty($_SESSION['relation'][$GLOBALS['server']])
+ || (empty($_SESSION['relation'][$GLOBALS['server']]['PMA_VERSION']))
+ || $_SESSION['relation'][$GLOBALS['server']]['PMA_VERSION'] != PMA_VERSION
+ ) {
$_SESSION['relation'][$GLOBALS['server']] = PMA_checkRelationsParam();
}
@@ -79,7 +82,7 @@ function PMA_getRelationsParam()
*/
function PMA_getRelationsParamDiagnostic($cfgRelation)
{
- $retval = '';
+ $retval = '<br>';
$messages = array();
$messages['error'] = '<font color="red"><strong>'
@@ -101,8 +104,12 @@ function PMA_getRelationsParamDiagnostic($cfgRelation)
. __('General relation features')
. ' <font color="green">' . __('Disabled')
. '</font>' . "\n";
- if (! empty($GLOBALS['db']) && $GLOBALS['cfg']['ZeroConf']) {
- $retval .= PMA_getHtmlFixPMATables(true);
+ if ($GLOBALS['cfg']['ZeroConf']) {
+ if (empty($GLOBALS['db'])) {
+ $retval .= PMA_getHtmlFixPMATables(true, true);
+ } else {
+ $retval .= PMA_getHtmlFixPMATables(true);
+ }
}
} else {
$retval .= '<table>' . "\n";
@@ -307,7 +314,29 @@ function PMA_getRelationsParamDiagnostic($cfgRelation)
);
$retval .= PMA_getDiagMessageForFeature(
__('Managing Central list of columns'),
- 'central_columnswork',
+ 'centralcolumnswork',
+ $messages
+ );
+ $retval .= PMA_getDiagMessageForParameter(
+ 'designer_settings',
+ isset($cfgRelation['designer_settings']),
+ $messages,
+ 'designer_settings'
+ );
+ $retval .= PMA_getDiagMessageForFeature(
+ __('Remembering Designer Settings'),
+ 'designersettingswork',
+ $messages
+ );
+ $retval .= PMA_getDiagMessageForParameter(
+ 'export_templates',
+ isset($cfgRelation['export_templates']),
+ $messages,
+ 'export_templates'
+ );
+ $retval .= PMA_getDiagMessageForFeature(
+ __('Saving export templates'),
+ 'exporttemplateswork',
$messages
);
$retval .= '</table>' . "\n";
@@ -316,35 +345,30 @@ function PMA_getRelationsParamDiagnostic($cfgRelation)
$retval .= '<p>' . __('Quick steps to setup advanced features:')
. '</p>';
- $retval .= '<ul>';
- $retval .= '<li>';
- $retval .= sprintf(
+
+ $items = array();
+ $items[] = sprintf(
__(
'Create the needed tables with the '
. '<code>%screate_tables.sql</code>.'
),
htmlspecialchars(SQL_DIR)
- );
- $retval .= ' ' . PMA_Util::showDocu('setup', 'linked-tables');
- $retval .= '</li>';
- $retval .= '<li>';
- $retval .= __('Create a pma user and give access to these tables.');
- $retval .= ' ' . PMA_Util::showDocu('config', 'cfg_Servers_controluser');
- $retval .= '</li>';
- $retval .= '<li>';
- $retval .= __(
+ ) . ' ' . PMA_Util::showDocu('setup', 'linked-tables');
+ $items[] = __('Create a pma user and give access to these tables.') . ' '
+ . PMA_Util::showDocu('config', 'cfg_Servers_controluser');
+ $items[] = __(
'Enable advanced features in configuration file '
. '(<code>config.inc.php</code>), for example by '
. 'starting from <code>config.sample.inc.php</code>.'
- );
- $retval .= ' ' . PMA_Util::showDocu('setup', 'quick-install');
- $retval .= '</li>';
- $retval .= '<li>';
- $retval .= __(
+ ) . ' ' . PMA_Util::showDocu('setup', 'quick-install');
+ $items[] = __(
'Re-login to phpMyAdmin to load the updated configuration file.'
);
- $retval .= '</li>';
- $retval .= '</ul>';
+
+ include_once './libraries/Template.class.php';
+ $retval .= PMA\Template::get('list/unordered')->render(
+ array('items' => $items,)
+ );
}
}
@@ -419,6 +443,8 @@ function PMA_getDiagMessageForParameter($parameter,
function PMA_checkRelationsParam()
{
$cfgRelation = array();
+ $cfgRelation['PMA_VERSION'] = PMA_VERSION;
+
$cfgRelation['relwork'] = false;
$cfgRelation['displaywork'] = false;
$cfgRelation['bookmarkwork'] = false;
@@ -435,7 +461,9 @@ function PMA_checkRelationsParam()
$cfgRelation['navwork'] = false;
$cfgRelation['allworks'] = false;
$cfgRelation['savedsearcheswork'] = false;
- $cfgRelation['central_columnswork'] = false;
+ $cfgRelation['centralcolumnswork'] = false;
+ $cfgRelation['designersettingswork'] = false;
+ $cfgRelation['exporttemplateswork'] = false;
$cfgRelation['user'] = null;
$cfgRelation['db'] = null;
@@ -509,6 +537,10 @@ function PMA_checkRelationsParam()
$cfgRelation['savedsearches'] = $curr_table[0];
} elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['central_columns']) {
$cfgRelation['central_columns'] = $curr_table[0];
+ } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['designer_settings']) {
+ $cfgRelation['designer_settings'] = $curr_table[0];
+ } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['export_templates']) {
+ $cfgRelation['export_templates'] = $curr_table[0];
}
} // end while
$GLOBALS['dbi']->freeResult($tab_rs);
@@ -572,7 +604,15 @@ function PMA_checkRelationsParam()
}
if (isset($cfgRelation['central_columns'])) {
- $cfgRelation['central_columnswork'] = true;
+ $cfgRelation['centralcolumnswork'] = true;
+ }
+
+ if (isset($cfgRelation['designer_settings'])) {
+ $cfgRelation['designersettingswork'] = true;
+ }
+
+ if (isset($cfgRelation['export_templates'])) {
+ $cfgRelation['exporttemplateswork'] = true;
}
if ($cfgRelation['relwork'] && $cfgRelation['displaywork']
@@ -580,9 +620,11 @@ function PMA_checkRelationsParam()
&& $cfgRelation['mimework'] && $cfgRelation['historywork']
&& $cfgRelation['recentwork'] && $cfgRelation['uiprefswork']
&& $cfgRelation['trackingwork'] && $cfgRelation['userconfigwork']
- && $cfgRelation['bookmarkwork'] && $cfgRelation['central_columnswork']
+ && $cfgRelation['bookmarkwork'] && $cfgRelation['centralcolumnswork']
&& $cfgRelation['menuswork'] && $cfgRelation['navwork']
&& $cfgRelation['savedsearcheswork'] && $cfgRelation['favoritework']
+ && $cfgRelation['designersettingswork']
+ && $cfgRelation['exporttemplateswork']
) {
$cfgRelation['allworks'] = true;
}
@@ -692,15 +734,17 @@ function PMA_getForeigners($db, $table, $column = '', $source = 'both')
if (($source == 'both' || $source == 'foreign') && /*overload*/mb_strlen($table)
) {
-
- $showCreateTableQuery = 'SHOW CREATE TABLE '
- . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table);
- $show_create_table = $GLOBALS['dbi']->fetchValue(
- $showCreateTableQuery, 0, 1
- );
+ $tableObj = new PMA_Table($table, $db);
+ $show_create_table = $tableObj->showCreate();
if ($show_create_table) {
- $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table));
- $foreign['foreign_keys_data'] = $analyzed_sql[0]['foreign_keys'];
+ $parser = new SqlParser\Parser($show_create_table);
+ /**
+ * @var CreateStatement $stmt
+ */
+ $stmt = $parser->statements[0];
+ $foreign['foreign_keys_data'] = SqlParser\Utils\Table::getForeignKeys(
+ $stmt
+ );
}
}
@@ -1255,7 +1299,6 @@ function PMA_foreignDropdown($disp_row, $foreign_field, $foreign_display, $data,
*
* @access public
*/
-
function PMA_getForeignData(
$foreigners, $field, $override_total, $foreign_filter, $foreign_limit
) {
@@ -1283,7 +1326,8 @@ function PMA_getForeignData(
// We could also do the SELECT anyway, with a LIMIT, and ensure that
// the current value of the field is one of the choices.
- $the_total = PMA_Table::countRecords($foreign_db, $foreign_table, true);
+ $the_total = $GLOBALS['dbi']->getTable($foreign_db, $foreign_table)
+ ->countRecords(true);
if ($override_total == true
|| $the_total < $GLOBALS['cfg']['ForeignKeyMaxLimit']
@@ -1362,130 +1406,6 @@ function PMA_getForeignData(
} // end of 'PMA_getForeignData()' function
/**
- * Finds all related tables
- *
- * @param array $all_tables All the involved tables
- * @param string $master The master table to form the LEFT JOIN clause
- *
- * @return string LEFT JOIN
- * @access private
- */
-function PMA_getRelatives($all_tables, $master)
-{
- $fromclause = '';
- $left_joins = array();
- $emerg = '';
- $ignore_internal_relations = false;
-
- // The list of tables that we still couldn't connect
- $remaining_tables = $all_tables;
- unset($remaining_tables[$master]);
- // The list of already connected tables
- $known_tables = array();
- $known_tables[$master] = $master;
- $run = 0;
- while ($GLOBALS['cfgRelation']['relwork'] && count($remaining_tables) > 0) {
- // Whether to go from master to foreign or vice versa
- if ($run % 2 == 0) {
- $from = 'master';
- $to = 'foreign';
- } else {
- $from = 'foreign';
- $to = 'master';
- }
- $in_know = '(\'' . implode('\', \'', $known_tables) . '\')';
- $in_left = '(\'' . implode('\', \'', $remaining_tables) . '\')';
- $rel_query = 'SELECT *'
- . ' FROM ' . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($GLOBALS['cfgRelation']['relation'])
- . ' WHERE ' . $from . '_db = \''
- . PMA_Util::sqlAddSlashes($GLOBALS['db']) . '\''
- . ' AND ' . $to . '_db = \''
- . PMA_Util::sqlAddSlashes($GLOBALS['db']) . '\''
- . ' AND ' . $from . '_table IN ' . $in_know
- . ' AND ' . $to . '_table IN ' . $in_left;
- $relations = @$GLOBALS['dbi']->query($rel_query, $GLOBALS['controllink']);
- while ($row = $GLOBALS['dbi']->fetchAssoc($relations)) {
- $found_table = $row[$to . '_table'];
- if (isset($remaining_tables[$found_table])) {
- $left_join_with = PMA_Util::backquote($GLOBALS['db']) . '.'
- . PMA_Util::backquote($row[$to . '_table']);
- $on_condition = PMA_Util::backquote($row[$from . '_table']) . '.'
- . PMA_Util::backquote($row[$from . '_field']) . ' = '
- . PMA_Util::backquote($row[$to . '_table']) . '.'
- . PMA_Util::backquote($row[$to . '_field']);
-
- $left_joins[$left_join_with] = array(
- 'left_join_with' => $left_join_with,
- 'on_condition' => array($on_condition)
- );
-
- $known_tables[$found_table] = $found_table;
- unset($remaining_tables[$found_table]);
- }
- } // end while
- $run++;
- if ($run > 5) {
- foreach ($remaining_tables as $table) {
- $emerg .= ', ' . PMA_Util::backquote($table);
- unset($remaining_tables[$table]);
- }
- }
- } // end while
-
- // Generate 'LEFT JOIN's for InnoDB foreign keys.
- $remaining_tables = $all_tables;
- foreach ($remaining_tables as $one_table) {
- $foreigners = PMA_getForeigners($GLOBALS['db'], $one_table, '', 'foreign');
- foreach ($foreigners['foreign_keys_data'] as $one_key) {
- if (in_array($one_key['ref_table_name'], $all_tables)
- && ! isset($one_key['ref_db_name'])
- && ($one_key['ref_table_name'] == $master
- || $one_key['ref_table_name'] == $one_table)
- ) {
- $left_join_with = PMA_Util::backquote($GLOBALS['db']) . '.'
- . PMA_Util::backquote($one_table);
- if (! isset($left_joins[$left_join_with])) {
- $left_joins[$left_join_with] = array(
- 'left_join_with' =>$left_join_with,
- 'on_condition' => array()
- );
- }
-
- foreach ($one_key['ref_index_list'] as $key => $one_column) {
- $on_condition = PMA_Util::backquote($one_key['ref_table_name'])
- . '.' . PMA_Util::backquote($one_column) . ' = '
- . PMA_Util::backquote($one_table) . '.'
- . PMA_Util::backquote($one_key['index_list'][$key]);
-
- if (! in_array($on_condition, $left_joins[$left_join_with]['on_condition'])) {
- $left_joins[$left_join_with]['on_condition'][]
- = $on_condition;
- }
- }
- $ignore_internal_relations = true;
- unset($remaining_tables[$one_table]);
- }
- }
- }
-
- if ($ignore_internal_relations) {
- $emerg = '';
- }
-
- // Build the 'FROM' clause.
- foreach ($left_joins as $one_join) {
- $fromclause .= "\n" . ' LEFT JOIN '
- . $one_join['left_join_with']
- . ' ON '
- . implode(' AND ', $one_join['on_condition']);
- }
-
- $fromclause = $emerg . $fromclause;
- return $fromclause;
-} // end of the "PMA_getRelatives()" function
-
-/**
* Rename a field in relation tables
*
* usually called after a column in a table was renamed
@@ -1780,7 +1700,7 @@ function PMA_checkChildForeignReferences(
) {
if (sizeof($child_references, 0) > 0) {
$column_status['isReferenced'] = true;
- foreach ($child_references as $row => $columns) {
+ foreach ($child_references as $columns) {
array_push(
$column_status['references'],
PMA_Util::backquote($columns['table_schema'])
@@ -1813,7 +1733,7 @@ function PMA_searchColumnInForeigners($foreigners, $column)
return $foreigners[$column];
} else {
$foreigner = array();
- foreach ($foreigners['foreign_keys_data'] as $key => $one_key) {
+ foreach ($foreigners['foreign_keys_data'] as $one_key) {
$column_index = array_search($column, $one_key['index_list']);
if ($column_index !== false) {
$foreigner['foreign_field']
@@ -1873,6 +1793,29 @@ function PMA_getDefaultPMATableNames()
}
/**
+ * Create a table named phpmyadmin to be used as configuration storage
+ *
+ * @return bool
+ */
+function PMA_createPMADatabase()
+{
+ $GLOBALS['dbi']->tryQuery("CREATE DATABASE IF NOT EXISTS `phpmyadmin`");
+ if ($error = $GLOBALS['dbi']->getError()) {
+ if ($GLOBALS['errno'] == 1044) {
+ $GLOBALS['message'] = __(
+ 'You do not have necessary privileges to create a database named'
+ . ' \'phpmyadmin\'. You may go to \'Operations\' tab of any'
+ . ' database to set up the phpMyAdmin configuration storage there.'
+ );
+ } else {
+ $GLOBALS['message'] = $error;
+ }
+ return false;
+ }
+ return true;
+}
+
+/**
* Creates PMA tables in the given db, updates if already exists.
*
* @param string $db database
@@ -1899,7 +1842,9 @@ function PMA_fixPMATables($db, $create = true)
'pma__usergroups' => 'usergroups',
'pma__navigationhiding' => 'navigationhiding',
'pma__savedsearches' => 'savedsearches',
- 'pma__central_columns' => 'central_columns'
+ 'pma__central_columns' => 'central_columns',
+ 'pma__designer_settings' => 'designer_settings',
+ 'pma__export_templates' => 'export_templates',
);
$existingTables = $GLOBALS['dbi']->getTables($db, $GLOBALS['controllink']);
@@ -1918,6 +1863,7 @@ function PMA_fixPMATables($db, $create = true)
$GLOBALS['message'] = $error;
return;
}
+ $foundOne = true;
$GLOBALS['cfg']['Server'][$feature] = $table;
}
} else {
@@ -1960,22 +1906,33 @@ function PMA_fixPMATables($db, $create = true)
* Get Html for PMA tables fixing anchor.
*
* @param boolean $allTables whether to create all tables
+ * @param boolean $createDb whether to create the pmadb also
*
* @return string Html
*/
-function PMA_getHtmlFixPMATables($allTables)
+function PMA_getHtmlFixPMATables($allTables, $createDb = false)
{
$retval = '';
$url_query = PMA_URL_getCommon(array('db' => $GLOBALS['db']));
if ($allTables) {
- $url_query .= '&amp;goto=db_operations.php&amp;create_pmadb=1';
- $message = PMA_Message::notice(
- __(
- '%sCreate%s the phpMyAdmin configuration storage in the '
- . 'current database.'
- )
- );
+ if ($createDb) {
+ $url_query .= '&amp;goto=db_operations.php&amp;create_pmadb=1';
+ $message = PMA_Message::notice(
+ __(
+ '%sCreate%s a database named \'phpmyadmin\' and setup '
+ . 'the phpMyAdmin configuration storage there.'
+ )
+ );
+ } else {
+ $url_query .= '&amp;goto=db_operations.php&amp;fixall_pmadb=1';
+ $message = PMA_Message::notice(
+ __(
+ '%sCreate%s the phpMyAdmin configuration storage in the '
+ . 'current database.'
+ )
+ );
+ }
} else {
$url_query .= '&amp;goto=db_operations.php&amp;fix_pmadb=1';
$message = PMA_Message::notice(
@@ -2021,4 +1978,3 @@ function PMA_getRelationsAndStatus($condition, $db, $table)
} // end if
return(array($res_rel, $have_rel));
}
-?>
diff --git a/libraries/relation_cleanup.lib.php b/libraries/relation_cleanup.lib.php
index d76774936b..3fa094d787 100644
--- a/libraries/relation_cleanup.lib.php
+++ b/libraries/relation_cleanup.lib.php
@@ -203,9 +203,7 @@ function PMA_relationsCleanupDatabase($db)
PMA_queryAsControlUser($remove_query);
}
- if (isset($cfgRelation['central_columnswork'])
- && $cfgRelation['central_columnswork']
- ) {
+ if ($cfgRelation['centralcolumnswork']) {
$remove_query = 'DELETE FROM ' . PMA_Util::backquote($cfgRelation['db'])
. '.' . PMA_Util::backquote($cfgRelation['central_columns'])
. ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($db) . '\'';
@@ -213,4 +211,85 @@ function PMA_relationsCleanupDatabase($db)
}
}
-?>
+/**
+ * Cleanup user related relation stuff
+ *
+ * @param string $username username
+ *
+ * @return void
+ */
+function PMA_relationsCleanupUser($username)
+{
+ $cfgRelation = PMA_getRelationsParam();
+
+ if ($cfgRelation['bookmarkwork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['bookmark'])
+ . " WHERE `user` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['historywork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['history'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['recentwork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['recent'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['favoritework']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['favorite'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['uiprefswork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['table_uiprefs'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['userconfigwork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['userconfig'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['menuswork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['users'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['navwork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['navigationhiding'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['savedsearcheswork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['savedsearches'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+
+ if ($cfgRelation['designersettingswork']) {
+ $remove_query = "DELETE FROM " . PMA_Util::backquote($cfgRelation['db'])
+ . "." . PMA_Util::backquote($cfgRelation['designer_settings'])
+ . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
+ PMA_queryAsControlUser($remove_query);
+ }
+}
+
diff --git a/libraries/replication.inc.php b/libraries/replication.inc.php
index eec2fd379d..2e0ecd71f0 100644
--- a/libraries/replication.inc.php
+++ b/libraries/replication.inc.php
@@ -16,22 +16,23 @@ if (! defined('PHPMYADMIN')) {
$server_master_replication = $GLOBALS['dbi']->fetchResult('SHOW MASTER STATUS');
/**
- * check for multi-master replication functionality
- */
-$server_slave_multi_replication = $GLOBALS['dbi']->fetchResult(
- 'SHOW ALL SLAVES STATUS'
-);
-
-/**
* set selected master server
*/
-if ($server_slave_multi_replication && !empty($_REQUEST['master_connection'])) {
- $GLOBALS['dbi']->query(
- "SET @@default_master_connection = '" . PMA_Util::sqlAddSlashes(
- $_REQUEST['master_connection']
- ) . "'"
+if (! empty($_REQUEST['master_connection'])) {
+ /**
+ * check for multi-master replication functionality
+ */
+ $server_slave_multi_replication = $GLOBALS['dbi']->fetchResult(
+ 'SHOW ALL SLAVES STATUS'
);
- $GLOBALS['url_params']['master_connection'] = $_REQUEST['master_connection'];
+ if ($server_slave_multi_replication) {
+ $GLOBALS['dbi']->query(
+ "SET @@default_master_connection = '" . PMA_Util::sqlAddSlashes(
+ $_REQUEST['master_connection']
+ ) . "'"
+ );
+ $GLOBALS['url_params']['master_connection'] = $_REQUEST['master_connection'];
+ }
}
/**
@@ -318,4 +319,3 @@ function PMA_Replication_Slave_binLogMaster($link = null)
}
return $output;
}
-?>
diff --git a/libraries/replication_gui.lib.php b/libraries/replication_gui.lib.php
index a7acd035ea..27059cfc45 100644
--- a/libraries/replication_gui.lib.php
+++ b/libraries/replication_gui.lib.php
@@ -46,12 +46,12 @@ function PMA_getHtmlForMasterReplication()
$html .= '<legend>' . __('Master replication') . '</legend>';
$html .= __('This server is configured as master in a replication process.');
$html .= '<ul>';
- $html .= ' <li><a href="#" id="master_status_href">';
+ $html .= ' <li><a href="#master_status_href" id="master_status_href">';
$html .= __('Show master status') . '</a>';
$html .= PMA_getHtmlForReplicationStatusTable('master', true, false);
$html .= ' </li>';
- $html .= ' <li><a href="#" id="master_slaves_href">';
+ $html .= ' <li><a href="#master_slaves_href" id="master_slaves_href">';
$html .= __('Show connected slaves') . '</a>';
$html .= PMA_getHtmlForReplicationSlavesTable(true);
$html .= ' </li>';
@@ -87,12 +87,12 @@ function PMA_getHtmlForMasterConfiguration()
$html = '<fieldset>';
$html .= '<legend>' . __('Master configuration') . '</legend>';
$html .= __(
- 'This server is not configured as master server in a '
+ 'This server is not configured as a master server in a '
. 'replication process. You can choose from either replicating '
- . 'all databases and ignoring certain (useful if you want to replicate '
- . 'majority of databases) or you can choose to ignore all databases by '
- . 'default and allow only certain databases to be replicated. '
- . 'Please select the mode:'
+ . 'all databases and ignoring some of them (useful if you want to '
+ . 'replicate a majority of the databases) or you can choose to ignore '
+ . 'all databases by default and allow only certain databases to be '
+ . 'replicated. Please select the mode:'
) . '<br /><br />';
$html .= '<select name="db_type" id="db_type">';
@@ -139,15 +139,22 @@ function PMA_getHtmlForSlaveConfiguration(
) {
$html = '<fieldset>';
$html .= '<legend>' . __('Slave replication') . '</legend>';
- if ($GLOBALS['server_slave_multi_replication']) {
+ /**
+ * check for multi-master replication functionality
+ */
+ $server_slave_multi_replication = $GLOBALS['dbi']->fetchResult(
+ 'SHOW ALL SLAVES STATUS'
+ );
+ if ($server_slave_multi_replication) {
$html .= __('Master connection:');
$html .= '<form method="get" action="server_replication.php">';
$html .= PMA_URL_getHiddenInputs($GLOBALS['url_params']);
$html .= ' <select name="master_connection">';
$html .= '<option value="">' . __('Default') . '</option>';
- foreach ($GLOBALS['server_slave_multi_replication'] as $server) {
- $html .= '<option' . (isset($_REQUEST['master_connection']) && $_REQUEST['master_connection'] == $server['Connection_name'] ?
- ' selected="selected"' : '') . '>' . $server['Connection_name']
+ foreach ($server_slave_multi_replication as $server) {
+ $html .= '<option' . (isset($_REQUEST['master_connection'])
+ && $_REQUEST['master_connection'] == $server['Connection_name'] ?
+ ' selected="selected"' : '') . '>' . $server['Connection_name']
. '</option>';
}
$html .= '</select>';
@@ -222,15 +229,18 @@ function PMA_getHtmlForSlaveConfiguration(
$reconfiguremaster_link = 'server_replication.php'
. PMA_URL_getCommon($_url_params);
- $html .= __('Server is configured as slave in a replication process. Would you like to:');
+ $html .= __(
+ 'Server is configured as slave in a replication process. Would you ' .
+ 'like to:'
+ );
$html .= '<br />';
$html .= '<ul>';
- $html .= ' <li><a href="#" id="slave_status_href">';
+ $html .= ' <li><a href="#slave_status_href" id="slave_status_href">';
$html .= __('See slave status table') . '</a>';
$html .= PMA_getHtmlForReplicationStatusTable('slave', true, false);
$html .= ' </li>';
- $html .= ' <li><a href="#" id="slave_control_href">';
+ $html .= ' <li><a href="#slave_control_href" id="slave_control_href">';
$html .= __('Control slave:') . '</a>';
$html .= ' <div id="slave_control_gui" style="display: none">';
$html .= ' <ul>';
@@ -293,7 +303,8 @@ function PMA_getHtmlForSlaveConfiguration(
*/
function PMA_getHtmlForSlaveErrorManagement($slave_skip_error_link)
{
- $html = '<a href="#" id="slave_errormanagement_href">';
+ $html = '<a href="#slave_errormanagement_href" '
+ . 'id="slave_errormanagement_href">';
$html .= __('Error management:') . '</a>';
$html .= ' <div id="slave_errormanagement_gui" style="display: none">';
$html .= PMA_Message::error(
@@ -363,9 +374,10 @@ function PMA_getHtmlForReplicationDbMultibox()
$multi_values .= $current_db . '</option>';
} // end while
- $multi_values .= '</select>';
- $multi_values .= '<br /><a href="#" id="db_reset_href">';
- $multi_values .= __('Uncheck All') . '</a>';
+ $multi_values .= '</select><br />';
+ $multi_values .= '<a href="#" id="db_select_href">' . __('Select all') . '</a>';
+ $multi_values .= '&nbsp;/&nbsp;';
+ $multi_values .= '<a href="#" id="db_reset_href">' . __('Unselect all') . '</a>';
return $multi_values;
}
@@ -377,7 +389,6 @@ function PMA_getHtmlForReplicationDbMultibox()
*
* @return String HTML code
*/
-
function PMA_getHtmlForReplicationChangeMaster($submitname)
{
$html = '';
@@ -641,7 +652,6 @@ function PMA_getHtmlForReplicationSlavesTable($hidden = false)
*
* @return array username length, hostname length
*/
-
function PMA_replicationGetUsernameHostnameLength()
{
$fields_info = $GLOBALS['dbi']->getColumns('mysql', 'user');
@@ -882,7 +892,7 @@ function PMA_getHtmlForTableInfoForm($hostname_length)
. '</div>'
. '<div class="item">'
. '<label for="button_generate_password">'
- . ' ' . __('Generate Password:')
+ . ' ' . __('Generate password:')
. '</label>'
. '<span class="options">'
. ' <input type="button" class="button" '
@@ -1085,4 +1095,3 @@ function PMA_handleRequestForSlaveSkipError()
return $result;
}
-?>
diff --git a/libraries/rte/rte_events.lib.php b/libraries/rte/rte_events.lib.php
index 0bb2b42255..f7175bfdcb 100644
--- a/libraries/rte/rte_events.lib.php
+++ b/libraries/rte/rte_events.lib.php
@@ -63,12 +63,7 @@ function PMA_EVN_main()
/**
* Display a list of available events
*/
- $columns = "`EVENT_NAME`, `EVENT_TYPE`, `STATUS`";
- $where = "EVENT_SCHEMA " . PMA_Util::getCollateForIS() . "="
- . "'" . PMA_Util::sqlAddSlashes($db) . "'";
- $query = "SELECT $columns FROM `INFORMATION_SCHEMA`.`EVENTS` "
- . "WHERE $where ORDER BY `EVENT_NAME` ASC;";
- $items = $GLOBALS['dbi']->fetchResult($query);
+ $items = $GLOBALS['dbi']->getEvents($db);
echo PMA_RTE_getList('event', $items);
/**
* Display a link for adding a new event, if
@@ -184,14 +179,8 @@ function PMA_EVN_handleEditor()
if ($GLOBALS['is_ajax_request']) {
$response = PMA_Response::getInstance();
if ($message->isSuccess()) {
- $columns = "`EVENT_NAME`, `EVENT_TYPE`, `STATUS`";
- $where = "EVENT_SCHEMA " . PMA_Util::getCollateForIS() . "="
- . "'" . PMA_Util::sqlAddSlashes($db) . "' "
- . "AND EVENT_NAME='"
- . PMA_Util::sqlAddSlashes($_REQUEST['item_name']) . "'";
- $query = "SELECT " . $columns
- . " FROM `INFORMATION_SCHEMA`.`EVENTS` WHERE " . $where . ";";
- $event = $GLOBALS['dbi']->fetchSingleRow($query);
+ $events = $GLOBALS['dbi']->getEvents($db, $_REQUEST['item_name']);
+ $event = $events[0];
$response->addJSON(
'name',
htmlspecialchars(
@@ -431,8 +420,8 @@ function PMA_EVN_getEditorForm($mode, $operation, $item)
} else {
$retval .= " <input name='item_type' type='hidden' \n";
$retval .= " value='{$item['item_type']}' />\n";
- $retval .= " <div style='width: 49%; float: left; text-align: center;"
- . " font-weight: bold;'>\n";
+ $retval .= " <div class='floatleft' style='width: 49%; "
+ . "text-align: center; font-weight: bold;'>\n";
$retval .= " {$item['item_type']}\n";
$retval .= " </div>\n";
$retval .= " <input style='width: 49%;' type='submit'\n";
@@ -615,4 +604,3 @@ function PMA_EVN_getQueryFromRequest()
return $query;
} // end PMA_EVN_getQueryFromRequest()
-?>
diff --git a/libraries/rte/rte_export.lib.php b/libraries/rte/rte_export.lib.php
index 8b8467ccdb..5d4389e830 100644
--- a/libraries/rte/rte_export.lib.php
+++ b/libraries/rte/rte_export.lib.php
@@ -23,8 +23,7 @@ function PMA_RTE_handleExport($export_data)
$item_name = htmlspecialchars(PMA_Util::backquote($_GET['item_name']));
if ($export_data !== false) {
- $export_data = '<textarea cols="40" rows="15" style="width: 100%;">'
- . htmlspecialchars(trim($export_data)) . '</textarea>';
+ $export_data = htmlspecialchars(trim($export_data));
$title = sprintf(PMA_RTE_getWord('export'), $item_name);
if ($GLOBALS['is_ajax_request'] == true) {
$response = PMA_Response::getInstance();
@@ -32,6 +31,8 @@ function PMA_RTE_handleExport($export_data)
$response->addJSON('title', $title);
exit;
} else {
+ $export_data = '<textarea cols="40" rows="15" style="width: 100%;">'
+ . $export_data . '</textarea>';
echo "<fieldset>\n"
. "<legend>$title</legend>\n"
. $export_data
@@ -80,7 +81,7 @@ function PMA_RTN_handleExport()
{
global $_GET, $db;
- if ( ! empty($_GET['export_item'])
+ if (! empty($_GET['export_item'])
&& ! empty($_GET['item_name'])
&& ! empty($_GET['item_type'])
) {
@@ -118,4 +119,3 @@ function PMA_TRI_handleExport()
PMA_RTE_handleExport($export_data);
}
} // end PMA_TRI_handleExport()
-?>
diff --git a/libraries/rte/rte_footer.lib.php b/libraries/rte/rte_footer.lib.php
index 1bdd3e921f..b88800d190 100644
--- a/libraries/rte/rte_footer.lib.php
+++ b/libraries/rte/rte_footer.lib.php
@@ -127,4 +127,3 @@ function PMA_EVN_getFooterLinks()
return $retval;
} // end PMA_EVN_getFooterLinks()
-?>
diff --git a/libraries/rte/rte_list.lib.php b/libraries/rte/rte_list.lib.php
index 7b7ab3d4e5..6e2e68ad6c 100644
--- a/libraries/rte/rte_list.lib.php
+++ b/libraries/rte/rte_list.lib.php
@@ -35,6 +35,26 @@ function PMA_RTE_getList($type, $items)
* Generate output
*/
$retval = "<!-- LIST OF " . PMA_RTE_getWord('docu') . " START -->\n";
+ $retval .= '<form id="rteListForm" class="ajax" action="';
+ switch ($type) {
+ case 'routine':
+ $retval .= 'db_routines.php';
+ break;
+ case 'trigger':
+ if (! empty($table)) {
+ $retval .= 'tbl_triggers.php';
+ } else {
+ $retval .= 'db_triggers.php';
+ }
+ break;
+ case 'event':
+ $retval .= 'db_events.php';
+ break;
+ default:
+ break;
+ }
+ $retval .= '">';
+ $retval .= PMA_URL_getHiddenInputs($GLOBALS['db'], $GLOBALS['table']);
$retval .= "<fieldset>\n";
$retval .= " <legend>\n";
$retval .= " " . PMA_RTE_getWord('title') . "\n";
@@ -49,6 +69,7 @@ function PMA_RTE_getList($type, $items)
// th cells with a colspan need corresponding td cells, according to W3C
switch ($type) {
case 'routine':
+ $retval .= " <th></th>\n";
$retval .= " <th>" . __('Name') . "</th>\n";
$retval .= " <th colspan='4'>" . __('Action') . "</th>\n";
$retval .= " <th>" . __('Type') . "</th>\n";
@@ -60,6 +81,7 @@ function PMA_RTE_getList($type, $items)
}
break;
case 'trigger':
+ $retval .= " <th></th>\n";
$retval .= " <th>" . __('Name') . "</th>\n";
if (empty($table)) {
$retval .= " <th>" . __('Table') . "</th>\n";
@@ -74,6 +96,7 @@ function PMA_RTE_getList($type, $items)
}
break;
case 'event':
+ $retval .= " <th></th>\n";
$retval .= " <th>" . __('Name') . "</th>\n";
$retval .= " <th>" . __('Status') . "</th>\n";
$retval .= " <th colspan='3'>" . __('Action') . "</th>\n";
@@ -112,7 +135,25 @@ function PMA_RTE_getList($type, $items)
$count++;
}
$retval .= " </table>\n";
+
+ if (count($items)) {
+ $retval .= '<div class="withSelected">';
+ $retval .= PMA_Util::getWithSelected(
+ $GLOBALS['pmaThemeImage'], $GLOBALS['text_dir'], 'rteListForm'
+ );
+ $retval .= PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_export',
+ __('Export'), 'b_export.png', 'export'
+ );
+ $retval .= PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_drop',
+ __('Drop'), 'b_drop.png', 'drop'
+ );
+ $retval .= '</div>';
+ }
+
$retval .= "</fieldset>\n";
+ $retval .= "</form>\n";
$retval .= "<!-- LIST OF " . PMA_RTE_getWord('docu') . " END -->\n";
return $retval;
@@ -132,32 +173,35 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
$sql_drop = sprintf(
'DROP %s IF EXISTS %s',
- $routine['ROUTINE_TYPE'],
- PMA_Util::backquote($routine['SPECIFIC_NAME'])
+ $routine['type'],
+ PMA_Util::backquote($routine['name'])
);
- $type_link = "item_type={$routine['ROUTINE_TYPE']}";
+ $type_link = "item_type={$routine['type']}";
- $retval = " <tr class='noclick $rowclass'>\n";
+ $retval = " <tr class='$rowclass'>\n";
+ $retval .= " <td>\n";
+ $retval .= ' <input type="checkbox"'
+ . ' class="checkall" name="item_name[]"'
+ . ' value="' . htmlspecialchars($routine['name']) . '" />';
+ $retval .= " </td>\n";
$retval .= " <td>\n";
$retval .= " <span class='drop_sql hide'>"
. htmlspecialchars($sql_drop) . "</span>\n";
$retval .= " <strong>\n";
$retval .= " "
- . htmlspecialchars($routine['SPECIFIC_NAME']) . "\n";
+ . htmlspecialchars($routine['name']) . "\n";
$retval .= " </strong>\n";
$retval .= " </td>\n";
$retval .= " <td>\n";
// Since editing a procedure involved dropping and recreating, check also for
// CREATE ROUTINE privilege to avoid lost procedures.
- if ($routine['ROUTINE_DEFINITION'] !== null
- && PMA_Util::currentUserHasPrivilege('CREATE ROUTINE', $db)
- ) {
+ if (PMA_Util::currentUserHasPrivilege('CREATE ROUTINE', $db)) {
$retval .= ' <a ' . $ajax_class['edit']
. ' href="db_routines.php'
. $url_query
. '&amp;edit_item=1'
. '&amp;item_name='
- . urlencode($routine['SPECIFIC_NAME'])
+ . urlencode($routine['name'])
. '&amp;' . $type_link
. '">' . $titles['Edit'] . "</a>\n";
} else {
@@ -173,20 +217,30 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
// Also, information_schema might be hiding the ROUTINE_DEFINITION
// but a routine with no input parameters can be nonetheless executed.
- // Check if he routine has any input parameters. If it does,
+ // Check if the routine has any input parameters. If it does,
// we will show a dialog to get values for these parameters,
// otherwise we can execute it directly.
- $routine_details = PMA_RTN_getDataFromName(
- $routine['SPECIFIC_NAME'],
- $routine['ROUTINE_TYPE'],
- false
+
+ $parser = new SqlParser\Parser(
+ $GLOBALS['dbi']->getDefinition(
+ $db,
+ $routine['type'],
+ $routine['name']
+ )
);
+
+ /**
+ * @var CreateStatement $stmt
+ */
+ $stmt = $parser->statements[0];
+
+ $params = SqlParser\Utils\Routine::getParameters($stmt);
if ($routine !== false) {
if (PMA_Util::currentUserHasPrivilege('EXECUTE', $db)) {
$execute_action = 'execute_routine';
- for ($i=0; $i<$routine_details['item_num_params']; $i++) {
- if ($routine_details['item_type'] == 'PROCEDURE'
- && $routine_details['item_param_dir'][$i] == 'OUT'
+ for ($i = 0; $i < $params['num']; $i++) {
+ if ($routine['type'] == 'PROCEDURE'
+ && $params['dir'][$i] == 'OUT'
) {
continue;
}
@@ -198,7 +252,7 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
. $url_query
. '&amp;' . $execute_action . '=1'
. '&amp;item_name='
- . urlencode($routine['SPECIFIC_NAME'])
+ . urlencode($routine['name'])
. '&amp;' . $type_link
. '">' . $titles['Execute'] . "</a>\n";
} else {
@@ -213,7 +267,7 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
. $url_query
. '&amp;export_item=1'
. '&amp;item_name='
- . urlencode($routine['SPECIFIC_NAME'])
+ . urlencode($routine['name'])
. '&amp;' . $type_link
. '">' . $titles['Export'] . "</a>\n";
$retval .= " </td>\n";
@@ -227,11 +281,11 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
. '" >' . $titles['Drop'] . "</a>\n";
$retval .= " </td>\n";
$retval .= " <td>\n";
- $retval .= " {$routine['ROUTINE_TYPE']}\n";
+ $retval .= " {$routine['type']}\n";
$retval .= " </td>\n";
- $retval .= " <td>\n";
+ $retval .= " <td dir=\"ltr\">\n";
$retval .= " "
- . htmlspecialchars($routine['DTD_IDENTIFIER']) . "\n";
+ . htmlspecialchars($routine['returns']) . "\n";
$retval .= " </td>\n";
$retval .= " </tr>\n";
@@ -250,7 +304,12 @@ function PMA_TRI_getRowForList($trigger, $rowclass = '')
{
global $ajax_class, $url_query, $db, $table, $titles;
- $retval = " <tr class='noclick $rowclass'>\n";
+ $retval = " <tr class='$rowclass'>\n";
+ $retval .= " <td>\n";
+ $retval .= ' <input type="checkbox"'
+ . ' class="checkall" name="item_name[]"'
+ . ' value="' . htmlspecialchars($trigger['name']) . '" />';
+ $retval .= " </td>\n";
$retval .= " <td>\n";
$retval .= " <span class='drop_sql hide'>"
. htmlspecialchars($trigger['drop']) . "</span>\n";
@@ -326,20 +385,25 @@ function PMA_EVN_getRowForList($event, $rowclass = '')
$sql_drop = sprintf(
'DROP EVENT IF EXISTS %s',
- PMA_Util::backquote($event['EVENT_NAME'])
+ PMA_Util::backquote($event['name'])
);
- $retval = " <tr class='noclick $rowclass'>\n";
+ $retval = " <tr class='$rowclass'>\n";
+ $retval .= " <td>\n";
+ $retval .= ' <input type="checkbox"'
+ . ' class="checkall" name="item_name[]"'
+ . ' value="' . htmlspecialchars($event['name']) . '" />';
+ $retval .= " </td>\n";
$retval .= " <td>\n";
$retval .= " <span class='drop_sql hide'>"
. htmlspecialchars($sql_drop) . "</span>\n";
$retval .= " <strong>\n";
$retval .= " "
- . htmlspecialchars($event['EVENT_NAME']) . "\n";
+ . htmlspecialchars($event['name']) . "\n";
$retval .= " </strong>\n";
$retval .= " </td>\n";
$retval .= " <td>\n";
- $retval .= " {$event['STATUS']}\n";
+ $retval .= " {$event['status']}\n";
$retval .= " </td>\n";
$retval .= " <td>\n";
if (PMA_Util::currentUserHasPrivilege('EVENT', $db)) {
@@ -348,7 +412,7 @@ function PMA_EVN_getRowForList($event, $rowclass = '')
. $url_query
. '&amp;edit_item=1'
. '&amp;item_name='
- . urlencode($event['EVENT_NAME'])
+ . urlencode($event['name'])
. '">' . $titles['Edit'] . "</a>\n";
} else {
$retval .= " {$titles['NoEdit']}\n";
@@ -360,7 +424,7 @@ function PMA_EVN_getRowForList($event, $rowclass = '')
. $url_query
. '&amp;export_item=1'
. '&amp;item_name='
- . urlencode($event['EVENT_NAME'])
+ . urlencode($event['name'])
. '">' . $titles['Export'] . "</a>\n";
$retval .= " </td>\n";
$retval .= " <td>\n";
@@ -377,11 +441,10 @@ function PMA_EVN_getRowForList($event, $rowclass = '')
}
$retval .= " </td>\n";
$retval .= " <td>\n";
- $retval .= " {$event['EVENT_TYPE']}\n";
+ $retval .= " {$event['type']}\n";
$retval .= " </td>\n";
$retval .= " </tr>\n";
return $retval;
} // end PMA_EVN_getRowForList()
-?>
diff --git a/libraries/rte/rte_main.inc.php b/libraries/rte/rte_main.inc.php
index 93047ab6f4..fc03848556 100644
--- a/libraries/rte/rte_main.inc.php
+++ b/libraries/rte/rte_main.inc.php
@@ -28,7 +28,18 @@ if ($GLOBALS['is_ajax_request'] != true) {
} else {
$table = '';
include_once './libraries/db_common.inc.php';
- include_once './libraries/db_info.inc.php';
+
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
}
} else {
/**
@@ -91,4 +102,3 @@ case 'EVN':
break;
}
-?>
diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php
index 70ec2a093d..9fca018734 100644
--- a/libraries/rte/rte_routines.lib.php
+++ b/libraries/rte/rte_routines.lib.php
@@ -9,6 +9,8 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once 'libraries/Template.class.php';
+
/**
* Sets required globals
*
@@ -53,16 +55,10 @@ function PMA_RTN_main($type)
/**
* Display a list of available routines
*/
- $columns = "`SPECIFIC_NAME`, `ROUTINE_NAME`, `ROUTINE_TYPE`, ";
- $columns .= "`DTD_IDENTIFIER`, `ROUTINE_DEFINITION`";
- $where = "ROUTINE_SCHEMA " . PMA_Util::getCollateForIS() . "="
- . "'" . PMA_Util::sqlAddSlashes($db) . "'";
- if (PMA_isValid($type, array('FUNCTION','PROCEDURE'))) {
- $where .= " AND `ROUTINE_TYPE`='" . $type . "'";
+ if (! PMA_isValid($type, array('FUNCTION','PROCEDURE'))) {
+ $type = null;
}
- $items = $GLOBALS['dbi']->fetchResult(
- "SELECT $columns FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE $where;"
- );
+ $items = $GLOBALS['dbi']->getRoutines($db, $type);
echo PMA_RTE_getList('routine', $items);
/**
* Display the form for adding a new routine, if the user has the privileges.
@@ -86,198 +82,6 @@ function PMA_RTN_main($type)
} // end PMA_RTN_main()
/**
- * This function parses a string containing one parameter of a routine,
- * as returned by PMA_RTN_parseAllParameters() and returns an array containing
- * the information about this parameter.
- *
- * @param string $value A string containing one parameter of a routine
- *
- * @return array Parsed information about the input parameter
- */
-function PMA_RTN_parseOneParameter($value)
-{
- global $param_directions;
-
- $retval = array(0 => '',
- 1 => '',
- 2 => '',
- 3 => '',
- 4 => '');
- $parsed_param = PMA_SQP_parse($value);
- $pos = 0;
- while ($pos < $parsed_param['len']
- && $parsed_param[$pos]['type'] == 'white_newline'
- ) {
- $pos++;
- }
- if (in_array(
- /*overload*/mb_strtoupper($parsed_param[$pos]['data']),
- $param_directions
- )) {
- $retval[0] = /*overload*/mb_strtoupper($parsed_param[0]['data']);
- $pos++;
- }
- if ($parsed_param[$pos]['type'] == 'alpha_identifier'
- || $parsed_param[$pos]['type'] == 'quote_backtick'
- ) {
- $retval[1] = PMA_Util::unQuote(
- $parsed_param[$pos]['data']
- );
- $pos++;
- }
- $depth = 0;
- $param_length = '';
- $param_opts = array();
- for ($i=$pos; $i<$parsed_param['len']; $i++) {
- if (($parsed_param[$i]['type'] == 'alpha_columnType'
- || $parsed_param[$i]['type'] == 'alpha_functionName') && $depth == 0
- ) {
- $retval[2] = /*overload*/mb_strtoupper($parsed_param[$i]['data']);
- } else if ($parsed_param[$i]['type'] == 'punct_bracket_open_round'
- && $depth == 0
- ) {
- $depth = 1;
- } else if ($parsed_param[$i]['type'] == 'punct_bracket_close_round'
- && $depth == 1
- ) {
- $depth = 0;
- } else if ($depth == 1) {
- $param_length .= $parsed_param[$i]['data'];
- } else if ($parsed_param[$i]['type'] == 'alpha_reservedWord'
- && /*overload*/mb_strtoupper($parsed_param[$i]['data']) == 'CHARSET'
- && $depth == 0
- ) {
- if ($parsed_param[$i+1]['type'] == 'alpha_charset'
- || $parsed_param[$i+1]['type'] == 'alpha_identifier'
- ) {
- $param_opts[] = /*overload*/mb_strtolower(
- $parsed_param[$i+1]['data']
- );
- }
- } else if ($parsed_param[$i]['type'] == 'alpha_columnAttrib'
- && $depth == 0
- ) {
- $param_opts[] = /*overload*/mb_strtoupper($parsed_param[$i]['data']);
- }
- }
- $retval[3] = $param_length;
- sort($param_opts);
- $retval[4] = implode(' ', $param_opts);
-
- return $retval;
-} // end PMA_RTN_parseOneParameter()
-
-/**
- * This function looks through the contents of a parsed
- * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts
- * information about the routine's parameters.
- *
- * @param array $parsed_query Parsed query, returned by by PMA_SQP_parse()
- * @param string $routine_type Routine type: 'PROCEDURE' or 'FUNCTION'
- *
- * @return array Information about the parameters of a routine.
- */
-function PMA_RTN_parseAllParameters($parsed_query, $routine_type)
-{
- $retval = array();
- $retval['num'] = 0;
-
- if ($parsed_query) {
- // First get the list of parameters from the query
- $buffer = '';
- $params = array();
- $fetching = false;
- $depth = 0;
- for ($i=0; $i<$parsed_query['len']; $i++) {
- if ($parsed_query[$i]['type'] == 'alpha_reservedWord'
- && $parsed_query[$i]['data'] == $routine_type
- ) {
- $fetching = true;
- } else if ($fetching == true
- && $parsed_query[$i]['type'] == 'punct_bracket_open_round'
- ) {
- $depth++;
- if ($depth > 1) {
- $buffer .= $parsed_query[$i]['data'] . ' ';
- }
- } else if ($fetching == true
- && $parsed_query[$i]['type'] == 'punct_bracket_close_round'
- ) {
- $depth--;
- if ($depth > 0) {
- $buffer .= $parsed_query[$i]['data'] . ' ';
- } else {
- break;
- }
- } else if ($parsed_query[$i]['type'] == 'punct_listsep' && $depth == 1) {
- $params[] = $buffer;
- $retval['num']++;
- $buffer = '';
- } else if ($fetching == true && $depth > 0) {
- $buffer .= $parsed_query[$i]['data'] . ' ';
- }
- }
- if (! empty($buffer)) {
- $params[] = $buffer;
- $retval['num']++;
- }
- // Now parse each parameter individually
- foreach ($params as $key => $value) {
- list($retval['dir'][],
- $retval['name'][],
- $retval['type'][],
- $retval['length'][],
- $retval['opts'][]) = PMA_RTN_parseOneParameter($value);
- }
- }
- // Since some indices of $retval may be still undefined, we fill
- // them each with an empty array to avoid E_ALL errors in PHP.
- foreach (array('dir', 'name', 'type', 'length', 'opts') as $key => $index) {
- if (! isset($retval[$index])) {
- $retval[$index] = array();
- }
- }
-
- return $retval;
-} // end PMA_RTN_parseAllParameters()
-
-/**
- * This function looks through the contents of a parsed
- * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts
- * information about the routine's definer.
- *
- * @param array $parsed_query Parsed query, returned by PMA_SQP_parse()
- *
- * @return string The definer of a routine.
- */
-function PMA_RTN_parseRoutineDefiner($parsed_query)
-{
- $retval = '';
- $fetching = false;
- for ($i=0; $i<$parsed_query['len']; $i++) {
- if ($parsed_query[$i]['type'] == 'alpha_reservedWord'
- && $parsed_query[$i]['data'] == 'DEFINER'
- ) {
- $fetching = true;
- } else if ($fetching == true
- && $parsed_query[$i]['type'] != 'quote_backtick'
- && /*overload*/mb_substr($parsed_query[$i]['type'], 0, 5) != 'punct'
- ) {
- break;
- } else if ($fetching == true
- && $parsed_query[$i]['type'] == 'quote_backtick'
- ) {
- $retval .= PMA_Util::unQuote(
- $parsed_query[$i]['data']
- );
- } else if ($fetching == true && $parsed_query[$i]['type'] == 'punct_user') {
- $retval .= $parsed_query[$i]['data'];
- }
- }
- return $retval;
-} // end PMA_RTN_parseRoutineDefiner()
-
-/**
* Handles editor requests for adding or editing an item
*
* @return void
@@ -286,144 +90,7 @@ function PMA_RTN_handleEditor()
{
global $_GET, $_POST, $_REQUEST, $GLOBALS, $db, $errors;
- if (! empty($_REQUEST['editor_process_add'])
- || ! empty($_REQUEST['editor_process_edit'])
- ) {
- /**
- * Handle a request to create/edit a routine
- */
- $sql_query = '';
- $routine_query = PMA_RTN_getQueryFromRequest();
- if (! count($errors)) { // set by PMA_RTN_getQueryFromRequest()
- // Execute the created query
- if (! empty($_REQUEST['editor_process_edit'])) {
- $isProcOrFunc = in_array(
- $_REQUEST['item_original_type'],
- array('PROCEDURE', 'FUNCTION')
- );
- if (!$isProcOrFunc) {
- $errors[] = sprintf(
- __('Invalid routine type: "%s"'),
- htmlspecialchars($_REQUEST['item_original_type'])
- );
- } else {
- // Backup the old routine, in case something goes wrong
- $create_routine = $GLOBALS['dbi']->getDefinition(
- $db, $_REQUEST['item_original_type'],
- $_REQUEST['item_original_name']
- );
- $drop_routine = "DROP {$_REQUEST['item_original_type']} "
- . PMA_Util::backquote($_REQUEST['item_original_name'])
- . ";\n";
- $result = $GLOBALS['dbi']->tryQuery($drop_routine);
- if (! $result) {
- $errors[] = sprintf(
- __('The following query has failed: "%s"'),
- htmlspecialchars($drop_routine)
- )
- . '<br />'
- . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
- } else {
- $result = $GLOBALS['dbi']->tryQuery($routine_query);
- if (! $result) {
- $errors[] = sprintf(
- __('The following query has failed: "%s"'),
- htmlspecialchars($routine_query)
- )
- . '<br />'
- . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
- // We dropped the old routine,
- // but were unable to create the new one
- // Try to restore the backup query
- $result = $GLOBALS['dbi']->tryQuery($create_routine);
- $errors = checkResult(
- $result,
- __(
- 'Sorry, we failed to restore'
- . ' the dropped routine.'
- ),
- $create_routine,
- $errors
- );
- } else {
- $message = PMA_Message::success(
- __('Routine %1$s has been modified.')
- );
- $message->addParam(
- PMA_Util::backquote($_REQUEST['item_name'])
- );
- $sql_query = $drop_routine . $routine_query;
- }
- }
- }
- } else {
- // 'Add a new routine' mode
- $result = $GLOBALS['dbi']->tryQuery($routine_query);
- if (! $result) {
- $errors[] = sprintf(
- __('The following query has failed: "%s"'),
- htmlspecialchars($routine_query)
- )
- . '<br /><br />'
- . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
- } else {
- $message = PMA_Message::success(
- __('Routine %1$s has been created.')
- );
- $message->addParam(
- PMA_Util::backquote($_REQUEST['item_name'])
- );
- $sql_query = $routine_query;
- }
- }
- }
-
- if (count($errors)) {
- $message = PMA_Message::error(
- __(
- 'One or more errors have occurred while'
- . ' processing your request:'
- )
- );
- $message->addString('<ul>');
- foreach ($errors as $string) {
- $message->addString('<li>' . $string . '</li>');
- }
- $message->addString('</ul>');
- }
-
- $output = PMA_Util::getMessage($message, $sql_query);
- if ($GLOBALS['is_ajax_request']) {
- $response = PMA_Response::getInstance();
- if ($message->isSuccess()) {
- $columns = "`SPECIFIC_NAME`, `ROUTINE_NAME`, `ROUTINE_TYPE`,"
- . " `DTD_IDENTIFIER`, `ROUTINE_DEFINITION`";
- $where = "ROUTINE_SCHEMA " . PMA_Util::getCollateForIS() . "="
- . "'" . PMA_Util::sqlAddSlashes($db) . "' "
- . "AND ROUTINE_NAME='"
- . PMA_Util::sqlAddSlashes($_REQUEST['item_name']) . "'"
- . "AND ROUTINE_TYPE='"
- . PMA_Util::sqlAddSlashes($_REQUEST['item_type']) . "'";
- $routine = $GLOBALS['dbi']->fetchSingleRow(
- "SELECT $columns FROM `INFORMATION_SCHEMA`.`ROUTINES`"
- . " WHERE $where;"
- );
- $response->addJSON(
- 'name',
- htmlspecialchars(
- /*overload*/mb_strtoupper($_REQUEST['item_name'])
- )
- );
- $response->addJSON('new_row', PMA_RTN_getRowForList($routine));
- $response->addJSON('insert', ! empty($routine));
- $response->addJSON('message', $output);
- } else {
- $response->isSuccess(false);
- $response->addJSON('message', $output);
- }
- exit;
- }
- }
+ $errors = PMA_RTN_handleRequestCreateOrEdit($errors, $db);
/**
* Display a form used to add/edit a routine, if necessary
@@ -491,6 +158,7 @@ function PMA_RTN_handleEditor()
);
$message = PMA_message::error($message);
if ($GLOBALS['is_ajax_request']) {
+ $response = PMA_Response::getInstance();
$response->isSuccess(false);
$response->addJSON('message', $message);
exit;
@@ -499,6 +167,288 @@ function PMA_RTN_handleEditor()
}
}
}
+}
+
+/**
+ * Handle request to create or edit a routine
+ *
+ * @param array $errors Errors
+ * @param string $db DB name
+ *
+ * @return array
+ */
+function PMA_RTN_handleRequestCreateOrEdit($errors, $db)
+{
+ if (empty($_REQUEST['editor_process_add'])
+ && empty($_REQUEST['editor_process_edit'])
+ ) {
+ return $errors;
+ }
+
+ $sql_query = '';
+ $routine_query = PMA_RTN_getQueryFromRequest();
+ if (!count($errors)) { // set by PMA_RTN_getQueryFromRequest()
+ // Execute the created query
+ if (!empty($_REQUEST['editor_process_edit'])) {
+ $isProcOrFunc = in_array(
+ $_REQUEST['item_original_type'],
+ array('PROCEDURE', 'FUNCTION')
+ );
+
+ if (!$isProcOrFunc) {
+ $errors[] = sprintf(
+ __('Invalid routine type: "%s"'),
+ htmlspecialchars($_REQUEST['item_original_type'])
+ );
+ } else {
+ // Backup the old routine, in case something goes wrong
+ $create_routine = $GLOBALS['dbi']->getDefinition(
+ $db,
+ $_REQUEST['item_original_type'],
+ $_REQUEST['item_original_name']
+ );
+
+ $privilegesBackup = PMA_RTN_backupPrivileges();
+
+ $drop_routine = "DROP {$_REQUEST['item_original_type']} "
+ . PMA_Util::backquote($_REQUEST['item_original_name'])
+ . ";\n";
+ $result = $GLOBALS['dbi']->tryQuery($drop_routine);
+ if (!$result) {
+ $errors[] = sprintf(
+ __('The following query has failed: "%s"'),
+ htmlspecialchars($drop_routine)
+ )
+ . '<br />'
+ . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
+ } else {
+ list($newErrors, $message) = PMA_RTN_createRoutine(
+ $routine_query,
+ $create_routine,
+ $privilegesBackup
+ );
+ if (empty($newErrors)) {
+ $sql_query = $drop_routine . $sql_query;
+ } else {
+ $errors = array_merge($errors, $newErrors);
+ }
+ unset($newErrors);
+ if (null === $message) {
+ unset($message);
+ }
+ }
+ }
+ } else {
+ // 'Add a new routine' mode
+ $result = $GLOBALS['dbi']->tryQuery($routine_query);
+ if (!$result) {
+ $errors[] = sprintf(
+ __('The following query has failed: "%s"'),
+ htmlspecialchars($routine_query)
+ )
+ . '<br /><br />'
+ . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
+ } else {
+ $message = PMA_Message::success(
+ __('Routine %1$s has been created.')
+ );
+ $message->addParam(
+ PMA_Util::backquote($_REQUEST['item_name'])
+ );
+ $sql_query = $routine_query;
+ }
+ }
+ }
+
+ if (count($errors)) {
+ $message = PMA_Message::error(
+ __(
+ 'One or more errors have occurred while'
+ . ' processing your request:'
+ )
+ );
+ $message->addString('<ul>');
+ foreach ($errors as $string) {
+ $message->addString('<li>' . $string . '</li>');
+ }
+ $message->addString('</ul>');
+ }
+
+ $output = PMA_Util::getMessage($message, $sql_query);
+ if (!$GLOBALS['is_ajax_request']) {
+ return $errors;
+ }
+
+ $response = PMA_Response::getInstance();
+ if (!$message->isSuccess()) {
+ $response->isSuccess(false);
+ $response->addJSON('message', $output);
+ exit;
+ }
+
+ $routines = $GLOBALS['dbi']->getRoutines(
+ $db,
+ $_REQUEST['item_type'],
+ $_REQUEST['item_name']
+ );
+ $routine = $routines[0];
+ $response->addJSON(
+ 'name',
+ htmlspecialchars(
+ /*overload*/
+ mb_strtoupper($_REQUEST['item_name'])
+ )
+ );
+ $response->addJSON('new_row', PMA_RTN_getRowForList($routine));
+ $response->addJSON('insert', !empty($routine));
+ $response->addJSON('message', $output);
+ exit;
+}
+
+/**
+ * Backup the privileges
+ *
+ * @return array
+ */
+function PMA_RTN_backupPrivileges()
+{
+ if (defined('PMA_DRIZZLE') && PMA_DRIZZLE) {
+ return array();
+ }
+
+ if (!(isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv'])
+ && $GLOBALS['flush_priv'])
+ ) {
+ return array();
+ }
+
+ // Backup the Old Privileges before dropping
+ // if $_REQUEST['item_adjust_privileges'] set
+ if (!isset($_REQUEST['item_adjust_privileges'])
+ || empty($_REQUEST['item_adjust_privileges'])
+ ) {
+ return array();
+ }
+
+ $privilegesBackupQuery = 'SELECT * FROM ' . PMA_Util::backquote(
+ 'mysql'
+ )
+ . '.' . PMA_Util::backquote('procs_priv')
+ . ' where Routine_name = "' . $_REQUEST['item_original_name']
+ . '" AND Routine_type = "' . $_REQUEST['item_original_type']
+ . '";';
+
+ $privilegesBackup = $GLOBALS['dbi']->fetchResult(
+ $privilegesBackupQuery,
+ 0
+ );
+
+ return $privilegesBackup;
+}
+
+/**
+ * Create the routine
+ *
+ * @param string $routine_query Query to create routine
+ * @param string $create_routine Query to restore routine
+ * @param array $privilegesBackup Privileges backup
+ *
+ * @return array
+ */
+function PMA_RTN_createRoutine(
+ $routine_query,
+ $create_routine,
+ $privilegesBackup
+) {
+ $result = $GLOBALS['dbi']->tryQuery($routine_query);
+ if (!$result) {
+ $errors = array();
+ $errors[] = sprintf(
+ __('The following query has failed: "%s"'),
+ htmlspecialchars($routine_query)
+ )
+ . '<br />'
+ . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
+ // We dropped the old routine,
+ // but were unable to create the new one
+ // Try to restore the backup query
+ $result = $GLOBALS['dbi']->tryQuery($create_routine);
+ $errors = checkResult(
+ $result,
+ __(
+ 'Sorry, we failed to restore'
+ . ' the dropped routine.'
+ ),
+ $create_routine,
+ $errors
+ );
+
+ return array($errors, null);
+ }
+
+ // Default value
+ $resultAdjust = false;
+
+ if (!defined('PMA_DRIZZLE') || !PMA_DRIZZLE) {
+ if (isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv'])
+ && $GLOBALS['flush_priv']
+ ) {
+ // Insert all the previous privileges
+ // but with the new name and the new type
+ foreach ($privilegesBackup as $priv) {
+ $adjustProcPrivilege = 'INSERT INTO '
+ . PMA_Util::backquote('mysql') . '.'
+ . PMA_Util::backquote('procs_priv')
+ . ' VALUES("' . $priv[0] . '", "'
+ . $priv[1] . '", "' . $priv[2] . '", "'
+ . $_REQUEST['item_name'] . '", "'
+ . $_REQUEST['item_type'] . '", "'
+ . $priv[5] . '", "'
+ . $priv[6] . '", "'
+ . $priv[7] . '");';
+ $resultAdjust = $GLOBALS['dbi']->query(
+ $adjustProcPrivilege
+ );
+ }
+ }
+ }
+
+ $message = PMA_RTN_flushPrivileges($resultAdjust);
+
+ return array(array(), $message);
+}
+
+/**
+ * Flush privileges and get message
+ *
+ * @param bool $flushPrivileges Flush privileges
+ *
+ * @return PMA_Message
+ */
+function PMA_RTN_flushPrivileges($flushPrivileges)
+{
+ if ($flushPrivileges) {
+ // Flush the Privileges
+ $flushPrivQuery = 'FLUSH PRIVILEGES;';
+ $GLOBALS['dbi']->query($flushPrivQuery);
+
+ $message = PMA_Message::success(
+ __(
+ 'Routine %1$s has been modified. Privileges have been adjusted.'
+ )
+ );
+ } else {
+ $message = PMA_Message::success(
+ __('Routine %1$s has been modified.')
+ );
+ }
+ $message->addParam(
+ PMA_Util::backquote($_REQUEST['item_name'])
+ );
+
+ return $message;
} // end PMA_RTN_handleEditor()
/**
@@ -545,7 +495,7 @@ function PMA_RTN_getDataFromRequest()
$retval['item_param_length'] = array();
$retval['item_param_opts_num'] = array();
$retval['item_param_opts_text'] = array();
- if ( isset($_REQUEST['item_param_name'])
+ if (isset($_REQUEST['item_param_name'])
&& isset($_REQUEST['item_param_type'])
&& isset($_REQUEST['item_param_length'])
&& isset($_REQUEST['item_param_opts_num'])
@@ -650,21 +600,29 @@ function PMA_RTN_getDataFromName($name, $type, $all = true)
// Get required data
$retval['item_name'] = $routine['SPECIFIC_NAME'];
$retval['item_type'] = $routine['ROUTINE_TYPE'];
- $parsed_query = PMA_SQP_parse(
+
+ $parser = new SqlParser\Parser(
$GLOBALS['dbi']->getDefinition(
$db,
$routine['ROUTINE_TYPE'],
$routine['SPECIFIC_NAME']
)
);
- $params = PMA_RTN_parseAllParameters($parsed_query, $routine['ROUTINE_TYPE']);
- $retval['item_num_params'] = $params['num'];
- $retval['item_param_dir'] = $params['dir'];
- $retval['item_param_name'] = $params['name'];
- $retval['item_param_type'] = $params['type'];
- $retval['item_param_length'] = $params['length'];
- $retval['item_param_opts_num'] = $params['opts'];
- $retval['item_param_opts_text'] = $params['opts'];
+
+ /**
+ * @var CreateStatement $stmt
+ */
+ $stmt = $parser->statements[0];
+
+ $params = SqlParser\Utils\Routine::getParameters($stmt);
+ $retval['item_num_params'] = $params['num'];
+ $retval['item_param_dir'] = $params['dir'];
+ $retval['item_param_name'] = $params['name'];
+ $retval['item_param_type'] = $params['type'];
+ $retval['item_param_length'] = $params['length'];
+ $retval['item_param_length_arr'] = $params['length_arr'];
+ $retval['item_param_opts_num'] = $params['opts'];
+ $retval['item_param_opts_text'] = $params['opts'];
// Get extra data
if (!$all) {
@@ -676,55 +634,24 @@ function PMA_RTN_getDataFromName($name, $type, $all = true)
} else {
$retval['item_type_toggle'] = 'FUNCTION';
}
- $retval['item_returntype'] = '';
- $retval['item_returnlength'] = '';
+ $retval['item_returntype'] = '';
+ $retval['item_returnlength'] = '';
$retval['item_returnopts_num'] = '';
$retval['item_returnopts_text'] = '';
+
if (! empty($routine['DTD_IDENTIFIER'])) {
- if (/*overload*/mb_strlen($routine['DTD_IDENTIFIER']) > 63) {
- // If the DTD_IDENTIFIER string from INFORMATION_SCHEMA is
- // at least 64 characters, then it may actually have been
- // chopped because that column is a varchar(64), so we will
- // parse the output of SHOW CREATE query to get accurate
- // information about the return variable.
- $dtd = '';
- $fetching = false;
- for ($i=0; $i<$parsed_query['len']; $i++) {
- if ($parsed_query[$i]['type'] == 'alpha_reservedWord'
- && /*overload*/mb_strtoupper($parsed_query[$i]['data']) == 'RETURNS'
- ) {
- $fetching = true;
- } else if ($fetching == true
- && $parsed_query[$i]['type'] == 'alpha_reservedWord'
- ) {
- // We will not be looking for options such as UNSIGNED
- // or ZEROFILL because there is no way that a numeric
- // field's DTD_IDENTIFIER can be longer than 64
- // characters. We can safely assume that the return
- // datatype is either ENUM or SET, so we only look
- // for CHARSET.
- $word = /*overload*/mb_strtoupper($parsed_query[$i]['data']);
- if ($word == 'CHARSET'
- && ($parsed_query[$i+1]['type'] == 'alpha_charset'
- || $parsed_query[$i+1]['type'] == 'alpha_identifier')
- ) {
- $dtd .= $word . ' ' . $parsed_query[$i+1]['data'];
- }
- break;
- } else if ($fetching == true) {
- $dtd .= $parsed_query[$i]['data'] . ' ';
- }
- }
- $routine['DTD_IDENTIFIER'] = $dtd;
+ $options = array();
+ foreach ($stmt->return->options->options as $opt) {
+ $options[] = is_string($opt) ? $opt : $opt['value'];
}
- $returnparam = PMA_RTN_parseOneParameter($routine['DTD_IDENTIFIER']);
- $retval['item_returntype'] = $returnparam[2];
- $retval['item_returnlength'] = $returnparam[3];
- $retval['item_returnopts_num'] = $returnparam[4];
- $retval['item_returnopts_text'] = $returnparam[4];
+
+ $retval['item_returntype'] = $stmt->return->name;
+ $retval['item_returnlength'] = implode(',', $stmt->return->size);
+ $retval['item_returnopts_num'] = implode(' ', $options);
+ $retval['item_returnopts_text'] = implode(' ', $options);
}
- $retval['item_definer'] = PMA_RTN_parseRoutineDefiner($parsed_query);
+ $retval['item_definer'] = $stmt->options->has('DEFINER');
$retval['item_definition'] = $routine['ROUTINE_DEFINITION'];
$retval['item_isdeterministic'] = '';
if ($routine['IS_DETERMINISTIC'] == 'YES') {
@@ -882,7 +809,7 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine)
foreach ($need_escape as $key => $index) {
$routine[$index] = htmlentities($routine[$index], ENT_QUOTES, 'UTF-8');
}
- for ($i=0; $i<$routine['item_num_params']; $i++) {
+ for ($i = 0; $i < $routine['item_num_params']; $i++) {
$routine['item_param_name'][$i] = htmlentities(
$routine['item_param_name'][$i],
ENT_QUOTES
@@ -913,12 +840,12 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine)
$routine['item_param_opts_text'][] = '';
$routine['item_num_params']++;
} else if ($operation == 'remove') {
- unset($routine['item_param_dir'][$routine['item_num_params']-1]);
- unset($routine['item_param_name'][$routine['item_num_params']-1]);
- unset($routine['item_param_type'][$routine['item_num_params']-1]);
- unset($routine['item_param_length'][$routine['item_num_params']-1]);
- unset($routine['item_param_opts_num'][$routine['item_num_params']-1]);
- unset($routine['item_param_opts_text'][$routine['item_num_params']-1]);
+ unset($routine['item_param_dir'][$routine['item_num_params'] - 1]);
+ unset($routine['item_param_name'][$routine['item_num_params'] - 1]);
+ unset($routine['item_param_type'][$routine['item_num_params'] - 1]);
+ unset($routine['item_param_length'][$routine['item_num_params'] - 1]);
+ unset($routine['item_param_opts_num'][$routine['item_num_params'] - 1]);
+ unset($routine['item_param_opts_text'][$routine['item_num_params'] - 1]);
$routine['item_num_params']--;
}
$disableRemoveParam = '';
@@ -973,7 +900,7 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine)
} else {
$retval .= "<input name='item_type' type='hidden'"
. " value='{$routine['item_type']}' />\n"
- . "<div style='width: 49%; float: left; text-align: center;"
+ . "<div class='floatleft' style='width: 49%; text-align: center;"
. " font-weight: bold;'>\n"
. $routine['item_type'] . "\n"
. "</div>\n"
@@ -997,7 +924,7 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine)
$retval .= " <th colspan='2'>" . __('Options') . "</th>\n";
$retval .= " <th class='routine_param_remove hide'>&nbsp;</th>\n";
$retval .= " </tr>";
- for ($i=0; $i<$routine['item_num_params']; $i++) { // each parameter
+ for ($i = 0; $i < $routine['item_num_params']; $i++) { // each parameter
$retval .= PMA_RTN_getParameterRow($routine, $i, $isprocedure_class);
}
$retval .= " </table>";
@@ -1064,6 +991,32 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine)
$retval .= " <td><input type='checkbox' name='item_isdeterministic'"
. $routine['item_isdeterministic'] . " /></td>";
$retval .= "</tr>";
+ if (isset($_REQUEST['edit_item'])
+ && ! empty($_REQUEST['edit_item'])
+ ) {
+ $retval .= "<tr>";
+ $retval .= " <td>" . __('Adjust privileges');
+ $retval .= PMA_Util::showDocu('faq', 'faq6-39');
+ $retval .= "</td>";
+ if (! defined('PMA_DRIZZLE') || ! PMA_DRIZZLE) {
+ if (isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $retval .= " <td><input type='checkbox' "
+ . "name='item_adjust_privileges' value='1' checked /></td>";
+ } else {
+ $retval .= " <td><input type='checkbox' "
+ . "name='item_adjust_privileges' value='1' title='" . __(
+ "You do not have sufficient privileges to perform this "
+ . "operation; Please refer to the documentation for more "
+ . "details"
+ )
+ . "' disabled/></td>";
+ }
+ }
+ $retval .= "</tr>";
+ }
+
$retval .= "<tr>";
$retval .= " <td>" . __('Definer') . "</td>";
$retval .= " <td><input type='text' name='item_definer'";
@@ -1154,7 +1107,7 @@ function PMA_RTN_getQueryFromRequest()
$warned_about_dir = false;
$warned_about_length = false;
- if ( ! empty($_REQUEST['item_param_name'])
+ if (! empty($_REQUEST['item_param_name'])
&& ! empty($_REQUEST['item_param_type'])
&& ! empty($_REQUEST['item_param_length'])
&& is_array($_REQUEST['item_param_name'])
@@ -1265,7 +1218,6 @@ function PMA_RTN_getQueryFromRequest()
)
) {
if (! $warned_about_length) {
- $warned_about_length = true;
$errors[] = __(
'You must provide length/values for routine parameters'
. ' of type ENUM, SET, VARCHAR and VARBINARY.'
@@ -1356,7 +1308,7 @@ function PMA_RTN_handleExecute()
$end_query = array();
$args = array();
$all_functions = $GLOBALS['PMA_Types']->getAllFunctions();
- for ($i=0; $i<$routine['item_num_params']; $i++) {
+ for ($i = 0; $i < $routine['item_num_params']; $i++) {
if (isset($_REQUEST['params'][$routine['item_param_name'][$i]])) {
$value = $_REQUEST['params'][$routine['item_param_name'][$i]];
if (is_array($value)) { // is SET type
@@ -1599,7 +1551,7 @@ function PMA_RTN_getExecuteForm($routine)
// Escape special characters
$routine['item_name'] = htmlentities($routine['item_name'], ENT_QUOTES);
- for ($i=0; $i<$routine['item_num_params']; $i++) {
+ for ($i = 0; $i < $routine['item_num_params']; $i++) {
$routine['item_param_name'][$i] = htmlentities(
$routine['item_param_name'][$i],
ENT_QUOTES
@@ -1637,7 +1589,7 @@ function PMA_RTN_getExecuteForm($routine)
$retval .= "</tr>\n";
// Get a list of data types that are not yet supported.
$no_support_types = PMA_Util::unsupportedDatatypes();
- for ($i=0; $i<$routine['item_num_params']; $i++) { // Each parameter
+ for ($i = 0; $i < $routine['item_num_params']; $i++) { // Each parameter
if ($routine['item_type'] == 'PROCEDURE'
&& $routine['item_param_dir'][$i] == 'OUT'
) {
@@ -1687,24 +1639,18 @@ function PMA_RTN_getExecuteForm($routine)
}
$retval .= "<td class='nowrap'>\n";
if (in_array($routine['item_param_type'][$i], array('ENUM', 'SET'))) {
- $tokens = PMA_SQP_parse($routine['item_param_length'][$i]);
if ($routine['item_param_type'][$i] == 'ENUM') {
$input_type = 'radio';
} else {
$input_type = 'checkbox';
}
- for ($j=0; $j<$tokens['len']; $j++) {
- if ($tokens[$j]['type'] != 'punct_listsep') {
- $tokens[$j]['data'] = htmlentities(
- PMA_Util::unquote($tokens[$j]['data']),
- ENT_QUOTES
- );
- $retval .= "<input name='params["
- . $routine['item_param_name'][$i] . "][]' "
- . "value='" . $tokens[$j]['data'] . "' type='"
- . $input_type . "' />"
- . $tokens[$j]['data'] . "<br />\n";
- }
+ foreach ($routine['item_param_length_arr'][$i] as $value) {
+ $value = htmlentities(PMA_Util::unquote($value), ENT_QUOTES);
+ $retval .= "<input name='params["
+ . $routine['item_param_name'][$i] . "][]' "
+ . "value='" . $value . "' type='"
+ . $input_type . "' />"
+ . $value . "<br />\n";
}
} else if (in_array(
/*overload*/mb_strtolower($routine['item_param_type'][$i]),
@@ -1735,4 +1681,3 @@ function PMA_RTN_getExecuteForm($routine)
return $retval;
} // end PMA_RTN_getExecuteForm()
-?>
diff --git a/libraries/rte/rte_triggers.lib.php b/libraries/rte/rte_triggers.lib.php
index 19ecccb3d4..21add8f85c 100644
--- a/libraries/rte/rte_triggers.lib.php
+++ b/libraries/rte/rte_triggers.lib.php
@@ -460,4 +460,3 @@ function PMA_TRI_getQueryFromRequest()
return $query;
} // end PMA_TRI_getQueryFromRequest()
-?>
diff --git a/libraries/rte/rte_words.lib.php b/libraries/rte/rte_words.lib.php
index 81184f0b5c..18d757d252 100644
--- a/libraries/rte/rte_words.lib.php
+++ b/libraries/rte/rte_words.lib.php
@@ -72,4 +72,3 @@ function PMA_RTE_getWord($index)
return isset($words[$index]) ? $words[$index] : '';
} // end PMA_RTE_getWord()
-?>
diff --git a/libraries/sanitizing.lib.php b/libraries/sanitizing.lib.php
index ff7c12437d..92e27ca86b 100644
--- a/libraries/sanitizing.lib.php
+++ b/libraries/sanitizing.lib.php
@@ -188,4 +188,3 @@ function PMA_sanitizeFilename($filename, $replaceDots = false)
return $filename;
}
-?>
diff --git a/libraries/select_lang.lib.php b/libraries/select_lang.lib.php
index 8b0ed4496d..da8556c553 100644
--- a/libraries/select_lang.lib.php
+++ b/libraries/select_lang.lib.php
@@ -608,7 +608,8 @@ $GLOBALS['l']['w_page'] = __('Page number:');
// now, that we have loaded the language strings we can send the errors
if ($GLOBALS['lang_failed_cfg']
|| $GLOBALS['lang_failed_cookie']
- || $GLOBALS['lang_failed_request']) {
+ || $GLOBALS['lang_failed_request']
+) {
trigger_error(
__('Ignoring unsupported language code.'),
E_USER_ERROR
@@ -618,4 +619,3 @@ unset(
$line, $fall_back_lang, $GLOBALS['lang_failed_cfg'],
$GLOBALS['lang_failed_cookie'], $GLOBALS['lang_failed_request']
);
-?>
diff --git a/libraries/select_server.lib.php b/libraries/select_server.lib.php
index db06332f36..9b914813b6 100644
--- a/libraries/select_server.lib.php
+++ b/libraries/select_server.lib.php
@@ -31,19 +31,21 @@ function PMA_selectServer($not_only_options, $omit_fieldset)
if ($not_only_options) {
$retval .= '<form method="post" action="'
- . $GLOBALS['cfg']['DefaultTabServer'] . '" class="disableAjax">';
- $retval .= PMA_getHiddenFields(array('token' => $_SESSION[' PMA_token ']));
+ . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabServer'], 'server'
+ )
+ . '" class="disableAjax">';
if (! $omit_fieldset) {
$retval .= '<fieldset>';
}
$retval .= '<label for="select_server">'
- . __('Current Server:') . '</label> ';
+ . __('Current server:') . '</label> ';
$retval .= '<select name="server" id="select_server" class="autosubmit">';
$retval .= '<option value="">(' . __('Servers') . ') ...</option>' . "\n";
} elseif ($list) {
- $retval .= __('Current Server:') . '<br />';
+ $retval .= __('Current server:') . '<br />';
$retval .= '<ul id="list_server">';
}
@@ -84,7 +86,9 @@ function PMA_selectServer($not_only_options, $omit_fieldset)
} else {
$retval .= '<a class="disableAjax item" href="'
- . $GLOBALS['cfg']['DefaultTabServer']
+ . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabServer'], 'server'
+ )
. PMA_URL_getCommon(array('server' => $key))
. '" >' . htmlspecialchars($label) . '</a>';
}
@@ -108,4 +112,3 @@ function PMA_selectServer($not_only_options, $omit_fieldset)
return $retval;
}
-?>
diff --git a/libraries/server_bin_log.lib.php b/libraries/server_bin_log.lib.php
index 0b1142331c..78ac6d421f 100644
--- a/libraries/server_bin_log.lib.php
+++ b/libraries/server_bin_log.lib.php
@@ -115,7 +115,7 @@ function PMA_getLogInfo($url_params)
//html output
$html = PMA_Util::getMessage(PMA_Message::success(), $sql_query);
- $html .= '<table cellpadding="2" cellspacing="1" id="binlogTable">'
+ $html .= '<table id="binlogTable">'
. '<thead>'
. '<tr>'
. '<td colspan="6" class="center">';
@@ -225,20 +225,19 @@ function PMA_getAllLogItemInfo($result, $dontlimitchars)
$odd_row = true;
while ($value = $GLOBALS['dbi']->fetchAssoc($result)) {
$html .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">'
- . '<td>&nbsp;' . $value['Log_name'] . '&nbsp;</td>'
- . '<td class="right">&nbsp;' . $value['Pos'] . '&nbsp;</td>'
- . '<td>&nbsp;' . $value['Event_type'] . '&nbsp;</td>'
- . '<td class="right">&nbsp;' . $value['Server_id'] . '&nbsp;</td>'
- . '<td class="right">&nbsp;'
+ . '<td>' . $value['Log_name'] . '</td>'
+ . '<td class="right">' . $value['Pos'] . '</td>'
+ . '<td>' . $value['Event_type'] . '</td>'
+ . '<td class="right">' . $value['Server_id'] . '</td>'
+ . '<td class="right">'
. (isset($value['Orig_log_pos'])
? $value['Orig_log_pos'] : $value['End_log_pos'])
- . '&nbsp;</td>'
- . '<td>&nbsp;' . PMA_Util::formatSql($value['Info'], ! $dontlimitchars)
- . '&nbsp;</td></tr>';
+ . '</td>'
+ . '<td>' . PMA_Util::formatSql($value['Info'], ! $dontlimitchars)
+ . '</td></tr>';
$odd_row = !$odd_row;
}
return $html;
}
-?>
diff --git a/libraries/server_collations.lib.php b/libraries/server_collations.lib.php
index 0ea690355f..a3bfabbb33 100644
--- a/libraries/server_collations.lib.php
+++ b/libraries/server_collations.lib.php
@@ -97,4 +97,3 @@ function PMA_getHtmlForCollationCurrentCharset(
}
return $html;
}
-?>
diff --git a/libraries/server_common.inc.php b/libraries/server_common.inc.php
index 1b69ba3808..b9a772fcb2 100644
--- a/libraries/server_common.inc.php
+++ b/libraries/server_common.inc.php
@@ -50,4 +50,3 @@ PMA_Util::checkParameters(
*/
require_once './libraries/server_common.lib.php';
-?>
diff --git a/libraries/server_common.lib.php b/libraries/server_common.lib.php
index 16c43c93af..2ee01bf599 100644
--- a/libraries/server_common.lib.php
+++ b/libraries/server_common.lib.php
@@ -64,4 +64,3 @@ function PMA_getHtmlForSubPageHeader($type, $link='', $is_image=true)
return $html;
}
-?>
diff --git a/libraries/server_databases.lib.php b/libraries/server_databases.lib.php
index 17fafca94c..7af2e057b2 100644
--- a/libraries/server_databases.lib.php
+++ b/libraries/server_databases.lib.php
@@ -23,8 +23,8 @@ if (! defined('PHPMYADMIN')) {
* @param string $sort_order sort order string
* @param bool $is_superuser User status
* @param Array $cfg configuration
- * @param string $replication_types replication types
- * @param string $replication_info replication info
+ * @param array $replication_types replication types
+ * @param array $replication_info replication info
* @param string $url_query url query
*
* @return string
@@ -194,10 +194,10 @@ function PMA_getHtmlForTableFooter(
*
* @param array $databases GBI return databases
* @param bool $is_superuser User status
- * @param Array $url_query Url query
- * @param string $column_order column order
- * @param string $replication_types replication types
- * @param string $replication_info replication info
+ * @param string $url_query Url query
+ * @param array $column_order column order
+ * @param array $replication_types replication types
+ * @param array $replication_info replication info
*
* @return Array
*/
@@ -345,7 +345,7 @@ function PMA_getHtmlForColumnOrderWithSort(
/**
* Returns the html for Enable Statistics
*
- * @param bool $url_query Url query
+ * @param string $url_query Url query
* @param string $html html for database list
*
* @return string
@@ -358,14 +358,24 @@ function PMA_getHtmlForNoticeEnableStatistics($url_query, $html)
. 'heavy traffic between the web server and the MySQL server.'
)
)->getDisplay();
- //we should put notice above database list
- $html = $notice . $html;
- $html .= '<ul><li id="li_switch_dbstats"><strong>' . "\n";
- $html .= '<a href="server_databases.php' . $url_query . '&amp;dbstats=1"'
- . ' title="' . __('Enable Statistics') . '">' . "\n"
- . ' ' . __('Enable Statistics');
- $html .= '</a></strong><br />' . "\n";
- $html .= '</li>' . "\n" . '</ul>' . "\n";
+ $html .= $notice;
+
+ $items = array();
+ $items[] = array(
+ 'content' => '<strong>' . "\n"
+ . __('Enable statistics')
+ . '</strong><br />' . "\n",
+ 'class' => 'li_switch_dbstats',
+ 'url' => array(
+ 'href' => 'server_databases.php' . $url_query . '&amp;dbstats=1',
+ 'title' => __('Enable statistics')
+ ),
+ );
+
+ include_once './libraries/Template.class.php';
+ $html .= PMA\Template::get('list/unordered')->render(
+ array('items' => $items,)
+ );
return $html;
}
@@ -495,4 +505,3 @@ function PMA_dropMultiDatabases()
}
}
-?>
diff --git a/libraries/server_engines.lib.php b/libraries/server_engines.lib.php
index 725b74d449..eddf7d4326 100644
--- a/libraries/server_engines.lib.php
+++ b/libraries/server_engines.lib.php
@@ -142,4 +142,3 @@ function PMA_getHtmlForSpecifiedServerEngines()
return $html;
}
-?>
diff --git a/libraries/server_plugins.lib.php b/libraries/server_plugins.lib.php
index 7c978f6c3c..7e2274a321 100644
--- a/libraries/server_plugins.lib.php
+++ b/libraries/server_plugins.lib.php
@@ -13,28 +13,94 @@ if (! defined('PHPMYADMIN')) {
}
/**
- * Returns the html for plugin and module Info.
+ * Get the HTML for the sub tabs
*
- * @param Array $plugins Plugin list
+ * @param string $activeUrl url of the active sub tab
*
- * @param Array $modules Module list
+ * @return string HTML for sub tabs
+ */
+function PMA_getHtmlForPluginsSubTabs($activeUrl)
+{
+ $url_params = PMA_URL_getCommon();
+ $items = array(
+ array(
+ 'name' => __('Plugins'),
+ 'url' => 'server_plugins.php'
+ ),
+ array(
+ 'name' => __('Modules'),
+ 'url' => 'server_modules.php'
+ )
+ );
+
+ $retval = '<ul id="topmenu2">';
+ foreach ($items as $item) {
+ $class = '';
+ if ($item['url'] === $activeUrl) {
+ $class = ' class="tabactive"';
+ }
+ $retval .= '<li>';
+ $retval .= '<a' . $class;
+ $retval .= ' href="' . $item['url'] . $url_params . '">';
+ $retval .= $item['name'];
+ $retval .= '</a>';
+ $retval .= '</li>';
+ }
+ $retval .= '</ul>';
+ $retval .= '<div class="clearfloat"></div>';
+
+ return $retval;
+}
+
+/**
+ * Returns the common SQL used to retrieve plugin and modules data
*
- * @return string
+ * @return string SQL
*/
-function PMA_getPluginAndModuleInfo($plugins, $modules)
+function PMA_getServerPluginModuleSQL()
{
- $html = '<script type="text/javascript">';
- $html .= 'pma_theme_image = "' . $GLOBALS['pmaThemeImage'] . '"';
- $html .= '</script>';
- $html .= '<div id="pluginsTabs">';
- $html .= '<ul>';
- $html .= '<li><a href="#plugins_plugins">' . __('Plugins') . '</a></li>';
- $html .= '<li><a href="#plugins_modules">' . __('Modules') . '</a></li>';
- $html .= '</ul>';
- $html .= PMA_getPluginTab($plugins);
- $html .= PMA_getModuleTab($modules);
- $html .= '</div>';
- return $html;
+ return "SELECT p.plugin_name, p.plugin_type, p.is_active, m.module_name,
+ m.module_library, m.module_version, m.module_author,
+ m.module_description, m.module_license
+ FROM data_dictionary.plugins p
+ JOIN data_dictionary.modules m USING (module_name)
+ ORDER BY m.module_name, p.plugin_type, p.plugin_name";
+}
+
+/**
+ * Returns details about server plugins
+ *
+ * @return array server plugins data
+ */
+function PMA_getServerPlugins()
+{
+ $sql = PMA_getServerPluginModuleSQL();
+ $res = $GLOBALS['dbi']->query($sql);
+ $plugins = array();
+ while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
+ $plugins[$row['plugin_type']][] = $row;
+ }
+ $GLOBALS['dbi']->freeResult($res);
+ ksort($plugins);
+ return $plugins;
+}
+
+/**
+ * Returns details about server modules
+ *
+ * @return array server modules data
+ */
+function PMA_getServerModules()
+{
+ $sql = PMA_getServerPluginModuleSQL();
+ $res = $GLOBALS['dbi']->query($sql);
+ $modules = array();
+ while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
+ $modules[$row['module_name']]['info'] = $row;
+ $modules[$row['module_name']]['plugins'][$row['plugin_type']][] = $row;
+ }
+ $GLOBALS['dbi']->freeResult($res);
+ return $modules;
}
/**
@@ -66,10 +132,6 @@ function PMA_getPluginTab($plugins)
$html .= '<table class="data_full_width" id="' . $key . '">';
$html .= '<caption class="tblHeaders">';
- $html .= '<a class="top" href="#serverinfo">';
- $html .= __('Begin');
- $html .= PMA_Util::getImage('s_asc.png');
- $html .= '</a>';
$html .= htmlspecialchars($plugin_type);
$html .= '</caption>';
$html .= '<thead>';
@@ -204,4 +266,3 @@ function PMA_getModuleList($modules)
return $html;
}
-?>
diff --git a/libraries/server_privileges.lib.php b/libraries/server_privileges.lib.php
index bcf4d978f5..7c62918adf 100644
--- a/libraries/server_privileges.lib.php
+++ b/libraries/server_privileges.lib.php
@@ -800,8 +800,8 @@ function PMA_getHtmlForRequires($row)
. 'REQUIRE SUBJECT'
. '</dfn></code></label>';
$html_output .= '<input type="text" name="x509_subject" id="text_x509_subject" '
- . 'value="' . (isset($row['x509_subject']) ? $row['x509_subject'] : '') . '" '
- . 'size=80" title="'
+ . 'value="' . (isset($row['x509_subject']) ? $row['x509_subject'] : '')
+ . '" size=80" title="'
. __(
'Requires that a valid X509 certificate with this subject be presented.'
)
@@ -837,7 +837,9 @@ function PMA_getHtmlForRequires($row)
'Requires SSL-encrypted connections.'
)
. '"'
- . ((isset($row['ssl_type']) && ($row['ssl_type'] == 'ANY' || $row['ssl_type'] == ''))
+ . ((isset($row['ssl_type'])
+ && ($row['ssl_type'] == 'ANY'
+ || $row['ssl_type'] == ''))
? ' checked="checked"'
: ''
)
@@ -1086,53 +1088,29 @@ function PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
. ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
. 'title="';
- $html_output .= (isset($GLOBALS[
- 'strPrivDesc' . /*overload*/mb_substr(
- $tmp_current_grant,
- 0,
- (/*overload*/mb_strlen($tmp_current_grant) - 5)
- )
- ] )
- ? $GLOBALS[
- 'strPrivDesc' . /*overload*/mb_substr(
- $tmp_current_grant,
- 0,
- (/*overload*/mb_strlen($tmp_current_grant) - 5)
- )
- ]
- : $GLOBALS[
- 'strPrivDesc' . /*overload*/mb_substr(
- $tmp_current_grant,
- 0,
- (/*overload*/mb_strlen($tmp_current_grant) - 5)
- ) . 'Tbl'
- ]
+ $privGlobalName = 'strPrivDesc'
+ . /*overload*/mb_substr(
+ $tmp_current_grant,
+ 0,
+ (/*overload*/mb_strlen($tmp_current_grant) - 5)
+ );
+ $html_output .= (isset($GLOBALS[$privGlobalName])
+ ? $GLOBALS[$privGlobalName]
+ : $GLOBALS[$privGlobalName . 'Tbl']
)
. '"/>' . "\n";
+ $privGlobalName1 = 'strPrivDesc'
+ . /*overload*/mb_substr(
+ $tmp_current_grant,
+ 0,
+ - 5
+ );
$html_output .= '<label for="checkbox_' . $current_grant
. '"><code><dfn title="'
- . (isset($GLOBALS[
- 'strPrivDesc' . /*overload*/mb_substr(
- $tmp_current_grant,
- 0,
- -5
- )
- ])
- ? $GLOBALS[
- 'strPrivDesc' . /*overload*/mb_substr(
- $tmp_current_grant,
- 0,
- -5
- )
- ]
- : $GLOBALS[
- 'strPrivDesc' . /*overload*/mb_substr(
- $tmp_current_grant,
- 0,
- -5
- ) . 'Tbl'
- ]
+ . (isset($GLOBALS[$privGlobalName1])
+ ? $GLOBALS[$privGlobalName1]
+ : $GLOBALS[$privGlobalName1 . 'Tbl']
)
. '">'
. /*overload*/mb_strtoupper(
@@ -1153,7 +1131,7 @@ function PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
*
* @param string $db the database
* @param string $table the table
- * @param string $row first row from result or boolean false
+ * @param array $row first row from result or boolean false
*
* @return string $html_output
*/
@@ -1193,8 +1171,8 @@ function PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row)
$html_output .= '<fieldset id="fieldset_user_global_rights">'
. '<legend data-submenu-label="' . $menu_label . '">' . $legend
. '<input type="checkbox" id="addUsersForm_checkall" '
- . 'class="checkall_box" title="' . __('Check All') . '" /> '
- . '<label for="addUsersForm_checkall">' . __('Check All') . '</label> '
+ . 'class="checkall_box" title="' . __('Check all') . '" /> '
+ . '<label for="addUsersForm_checkall">' . __('Check all') . '</label> '
. '</legend>'
. '<p><small><i>'
. __('Note: MySQL privilege names are expressed in English.')
@@ -1403,7 +1381,13 @@ function PMA_getHtmlForGlobalPrivTableWithCheckboxes(
$html_output = '';
foreach ($privTable as $i => $table) {
$html_output .= '<fieldset>' . "\n"
- . '<legend>' . $privTable_names[$i] . '</legend>' . "\n";
+ . '<legend>' . "\n"
+ . '<input type="checkbox" class="sub_checkall_box"'
+ . ' id="checkall_' . $privTable_names[$i] . '_priv"'
+ . ' title="' . __('Check all') . '"/>'
+ . '<label for="checkall_' . $privTable_names[$i] . '_priv">'
+ . $privTable_names[$i] . '</label>' . "\n"
+ . '</legend>' . "\n";
foreach ($table as $priv) {
$html_output .= '<div class="item">' . "\n"
. '<input type="checkbox" class="checkall"'
@@ -1431,16 +1415,21 @@ function PMA_getHtmlForGlobalPrivTableWithCheckboxes(
* Displays the fields used by the "new user" form as well as the
* "change login information / copy user" form.
*
- * @param string $mode are we creating a new user or are we just
- * changing one? (allowed values: 'new', 'change')
+ * @param string $mode are we creating a new user or are we just
+ * changing one? (allowed values: 'new', 'change')
+ * @param string $username User name
+ * @param string $hostname Host name
*
* @global array $cfg the phpMyAdmin configuration
* @global resource $user_link the database connection
*
* @return string $html_output a HTML snippet
*/
-function PMA_getHtmlForLoginInformationFields($mode = 'new')
-{
+function PMA_getHtmlForLoginInformationFields(
+ $mode = 'new',
+ $username = null,
+ $hostname = null
+) {
list($username_length, $hostname_length) = PMA_getUsernameAndHostnameLength();
if (isset($GLOBALS['username'])
@@ -1518,12 +1507,12 @@ function PMA_getHtmlForLoginInformationFields($mode = 'new')
$html_output .= '<div class="item">' . "\n"
. '<label for="select_pred_hostname">' . "\n"
- . ' ' . __('Host:') . "\n"
+ . ' ' . __('Host name:') . "\n"
. '</label>' . "\n";
$html_output .= '<span class="options">' . "\n"
. ' <select name="pred_hostname" id="select_pred_hostname" '
- . 'title="' . __('Host') . '"' . "\n";
+ . 'title="' . __('Host name') . '"' . "\n";
$_current_user = $GLOBALS['dbi']->fetchValue('SELECT USER();');
if (! empty($_current_user)) {
$thishost = str_replace(
@@ -1625,8 +1614,9 @@ function PMA_getHtmlForLoginInformationFields($mode = 'new')
. $hostname_length . '" value="'
// use default value of '%' to match with the default 'Any host'
. htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '%')
- . '" title="' . __('Host')
- . '" onchange="pred_hostname.value = \'userdefined\'; this.required = true;" '
+ . '" title="' . __('Host name')
+ . '" onchange="pred_hostname.value = \'userdefined\'; '
+ . 'this.required = true;" '
. ((isset($GLOBALS['pred_hostname'])
&& $GLOBALS['pred_hostname'] == 'userdefined'
)
@@ -1641,6 +1631,10 @@ function PMA_getHtmlForLoginInformationFields($mode = 'new')
)
. '</div>' . "\n";
+ $orig_auth_plugin = PMA_getCurrentAuthenticationPlugin(
+ $mode, $username, $hostname
+ );
+
$html_output .= '<div class="item">' . "\n"
. '<label for="select_pred_password">' . "\n"
. ' ' . __('Password:') . "\n"
@@ -1676,7 +1670,8 @@ function PMA_getHtmlForLoginInformationFields($mode = 'new')
. '</span>' . "\n"
. '<input type="password" id="text_pma_pw" name="pma_pw" '
. 'title="' . __('Password') . '" '
- . 'onchange="pred_password.value = \'userdefined\'; this.required = true; pma_pw2.required = true;" '
+ . 'onchange="pred_password.value = \'userdefined\'; this.required = true; '
+ . 'pma_pw2.required = true;" '
. (isset($GLOBALS['username']) ? '' : 'required="required"')
. '/>' . "\n"
. '</div>' . "\n";
@@ -1689,15 +1684,49 @@ function PMA_getHtmlForLoginInformationFields($mode = 'new')
. '<span class="options">&nbsp;</span>' . "\n"
. '<input type="password" name="pma_pw2" id="text_pma_pw2" '
. 'title="' . __('Re-type') . '" '
- . 'onchange="pred_password.value = \'userdefined\'; this.required = true; pma_pw.required = true;" '
+ . 'onchange="pred_password.value = \'userdefined\'; this.required = true; '
+ . 'pma_pw.required = true;" '
. (isset($GLOBALS['username']) ? '' : 'required="required"')
. '/>' . "\n"
. '</div>' . "\n"
+ . '<div class="item" id="authentication_plugin_div">'
+ . '<label for="select_authentication_plugin" >'
+ . __('Authentication Plugin')
+ . '</label><span class="options">&nbsp;</span>' . "\n"
+ . '<select id="select_authentication_plugin" name="authentication_plugin" '
+ . 'title="' . __('Authentication Plugin') . '" >'
+ . '<option value="mysql_native_password" '
+ . ($orig_auth_plugin == 'mysql_native_password' ? 'selected ' : '')
+ . '>' . __('MySQL native password') . '</option>';
+
+ // sha256 auth plugin exists only for 5.6.6+
+ if (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50606
+ ) {
+ $html_output .= '<option value="sha256_password" '
+ . ($orig_auth_plugin == 'sha256_password' ? ' selected ' : '')
+ . ' >' . __('SHA256 password') . '</option>';
+ }
+
+ $html_output .= '</select>'
+ . '<div id="ssl_reqd_warning" '
+ . ($orig_auth_plugin == 'sha256_password' ? '' : ' style="display:none"')
+ . ' >'
+ . PMA_Message::notice(
+ __(
+ 'This method requires using an \'<i>SSL connection</i>\' '
+ . 'or an \'<i>unencrypted connection that encrypts the password '
+ . 'using RSA</i>\'; while connecting to the server.'
+ )
+ . PMA_Util::showMySQLDocu('sha256-authentication-plugin')
+ )->getDisplay()
+ . '</div>'
+ . '</div>' . "\n"
// Generate password added here via jQuery
. '</fieldset>' . "\n";
return $html_output;
-} // end of the 'PMA_displayUserAndHostFields()' function
+} // end of the 'PMA_getHtmlForLoginInformationFields()' function
/**
* Get username and hostname length
@@ -1728,6 +1757,61 @@ function PMA_getUsernameAndHostnameLength()
}
/**
+ * Get current authentication plugin in use - for a user or globally
+ *
+ * @param string $mode are we creating a new user or are we just
+ * changing one? (allowed values: 'new', 'change')
+ * @param string $username User name
+ * @param string $hostname Host name
+ *
+ * @return string authentication plugin in use
+ */
+function PMA_getCurrentAuthenticationPlugin(
+ $mode = 'new',
+ $username = null,
+ $hostname = null
+) {
+ /* Fallback (standard) value */
+ $authentication_plugin = 'mysql_native_password';
+
+ if (isset($username) && isset($hostname)
+ && $mode == 'change'
+ ) {
+ $row = $GLOBALS['dbi']->fetchSingleRow(
+ 'SELECT `plugin` FROM `mysql`.`user` WHERE '
+ . '`User` = "' . $username . '" AND `Host` = "' . $hostname . '" LIMIT 1'
+ );
+ // Table 'mysql'.'user' may not exist for some previous
+ // versions of MySQL - in that case consider fallback value
+ if (isset($row) && $row) {
+ $authentication_plugin = $row['plugin'];
+ }
+ } elseif ($mode == 'change') {
+ $row = $GLOBALS['dbi']->fetchSingleRow(
+ 'SELECT CURRENT_USER() as user;'
+ );
+ if (isset($row) && $row) {
+ list($username, $hostname) = explode('@', $row['user']);
+ }
+
+ $row = $GLOBALS['dbi']->fetchSingleRow(
+ 'SELECT `plugin` FROM `mysql`.`user` WHERE '
+ . '`User` = "' . $username . '" AND `Host` = "' . $hostname . '"'
+ );
+ if (isset($row) && $row && ! empty($row['plugin'])) {
+ $authentication_plugin = $row['plugin'];
+ }
+ } elseif (PMA_MYSQL_INT_VERSION >= 50702) {
+ $row = $GLOBALS['dbi']->fetchSingleRow(
+ 'SELECT @@default_authentication_plugin'
+ );
+ $authentication_plugin = $row['@@default_authentication_plugin'];
+ }
+
+ return $authentication_plugin;
+}
+
+/**
* Returns all the grants for a certain user on a certain host
* Used in the export privileges for all users section
*
@@ -1780,10 +1864,18 @@ function PMA_updatePassword($err_url, $username, $hostname)
if (PMA_Util::getServerType() == 'MySQL'
&& PMA_MYSQL_INT_VERSION >= 50706
) {
- $query_prefix = "ALTER USER '"
- . PMA_Util::sqlAddSlashes($username)
- . "'@'" . PMA_Util::sqlAddSlashes($hostname) . "'"
- . " IDENTIFIED BY '";
+ if (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] != 'old') {
+ $query_prefix = "ALTER USER '"
+ . PMA_Util::sqlAddSlashes($username)
+ . "'@'" . PMA_Util::sqlAddSlashes($hostname) . "'"
+ . " IDENTIFIED WITH " . $_REQUEST['pw_hash']
+ . " BY '";
+ } else {
+ $query_prefix = "ALTER USER '"
+ . PMA_Util::sqlAddSlashes($username)
+ . "'@'" . PMA_Util::sqlAddSlashes($hostname) . "'"
+ . " IDENTIFIED BY '";
+ }
// in $sql_query which will be displayed, hide the password
$sql_query = $query_prefix . "*'";
@@ -1791,12 +1883,24 @@ function PMA_updatePassword($err_url, $username, $hostname)
$local_query = $query_prefix
. PMA_Util::sqlAddSlashes($_POST['pma_pw']) . "'";
} else {
- $hashing_function
- = (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] == 'old'
- ? 'OLD_'
- : ''
- )
- . 'PASSWORD';
+ if (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] == 'old') {
+ $hashing_function = 'OLD_PASSWORD';
+ } elseif (! empty($_REQUEST['pw_hash'])
+ && $_REQUEST['pw_hash'] == 'sha256_password'
+ ) {
+ $hashing_function = 'PASSWORD';
+
+ // Backup the old value, to be reset later
+ $row = $GLOBALS['dbi']->fetchSingleRow(
+ 'SELECT @@old_passwords;'
+ );
+ $orig_value = $row['@@old_passwords'];
+ // Set the hashing method used by PASSWORD()
+ // to be 'sha256_password' type
+ $GLOBALS['dbi']->tryQuery('SET old_passwords = 2;');
+ } else {
+ $hashing_function = 'PASSWORD';
+ }
$sql_query = 'SET PASSWORD FOR \''
. PMA_Util::sqlAddSlashes($username)
@@ -1824,6 +1928,11 @@ function PMA_updatePassword($err_url, $username, $hostname)
'\'' . htmlspecialchars($username)
. '\'@\'' . htmlspecialchars($hostname) . '\''
);
+ if (isset($orig_value)) {
+ $GLOBALS['dbi']->tryQuery(
+ 'SET `old_passwords` = ' . $orig_value . ';'
+ );
+ }
}
return $message;
}
@@ -1872,7 +1981,7 @@ function PMA_getMessageAndSqlQueryForPrivilegesRevoke($dbname,
/**
* Get REQUIRE cluase
*
- * @return stirng REQUIRE clause
+ * @return string REQUIRE clause
*/
function PMA_getRequireClause()
{
@@ -1949,7 +2058,7 @@ function PMA_getWithClauseForAddUserAndUpdatePrivs()
function PMA_getHtmlForAddUser($dbname)
{
$html_output = '<h2>' . "\n"
- . PMA_Util::getIcon('b_usradd.png') . __('Add user') . "\n"
+ . PMA_Util::getIcon('b_usradd.png') . __('Add user account') . "\n"
. '</h2>' . "\n"
. '<form name="usersForm" id="addUsersForm"'
. ' onsubmit="return checkAddUser(this);"'
@@ -1958,7 +2067,7 @@ function PMA_getHtmlForAddUser($dbname)
. PMA_getHtmlForLoginInformationFields('new');
$html_output .= '<fieldset id="fieldset_add_user_database">' . "\n"
- . '<legend>' . __('Database for user') . '</legend>' . "\n";
+ . '<legend>' . __('Database for user account') . '</legend>' . "\n";
$html_output .= PMA_Util::getCheckbox(
'createdb-1',
@@ -2079,7 +2188,9 @@ function PMA_getHtmlForSpecificDbPrivileges($db)
. ' '
. sprintf(
__('Users having access to "%s"'),
- '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
+ '<a href="' . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ )
. PMA_URL_getCommon(array('db' => $db)) . '">'
. htmlspecialchars($db)
. '</a>'
@@ -2093,7 +2204,7 @@ function PMA_getHtmlForSpecificDbPrivileges($db)
$html_output .= PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db);
$html_output .= '</table>';
- $html_output .= '<div style="float:left;">';
+ $html_output .= '<div class="floatleft">';
$html_output .= PMA_Util::getWithSelected(
$GLOBALS['pmaThemeImage'], $GLOBALS['text_dir'], "usersForm"
);
@@ -2143,7 +2254,9 @@ function PMA_getHtmlForSpecificTablePrivileges($db, $table)
. PMA_Util::getIcon('b_usrcheck.png')
. sprintf(
__('Users having access to "%s"'),
- '<a href="' . $GLOBALS['cfg']['DefaultTabTable']
+ '<a href="' . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
. PMA_URL_getCommon(
array(
'db' => $db,
@@ -2170,7 +2283,7 @@ function PMA_getHtmlForSpecificTablePrivileges($db, $table)
$html_output .= PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db);
$html_output .= '</table>';
- $html_output .= '<div style="float:left;">';
+ $html_output .= '<div class="floatleft">';
$html_output .= PMA_Util::getWithSelected(
$GLOBALS['pmaThemeImage'], $GLOBALS['text_dir'], "usersForm"
);
@@ -2253,8 +2366,8 @@ function PMA_getHtmlForPrivsTableHead()
return '<thead>'
. '<tr>'
. '<th></th>'
- . '<th>' . __('User') . '</th>'
- . '<th>' . __('Host') . '</th>'
+ . '<th>' . __('User name') . '</th>'
+ . '<th>' . __('Host name') . '</th>'
. '<th>' . __('Type') . '</th>'
. '<th>' . __('Privileges') . '</th>'
. '<th>' . __('Grant') . '</th>'
@@ -2302,8 +2415,7 @@ function PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db)
foreach ($privMap as $current_user => $val) {
foreach ($val as $current_host => $current_privileges) {
$nbPrivileges = count($current_privileges);
- $html_output .= '<tr class="noclick '
- . ($odd_row ? 'odd' : 'even') . '">';
+ $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">';
$value = htmlspecialchars($current_user . '&amp;#27;' . $current_host);
$html_output .= '<td';
@@ -2311,7 +2423,8 @@ function PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db)
$html_output .= ' rowspan="' . $nbPrivileges . '"';
}
$html_output .= '>';
- $html_output .= '<input type="checkbox" class="checkall" name="selected_usr[]" '
+ $html_output .= '<input type="checkbox" class="checkall" '
+ . 'name="selected_usr[]" '
. 'id="checkbox_sel_users_' . ($index_checkbox++) . '" '
. 'value="' . $value . '" /></td>' . "\n";
@@ -2512,7 +2625,7 @@ function PMA_getUserLink(
switch($linktype) {
case 'edit':
- $html .= PMA_Util::getIcon('b_usredit.png', __('Edit Privileges'));
+ $html .= PMA_Util::getIcon('b_usredit.png', __('Edit privileges'));
break;
case 'revoke':
$html .= PMA_Util::getIcon('b_usrdrop.png', __('Revoke'));
@@ -2531,7 +2644,7 @@ function PMA_getUserLink(
*
* @param string $username User name
*
- * @return HTML code with link
+ * @return string HTML code with link
*/
function PMA_getUserGroupEditLink($username)
{
@@ -2646,7 +2759,7 @@ function PMA_getExtraDataForAjaxBehavior(
. '</td>' . "\n";
}
- if (isset($cfgRelation['menuswork']) && $user_group_count > 0) {
+ if ($cfgRelation['menuswork'] && $user_group_count > 0) {
$new_user_string .= '<td>'
. PMA_getUserGroupEditLink($username)
. '</td>' . "\n";
@@ -2741,13 +2854,13 @@ function PMA_getChangeLoginInformationHtmlForm($username, $hostname)
. 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
. '<fieldset id="fieldset_change_copy_user">' . "\n"
. '<legend data-submenu-label="' . __('Login Information') . '">' . "\n"
- . __('Change Login Information / Copy User')
+ . __('Change login information / Copy user account')
. '</legend>' . "\n"
- . PMA_getHtmlForLoginInformationFields('change');
+ . PMA_getHtmlForLoginInformationFields('change', $username, $hostname);
$html_output .= '<fieldset id="fieldset_mode">' . "\n"
. ' <legend>'
- . __('Create a new user with the same privileges and …')
+ . __('Create a new user account with the same privileges and …')
. '</legend>' . "\n";
$html_output .= PMA_Util::getRadioFields(
'mode', $choices, '4', true
@@ -2777,7 +2890,9 @@ function PMA_getChangeLoginInformationHtmlForm($username, $hostname)
function PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename)
{
$html_output = '[ ' . __('Database')
- . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
+ . ' <a href="' . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ )
. PMA_URL_getCommon(
array(
'db' => $url_dbname,
@@ -2793,7 +2908,9 @@ function PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename)
if (/*overload*/mb_strlen($tablename)) {
$html_output .= ' [ ' . __('Table') . ' <a href="'
- . $GLOBALS['cfg']['DefaultTabTable']
+ . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
. PMA_URL_getCommon(
array(
'db' => $url_dbname,
@@ -2965,7 +3082,7 @@ function PMA_getHtmlForUserRights($db_rights, $dbname,
: __('No'))
. '</td>' . "\n"
. '<td>';
- if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
+ if (!empty($row['Table_privs']) || !empty($row['Column_priv'])) {
$html_output .= __('Yes');
} else {
$html_output .= __('No');
@@ -3212,7 +3329,7 @@ function PMA_getUsersOverview($result, $db_rights, $pmaThemeImage, $text_dir)
. '<thead>' . "\n"
. '<tr><th></th>' . "\n"
. '<th>' . __('User name') . '</th>' . "\n"
- . '<th>' . __('Host') . '</th>' . "\n"
+ . '<th>' . __('Host name') . '</th>' . "\n"
. '<th>' . __('Password') . '</th>' . "\n"
. '<th>' . __('Global privileges') . ' '
. PMA_Util::showHint(
@@ -3233,7 +3350,7 @@ function PMA_getUsersOverview($result, $db_rights, $pmaThemeImage, $text_dir)
$html_output .= '</tbody>'
. '</table>' . "\n";
- $html_output .= '<div style="float:left;">'
+ $html_output .= '<div class="floatleft">'
. PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "usersForm") . "\n";
$html_output .= PMA_Util::getButtonOrImage(
@@ -3303,7 +3420,31 @@ function PMA_getHtmlTableBodyForUserRights($db_rights)
. '<td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
$html_output .= '<td>';
- switch ($host['Password']) {
+
+ $password_column = 'Password';
+
+ if (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50606
+ && PMA_MYSQL_INT_VERSION < 50706
+ ) {
+ $check_plugin_query = "SELECT * FROM `mysql`.`user` WHERE "
+ . "`User` = '" . $host['User'] . "' AND `Host` = '"
+ . $host['Host'] . "'";
+ $res = $GLOBALS['dbi']->fetchSingleRow($check_plugin_query);
+ if (isset($res['plugin'])
+ && $res['plugin'] == 'sha256_password'
+ && isset($res['authentication_string'])
+ ) {
+ $password_column = 'authentication_string';
+ if (! empty($res['authentication_string'])) {
+ $host[$password_column] = 'Y';
+ } else {
+ $host[$password_column] = 'N';
+ }
+ }
+ }
+
+ switch ($host[$password_column]) {
case 'Y':
$html_output .= __('Yes');
break;
@@ -3316,6 +3457,7 @@ function PMA_getHtmlTableBodyForUserRights($db_rights)
$html_output .= '--'; // in future version, replace by "not present"
break;
} // end switch
+
$html_output .= '</td>' . "\n";
$html_output .= '<td><code>' . "\n"
@@ -3379,7 +3521,7 @@ function PMA_getFieldsetForAddDeleteUser()
$html_output .= '<fieldset id="fieldset_delete_user">'
. '<legend>' . "\n"
. PMA_Util::getIcon('b_usrdrop.png')
- . ' ' . __('Remove selected users') . '' . "\n"
+ . ' ' . __('Remove selected user accounts') . '' . "\n"
. '</legend>' . "\n";
$html_output .= '<input type="hidden" name="mode" value="2" />' . "\n"
@@ -3680,6 +3822,27 @@ function PMA_getDataForChangeOrCopyUser()
if (! isset($password) && isset($Password)) {
$password = $Password;
}
+ if (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50606
+ && PMA_MYSQL_INT_VERSION < 50706
+ && isset($password)
+ && empty($password)
+ && isset($plugin)
+ && $plugin == 'sha256_password'
+ ) {
+ $password = $authentication_string;
+ }
+
+ // Always use 'authentication_string' column
+ // for MySQL 5.7.6+ since it does not have
+ // the 'password' column at all
+ if (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50706
+ && isset($authentication_string)
+ ) {
+ $password = $authentication_string;
+ }
+
$queries = array();
}
}
@@ -3715,6 +3878,7 @@ function PMA_getDataForDeleteUsers($queries)
$queries[] = 'DROP USER \''
. PMA_Util::sqlAddSlashes($this_user)
. '\'@\'' . PMA_Util::sqlAddSlashes($this_host) . '\';';
+ PMA_relationsCleanupUser($this_user);
if (isset($_REQUEST['drop_users_db'])) {
$queries[] = 'DROP DATABASE IF EXISTS '
@@ -3795,79 +3959,140 @@ function PMA_addUser(
$queries_for_display = null;
$sql_query = null;
- if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
- $sql_query = '';
- if ($_POST['pred_username'] == 'any') {
- $username = '';
- }
- switch ($_POST['pred_hostname']) {
- case 'any':
- $hostname = '%';
- break;
- case 'localhost':
- $hostname = 'localhost';
- break;
- case 'hosttable':
- $hostname = '';
- break;
- case 'thishost':
- $_user_name = $GLOBALS['dbi']->fetchValue('SELECT USER()');
- $hostname = /*overload*/mb_substr(
- $_user_name,
- (/*overload*/mb_strrpos($_user_name, '@') + 1)
- );
- unset($_user_name);
- break;
- }
- $sql = "SELECT '1' FROM `mysql`.`user`"
- . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
- . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
- if ($GLOBALS['dbi']->fetchValue($sql) == 1) {
- $message = PMA_Message::error(__('The user %s already exists!'));
- $message->addParam(
- '[em]\'' . $username . '\'@\'' . $hostname . '\'[/em]'
- );
- $_REQUEST['adduser'] = true;
- $_add_user_error = true;
- } else {
- list($create_user_real, $create_user_show, $real_sql_query, $sql_query)
- = PMA_getSqlQueriesForDisplayAndAddUser(
- $username, $hostname, (isset ($password) ? $password : '')
- );
+ if (!isset($_REQUEST['adduser_submit']) && !isset($_REQUEST['change_copy'])) {
+ return array(
+ $message, $queries, $queries_for_display, $sql_query, $_add_user_error
+ );
+ }
- if (empty($_REQUEST['change_copy'])) {
- $_error = false;
+ if (!isset($_REQUEST['adduser_submit']) && !isset($_REQUEST['change_copy'])) {
+ return array(
+ $message,
+ $queries,
+ $queries_for_display,
+ $sql_query,
+ $_add_user_error
+ );
+ }
- if (isset($create_user_real)) {
- if (! $GLOBALS['dbi']->tryQuery($create_user_real)) {
- $_error = true;
- }
- $sql_query = $create_user_show . $sql_query;
- }
- list($sql_query, $message) = PMA_addUserAndCreateDatabase(
- $_error, $real_sql_query, $sql_query, $username, $hostname,
- isset($dbname) ? $dbname : null
- );
- if (! empty($_REQUEST['userGroup']) && $is_menuwork) {
- PMA_setUserGroup($GLOBALS['username'], $_REQUEST['userGroup']);
- }
+ $sql_query = '';
+ if ($_POST['pred_username'] == 'any') {
+ $username = '';
+ }
+ switch ($_POST['pred_hostname']) {
+ case 'any':
+ $hostname = '%';
+ break;
+ case 'localhost':
+ $hostname = 'localhost';
+ break;
+ case 'hosttable':
+ $hostname = '';
+ break;
+ case 'thishost':
+ $_user_name = $GLOBALS['dbi']->fetchValue('SELECT USER()');
+ $hostname = /*overload*/mb_substr(
+ $_user_name,
+ (/*overload*/mb_strrpos($_user_name, '@') + 1)
+ );
+ unset($_user_name);
+ break;
+ }
+ $sql = "SELECT '1' FROM `mysql`.`user`"
+ . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
+ . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
+ if ($GLOBALS['dbi']->fetchValue($sql) == 1) {
+ $message = PMA_Message::error(__('The user %s already exists!'));
+ $message->addParam(
+ '[em]\'' . $username . '\'@\'' . $hostname . '\'[/em]'
+ );
+ $_REQUEST['adduser'] = true;
+ $_add_user_error = true;
+
+ return array(
+ $message,
+ $queries,
+ $queries_for_display,
+ $sql_query,
+ $_add_user_error
+ );
+ }
- } else {
- if (isset($create_user_real)) {
- $queries[] = $create_user_real;
- }
- $queries[] = $real_sql_query;
- // we put the query containing the hidden password in
- // $queries_for_display, at the same position occupied
- // by the real query in $queries
- $tmp_count = count($queries);
- if (isset($create_user_real)) {
- $queries_for_display[$tmp_count - 2] = $create_user_show;
+ list(
+ $create_user_real, $create_user_show, $real_sql_query, $sql_query,
+ $password_set_real, $password_set_show
+ ) = PMA_getSqlQueriesForDisplayAndAddUser(
+ $username, $hostname, (isset($password) ? $password : '')
+ );
+
+ if (empty($_REQUEST['change_copy'])) {
+ $_error = false;
+
+ if (isset($create_user_real)) {
+ if (!$GLOBALS['dbi']->tryQuery($create_user_real)) {
+ $_error = true;
+ }
+ if (isset($password_set_real) && !empty($password_set_real)
+ && isset($_REQUEST['authentication_plugin'])
+ ) {
+ PMA_setProperPasswordHashing(
+ $_REQUEST['authentication_plugin']
+ );
+ if ($GLOBALS['dbi']->tryQuery($password_set_real)) {
+ $sql_query .= $password_set_show;
}
- $queries_for_display[$tmp_count - 1] = $sql_query;
}
- unset($real_sql_query);
+ $sql_query = $create_user_show . $sql_query;
+ }
+
+ list($sql_query, $message) = PMA_addUserAndCreateDatabase(
+ $_error,
+ $real_sql_query,
+ $sql_query,
+ $username,
+ $hostname,
+ isset($dbname) ? $dbname : null
+ );
+ if (!empty($_REQUEST['userGroup']) && $is_menuwork) {
+ PMA_setUserGroup($GLOBALS['username'], $_REQUEST['userGroup']);
}
+
+ return array(
+ $message,
+ $queries,
+ $queries_for_display,
+ $sql_query,
+ $_add_user_error
+ );
+ }
+
+ if (isset($create_user_real)) {
+ $queries[] = $create_user_real;
+ }
+ $queries[] = $real_sql_query;
+
+ if (isset($password_set_real) && ! empty($password_set_real)
+ && isset($_REQUEST['authentication_plugin'])
+ ) {
+ PMA_setProperPasswordHashing(
+ $_REQUEST['authentication_plugin']
+ );
+
+ $queries[] = $password_set_real;
+ }
+ // we put the query containing the hidden password in
+ // $queries_for_display, at the same position occupied
+ // by the real query in $queries
+ $tmp_count = count($queries);
+ if (isset($create_user_real)) {
+ $queries_for_display[$tmp_count - 2] = $create_user_show;
+ }
+ if (isset($password_set_real) && ! empty($password_set_real)) {
+ $queries_for_display[$tmp_count - 3] = $create_user_show;
+ $queries_for_display[$tmp_count - 2] = $sql_query;
+ $queries_for_display[$tmp_count - 1] = $password_set_show;
+ } else {
+ $queries_for_display[$tmp_count - 1] = $sql_query;
}
return array(
@@ -3876,6 +4101,25 @@ function PMA_addUser(
}
/**
+ * Sets proper value of `old_passwords` according to
+ * the authentication plugin selected
+ *
+ * @param string $auth_plugin authentication plugin selected
+ *
+ * @return void
+ */
+function PMA_setProperPasswordHashing($auth_plugin)
+{
+ // Set the hashing method used by PASSWORD()
+ // to be of type depending upon $authentication_plugin
+ if ($auth_plugin == 'sha256_password') {
+ $GLOBALS['dbi']->tryQuery('SET `old_passwords` = 2');
+ } else {
+ $GLOBALS['dbi']->tryQuery('SET `old_passwords` = 0');
+ }
+}
+
+/**
* Update DB information: DB, Table, isWildcard
*
* @return array
@@ -3888,10 +4132,10 @@ function PMA_getDataForDBInfo()
$tablename = null;
$dbname_is_wildcard = null;
- if (isset ($_REQUEST['username'])) {
+ if (isset($_REQUEST['username'])) {
$username = $_REQUEST['username'];
}
- if (isset ($_REQUEST['hostname'])) {
+ if (isset($_REQUEST['hostname'])) {
$hostname = $_REQUEST['hostname'];
}
/**
@@ -3998,8 +4242,7 @@ function PMA_getDataForDBInfo()
*/
function PMA_getListForExportUserDefinition($username, $hostname)
{
- $export = '<textarea class="export" cols="' . $GLOBALS['cfg']['TextareaCols']
- . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
+ $export = '<textarea class="export" cols="60" rows="15">';
if (isset($_REQUEST['selected_usr'])) {
// export privileges for selected users
@@ -4072,7 +4315,7 @@ function PMA_getAddUserHtmlFieldset($db = '', $table = '')
: '')
. '>' . "\n"
. PMA_Util::getIcon('b_usradd.png')
- . ' ' . __('Add user') . '</a>' . "\n"
+ . ' ' . __('Add user account') . '</a>' . "\n"
. '</fieldset>' . "\n";
}
@@ -4093,8 +4336,8 @@ function PMA_getHtmlHeaderForUserProperties(
) {
$html_output = '<h2>' . "\n"
. PMA_Util::getIcon('b_usredit.png')
- . __('Edit Privileges:') . ' '
- . __('User');
+ . __('Edit privileges:') . ' '
+ . __('User account');
if (! empty($dbname)) {
$html_output .= ' <i><a class="edit_user_anchor"'
@@ -4173,11 +4416,11 @@ function PMA_getHtmlForUserOverview($pmaThemeImage, $text_dir)
{
$html_output = '<h2>' . "\n"
. PMA_Util::getIcon('b_usrlist.png')
- . __('Users overview') . "\n"
+ . __('User accounts overview') . "\n"
. '</h2>' . "\n";
$password_column = 'Password';
- if (PMA_Util::getServerType() == 'MySQL'
+ if (PMA_Util::getServerType() == 'MySQL'
&& PMA_MYSQL_INT_VERSION >= 50706
) {
$password_column = 'authentication_string';
@@ -4236,6 +4479,23 @@ function PMA_getHtmlForUserOverview($pmaThemeImage, $text_dir)
// for all initials, even non A-Z
$array_initials = array();
+ foreach ($db_rights as $right) {
+ foreach ($right as $account) {
+ if (empty($account['User']) && $account['Host'] == 'localhost') {
+ $html_output .= PMA_Message::notice(
+ __(
+ 'A user account allowing any user from localhost to '
+ . 'connect is present. This will prevent other users '
+ . 'from connecting if the host part of their account '
+ . 'allows a connection from any (%) host.'
+ )
+ . PMA_Util::showMySQLDocu('problems-connecting')
+ )->getDisplay();
+ break 2;
+ }
+ }
+ }
+
/**
* Displays the initials
* Also not necessary if there is less than 20 privileges
@@ -4262,24 +4522,43 @@ function PMA_getHtmlForUserOverview($pmaThemeImage, $text_dir)
if (! $GLOBALS['is_ajax_request']
|| ! empty($_REQUEST['ajax_page_request'])
) {
- $flushnote = new PMA_Message(
- __(
- 'Note: phpMyAdmin gets the users\' privileges directly '
- . 'from MySQL\'s privilege tables. The content of these tables '
- . 'may differ from the privileges the server uses, '
- . 'if they have been changed manually. In this case, '
- . 'you should %sreload the privileges%s before you continue.'
- ),
- PMA_Message::NOTICE
- );
- $flushLink = '<a href="server_privileges.php'
- . PMA_URL_getCommon(array('flush_privileges' => 1))
- . '" id="reload_privileges_anchor">';
- $flushnote->addParam(
- $flushLink,
- false
- );
- $flushnote->addParam('</a>', false);
+ if (isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']) {
+ $flushnote = new PMA_Message(
+ __(
+ 'Note: phpMyAdmin gets the users\' privileges directly '
+ . 'from MySQL\'s privilege tables. The content of these '
+ . 'tables may differ from the privileges the server uses, '
+ . 'if they have been changed manually. In this case, '
+ . 'you should %sreload the privileges%s before you continue.'
+ ),
+ PMA_Message::NOTICE
+ );
+ $flushLink = '<a href="server_privileges.php'
+ . PMA_URL_getCommon(array('flush_privileges' => 1))
+ . '" id="reload_privileges_anchor">';
+ $flushnote->addParam(
+ $flushLink,
+ false
+ );
+ $flushnote->addParam('</a>', false);
+ } else {
+ $flushnote = new PMA_Message(
+ __(
+ 'Note: phpMyAdmin gets the users\' privileges directly '
+ . 'from MySQL\'s privilege tables. The content of these '
+ . 'tables may differ from the privileges the server uses, '
+ . 'if they have been changed manually. In this case, '
+ . 'the privileges have to be reloaded but currently, you '
+ . 'don\'t have the RELOAD privilege.'
+ )
+ . PMA_Util::showMySQLDocu(
+ 'privileges-provided',
+ false,
+ 'priv_reload'
+ ),
+ PMA_Message::NOTICE
+ );
+ }
$html_output .= $flushnote->getDisplay();
}
}
@@ -4618,42 +4897,108 @@ function PMA_addUserAndCreateDatabase($_error, $real_sql_query, $sql_query,
* @param string $hostname host name
* @param string $password password
*
- * @return array ($create_user_real, $create_user_show,$real_sql_query, $sql_query)
+ * @return array ($create_user_real, $create_user_show,$real_sql_query, $sql_query
+ * $password_set_real, $password_set_show)
*/
function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password)
{
- $create_user_real = 'CREATE USER \''
- . PMA_Util::sqlAddSlashes($username) . '\'@\''
- . PMA_Util::sqlAddSlashes($hostname) . '\'';
+ $slashedUsername = PMA_Util::sqlAddSlashes($username);
+ $slashedHostname = PMA_Util::sqlAddSlashes($hostname);
+ $slashedPassword = PMA_Util::sqlAddSlashes($password);
+
+ $create_user_stmt = sprintf(
+ 'CREATE USER \'%s\'@\'%s\'',
+ $slashedUsername,
+ $slashedHostname
+ );
- $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
- . PMA_Util::sqlAddSlashes($username) . '\'@\''
- . PMA_Util::sqlAddSlashes($hostname) . '\'';
-
- if ($_POST['pred_password'] != 'none' && $_POST['pred_password'] != 'keep') {
- $sql_query = $real_sql_query;
- // Requires SELECT privilege on mysql database
- // for using this with GRANT queries. It can be skipped.
- if ($GLOBALS['is_superuser']) {
- $sql_query .= ' IDENTIFIED BY \'***\'';
- $real_sql_query .= ' IDENTIFIED BY \''
- . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
- }
- if (isset($create_user_real)) {
- $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
- $create_user_real .= ' IDENTIFIED BY \''
- . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
+ if (PMA_MYSQL_INT_VERSION >= 50507
+ && isset($_REQUEST['authentication_plugin'])
+ ) {
+ $create_user_stmt .= ' IDENTIFIED WITH '
+ . $_REQUEST['authentication_plugin'];
+ }
+ if (PMA_MYSQL_INT_VERSION >= 50707
+ && strpos($create_user_stmt, '%') !== false
+ ) {
+ $create_user_stmt = str_replace(
+ '%', '%%', $create_user_stmt
+ );
+ }
+ $create_user_real = $create_user_show = $create_user_stmt;
+
+ $password_set_stmt = 'SET PASSWORD FOR \'%s\'@\'%s\' = PASSWORD(\'%s\')';
+ $password_set_show = sprintf(
+ $password_set_stmt,
+ $slashedUsername,
+ $slashedHostname,
+ '***'
+ );
+ $password_set_real = null;
+
+ $sql_query_stmt = sprintf(
+ 'GRANT %s ON *.* TO \'%s\'@\'%s\'',
+ join(', ', PMA_extractPrivInfo()),
+ $slashedUsername,
+ $slashedHostname
+ );
+ $real_sql_query = $sql_query = $sql_query_stmt;
+
+ if (PMA_MYSQL_INT_VERSION < 50707) {
+ if ($_POST['pred_password'] == 'keep') {
+ $password_set_real = sprintf(
+ $password_set_stmt,
+ $slashedUsername,
+ $slashedHostname,
+ $slashedPassword
+ );
+ } else if ($_POST['pred_password'] == 'none') {
+ $password_set_real = sprintf(
+ $password_set_stmt,
+ $slashedUsername,
+ $slashedHostname,
+ null
+ );
+ } else {
+ $password_set_real = sprintf(
+ $password_set_stmt,
+ $slashedUsername,
+ $slashedHostname,
+ $_POST['pma_pw']
+ );
}
} else {
- if ($_POST['pred_password'] == 'keep' && ! empty($password)) {
- $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
- if (isset($create_user_real)) {
- $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
- }
- }
- $sql_query = $real_sql_query;
- if (isset($create_user_real)) {
- $create_user_show = $create_user_real;
+ $password_set_real = null;
+ $create_user_stmt .= ' BY \'%s\'';
+ $create_user_real = $create_user_show = $create_user_stmt;
+
+ if ($_POST['pred_password'] == 'keep') {
+ $create_user_real = sprintf(
+ $create_user_stmt,
+ $password
+ );
+ $create_user_show = sprintf(
+ $create_user_stmt,
+ '***'
+ );
+ } else if ($_POST['pred_password'] == 'none') {
+ $create_user_real = sprintf(
+ $create_user_stmt,
+ null
+ );
+ $create_user_show = sprintf(
+ $create_user_stmt,
+ '***'
+ );
+ } else {
+ $create_user_real = sprintf(
+ $create_user_stmt,
+ $_POST['pma_pw']
+ );
+ $create_user_show = sprintf(
+ $create_user_stmt,
+ '***'
+ );
}
}
@@ -4683,10 +5028,21 @@ function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password)
$sql_query = '';
}
+ if (PMA_Util::getServerType() == 'MySQL'
+ && PMA_MYSQL_INT_VERSION >= 50700
+ ) {
+ $password_set_real = null;
+ $password_set_show = null;
+ } else {
+ $password_set_real .= ";";
+ $password_set_show .= ";";
+ }
+
return array($create_user_real,
$create_user_show,
$real_sql_query,
- $sql_query
+ $sql_query,
+ $password_set_real,
+ $password_set_show
);
}
-?>
diff --git a/libraries/server_status.lib.php b/libraries/server_status.lib.php
index dd1fd72352..824bdfe50d 100644
--- a/libraries/server_status.lib.php
+++ b/libraries/server_status.lib.php
@@ -30,6 +30,13 @@ function PMA_getHtmlForServerStatus($ServerStatusData)
//display the server state connection information
$retval .= PMA_getHtmlForServerStateConnections($ServerStatusData);
+ // display replication information
+ if ($GLOBALS['replication_info']['master']['status']
+ || $GLOBALS['replication_info']['slave']['status']
+ ) {
+ $retval .= PMA_getHtmlForReplicationInfo();
+ }
+
return $retval;
}
@@ -69,48 +76,50 @@ function PMA_getHtmlForServerStateGeneralInfo($ServerStatusData)
) . "\n";
$retval .= '</p>';
+ return $retval;
+}
+
+/**
+ * Returns HTML to display replication information
+ *
+ * @return string HTML on replication
+ */
+function PMA_getHtmlForReplicationInfo()
+{
+ $retval = '<p class="notice clearfloat">';
if ($GLOBALS['replication_info']['master']['status']
- || $GLOBALS['replication_info']['slave']['status']
+ && $GLOBALS['replication_info']['slave']['status']
) {
- $retval .= '<p class="notice">';
- if ($GLOBALS['replication_info']['master']['status']
- && $GLOBALS['replication_info']['slave']['status']
- ) {
- $retval .= __(
- 'This MySQL server works as <b>master</b> and '
- . '<b>slave</b> in <b>replication</b> process.'
- );
- } elseif ($GLOBALS['replication_info']['master']['status']) {
- $retval .= __(
- 'This MySQL server works as <b>master</b> '
- . 'in <b>replication</b> process.'
- );
- } elseif ($GLOBALS['replication_info']['slave']['status']) {
- $retval .= __(
- 'This MySQL server works as <b>slave</b> '
- . 'in <b>replication</b> process.'
- );
- }
- $retval .= '</p>';
+ $retval .= __(
+ 'This MySQL server works as <b>master</b> and '
+ . '<b>slave</b> in <b>replication</b> process.'
+ );
+ } elseif ($GLOBALS['replication_info']['master']['status']) {
+ $retval .= __(
+ 'This MySQL server works as <b>master</b> '
+ . 'in <b>replication</b> process.'
+ );
+ } elseif ($GLOBALS['replication_info']['slave']['status']) {
+ $retval .= __(
+ 'This MySQL server works as <b>slave</b> '
+ . 'in <b>replication</b> process.'
+ );
}
+ $retval .= '</p>';
/*
* if the server works as master or slave in replication process,
* display useful information
*/
- if ($GLOBALS['replication_info']['master']['status']
- || $GLOBALS['replication_info']['slave']['status']
- ) {
- $retval .= '<hr class="clearfloat" />';
- $retval .= '<h3><a name="replication">';
- $retval .= __('Replication status');
- $retval .= '</a></h3>';
- foreach ($GLOBALS['replication_types'] as $type) {
- if (isset($GLOBALS['replication_info'][$type]['status'])
- && $GLOBALS['replication_info'][$type]['status']
- ) {
- $retval .= PMA_getHtmlForReplicationStatusTable($type);
- }
+ $retval .= '<hr class="clearfloat" />';
+ $retval .= '<h3><a name="replication">';
+ $retval .= __('Replication status');
+ $retval .= '</a></h3>';
+ foreach ($GLOBALS['replication_types'] as $type) {
+ if (isset($GLOBALS['replication_info'][$type]['status'])
+ && $GLOBALS['replication_info'][$type]['status']
+ ) {
+ $retval .= PMA_getHtmlForReplicationStatusTable($type);
}
}
@@ -130,7 +139,7 @@ function PMA_getHtmlForServerStateTraffic($ServerStatusData)
$retval = '<table id="serverstatustraffic" class="data noclick">';
$retval .= '<thead>';
$retval .= '<tr>';
- $retval .= '<th colspan="2">';
+ $retval .= '<th>';
$retval .= __('Traffic') . '&nbsp;';
$retval .= PMA_Util::showHint(
__(
@@ -139,6 +148,7 @@ function PMA_getHtmlForServerStateTraffic($ServerStatusData)
)
);
$retval .= '</th>';
+ $retval .= '<th>#</th>';
$retval .= '<th>&oslash; ' . __('per hour') . '</th>';
$retval .= '</tr>';
$retval .= '</thead>';
@@ -222,14 +232,15 @@ function PMA_getHtmlForServerStateConnections($ServerStatusData)
$retval = '<table id="serverstatusconnections" class="data noclick">';
$retval .= '<thead>';
$retval .= '<tr>';
- $retval .= '<th colspan="2">' . __('Connections') . '</th>';
+ $retval .= '<th>' . __('Connections') . '</th>';
+ $retval .= '<th>#</th>';
$retval .= '<th>&oslash; ' . __('per hour') . '</th>';
$retval .= '<th>%</th>';
$retval .= '</tr>';
$retval .= '</thead>';
$retval .= '<tbody>';
$retval .= '<tr class="odd">';
- $retval .= '<th class="name">' . __('max. concurrent connections') . '</th>';
+ $retval .= '<th class="name">' . __('Max. concurrent connections') . '</th>';
$retval .= '<td class="value">';
$retval .= PMA_Util::formatNumber(
$ServerStatusData->status['Max_used_connections'], 0
@@ -314,4 +325,3 @@ function PMA_getHtmlForServerStateConnections($ServerStatusData)
return $retval;
}
-?>
diff --git a/libraries/server_status_advisor.lib.php b/libraries/server_status_advisor.lib.php
index acb2a542d7..b9da47896f 100644
--- a/libraries/server_status_advisor.lib.php
+++ b/libraries/server_status_advisor.lib.php
@@ -65,4 +65,3 @@ function PMA_getHtmlForAdvisor()
return $output;
}
-?>
diff --git a/libraries/server_status_monitor.lib.php b/libraries/server_status_monitor.lib.php
index 1f3466b17e..3cee3a17e4 100644
--- a/libraries/server_status_monitor.lib.php
+++ b/libraries/server_status_monitor.lib.php
@@ -40,7 +40,7 @@ function PMA_getHtmlForMonitor($ServerStatusData)
$retval .= '<script type="text/javascript">';
$retval .= 'variableNames = [ ';
- $i=0;
+ $i = 0;
foreach ($ServerStatusData->status as $name=>$value) {
if (is_numeric($value)) {
if ($i++ > 0) {
@@ -230,7 +230,7 @@ function PMA_getHtmlForAddChartDialog()
$retval .= ' | <a href="#submitClearSeries">' . __('Clear series') . '</a>';
$retval .= '</span>';
$retval .= '</p>';
- $retval .= __('Series in Chart:');
+ $retval .= __('Series in chart:');
$retval .= '<br/>';
$retval .= '<span id="seriesPreview">';
$retval .= '<i>' . __('None') . '</i>';
@@ -822,4 +822,3 @@ function PMA_getJsonForQueryAnalyzer()
return $return;
}
-?>
diff --git a/libraries/server_status_processes.lib.php b/libraries/server_status_processes.lib.php
index 95e8b82136..a5cdf73e77 100644
--- a/libraries/server_status_processes.lib.php
+++ b/libraries/server_status_processes.lib.php
@@ -13,11 +13,11 @@ if (! defined('PHPMYADMIN')) {
}
/**
- * Prints html for server status processes
+ * Prints html for auto refreshing processes list
*
* @return string
*/
-function PMA_getHtmlForServerProcesses()
+function PMA_getHtmlForProcessListAutoRefresh()
{
$notice = PMA_Message::notice(
__(
@@ -37,7 +37,6 @@ function PMA_getHtmlForServerProcesses()
$retval .= PMA_Util::getImage('play.png') . __('Start auto refresh');
$retval .= '</a>';
$retval .= '</div>';
- $retval .= PMA_getHtmlForServerProcesslist();
return $retval;
}
@@ -94,6 +93,10 @@ function PMA_getHtmlForServerProcesslist()
'order_by_field' => 'State'
),
array(
+ 'column_name' => __('Progress'),
+ 'order_by_field' => 'Progress'
+ ),
+ array(
'column_name' => __('SQL query'),
'order_by_field' => 'Info'
)
@@ -116,6 +119,9 @@ function PMA_getHtmlForServerProcesslist()
. ($show_full_sql
? 'LEFT JOIN data_dictionary.SESSIONS s ON s.session_id = p.id'
: '');
+ if (! empty($_REQUEST['showExecuting'])) {
+ $sql_query .= ' WHERE p.state = "executing" ';
+ }
if (! empty($_REQUEST['order_by_field'])
&& ! empty($_REQUEST['sort_order'])
) {
@@ -126,16 +132,16 @@ function PMA_getHtmlForServerProcesslist()
$sql_query = $show_full_sql
? 'SHOW FULL PROCESSLIST'
: 'SHOW PROCESSLIST';
- if ( (! empty($_REQUEST['order_by_field'])
- && ! empty($_REQUEST['sort_order']) )
- || (! empty($_REQUEST['showExecuting']) )
+ if ((! empty($_REQUEST['order_by_field'])
+ && ! empty($_REQUEST['sort_order']))
+ || (! empty($_REQUEST['showExecuting']))
) {
$sql_query = 'SELECT * FROM `INFORMATION_SCHEMA`.`PROCESSLIST` ';
}
if (! empty($_REQUEST['showExecuting'])) {
$sql_query .= ' WHERE state = "executing" ';
}
- if (! empty($_REQUEST['order_by_field']) && ! empty($_REQUEST['sort_order']) ) {
+ if (!empty($_REQUEST['order_by_field']) && !empty($_REQUEST['sort_order'])) {
$sql_query .= ' ORDER BY '
. PMA_Util::backquote($_REQUEST['order_by_field'])
. ' ' . $_REQUEST['sort_order'];
@@ -244,10 +250,12 @@ function PMA_getHtmlForProcessListFilter()
$retval = '';
$retval .= '<fieldset id="tableFilter">';
$retval .= '<legend>' . __('Filters') . '</legend>';
- $retval .= '<form action="server_status_processes.php' . PMA_URL_getCommon($url_params) . '">';
+ $retval .= '<form action="server_status_processes.php'
+ . PMA_URL_getCommon($url_params) . '">';
$retval .= '<input type="submit" value="' . __('Refresh') . '" />';
$retval .= '<div class="formelement">';
- $retval .= '<input' . $showExecuting . ' type="checkbox" name="showExecuting" id="showExecuting" />';
+ $retval .= '<input' . $showExecuting . ' type="checkbox" name="showExecuting"'
+ . ' id="showExecuting" class="autosubmit"/>';
$retval .= '<label for="showExecuting">';
$retval .= __('Show only active');
$retval .= '</label>';
@@ -271,7 +279,7 @@ function PMA_getHtmlForServerProcessItem($process, $odd_row, $show_full_sql)
{
// Array keys need to modify due to the way it has used
// to display column values
- if ( (! empty($_REQUEST['order_by_field']) && ! empty($_REQUEST['sort_order']) )
+ if ((! empty($_REQUEST['order_by_field']) && ! empty($_REQUEST['sort_order']))
|| (! empty($_REQUEST['showExecuting']))
) {
foreach (array_keys($process) as $key) {
@@ -303,6 +311,8 @@ function PMA_getHtmlForServerProcessItem($process, $odd_row, $show_full_sql)
$retval .= '<td class="value">' . $process['Time'] . '</td>';
$processStatusStr = empty($process['State']) ? '---' : $process['State'];
$retval .= '<td>' . $processStatusStr . '</td>';
+ $processProgress = empty($process['Progress']) ? '---' : $process['Progress'];
+ $retval .= '<td>' . $processProgress . '</td>';
$retval .= '<td>';
if (empty($process['Info'])) {
@@ -316,4 +326,3 @@ function PMA_getHtmlForServerProcessItem($process, $odd_row, $show_full_sql)
return $retval;
}
-?>
diff --git a/libraries/server_status_queries.lib.php b/libraries/server_status_queries.lib.php
index 6d049b3815..fc84d084ef 100644
--- a/libraries/server_status_queries.lib.php
+++ b/libraries/server_status_queries.lib.php
@@ -151,4 +151,3 @@ function PMA_getHtmlForServerStatusQueriesDetails($ServerStatusData)
return $retval;
}
-?>
diff --git a/libraries/server_status_variables.lib.php b/libraries/server_status_variables.lib.php
index 29e4ba914e..e432209c5b 100644
--- a/libraries/server_status_variables.lib.php
+++ b/libraries/server_status_variables.lib.php
@@ -57,7 +57,7 @@ function PMA_getHtmlForFilter($ServerStatusData)
$retval .= '<option value="">' . __('Filter by category…') . '</option>';
foreach ($ServerStatusData->sections as $section_id => $section_name) {
- if (isset($ServerStatusData->categoryUsed[$section_id])) {
+ if (isset($ServerStatusData->sectionUsed[$section_id])) {
if (! empty($_REQUEST['filterCategory'])
&& $_REQUEST['filterCategory'] == $section_id
) {
@@ -98,7 +98,7 @@ function PMA_getHtmlForLinkSuggestions($ServerStatusData)
$retval .= '<p class="notice">' . __('Related links:');
foreach ($ServerStatusData->links as $section_name => $section_links) {
$retval .= '<span class="status_' . $section_name . '"> ';
- $i=0;
+ $i = 0;
foreach ($section_links as $link_name => $link_url) {
if ($i > 0) {
$retval .= ', ';
@@ -762,4 +762,3 @@ function PMA_getStatusVariablesDescriptions()
);
}
-?>
diff --git a/libraries/server_user_groups.lib.php b/libraries/server_user_groups.lib.php
index d3ec9c340a..995b5ccff6 100644
--- a/libraries/server_user_groups.lib.php
+++ b/libraries/server_user_groups.lib.php
@@ -227,8 +227,8 @@ function PMA_getHtmlToEditUserGroup($userGroup = null)
$html_output .= '<fieldset id="fieldset_user_group_rights">';
$html_output .= '<legend>' . __('User group menu assignments')
. '&nbsp;&nbsp;&nbsp;'
- . '<input type="checkbox" class="checkall_box" title="Check All">'
- . '<label for="addUsersForm_checkall">' . __('Check All') . '</label>'
+ . '<input type="checkbox" class="checkall_box" title="Check all">'
+ . '<label for="addUsersForm_checkall">' . __('Check all') . '</label>'
. '</legend>';
if ($userGroup == null) {
@@ -357,4 +357,3 @@ function PMA_editUserGroup($userGroup, $new = false)
$sql_query .= ";";
PMA_queryAsControlUser($sql_query, true);
}
-?>
diff --git a/libraries/server_users.lib.php b/libraries/server_users.lib.php
index 807eaa19b8..09b72d7818 100644
--- a/libraries/server_users.lib.php
+++ b/libraries/server_users.lib.php
@@ -22,7 +22,7 @@ function PMA_getHtmlForSubMenusOnUsersPage($selfUrl)
$url_params = PMA_URL_getCommon();
$items = array(
array(
- 'name' => __('Users overview'),
+ 'name' => __('User accounts overview'),
'url' => 'server_privileges.php',
'specific_params' => '&viewing_mode=server'
)
@@ -55,4 +55,3 @@ function PMA_getHtmlForSubMenusOnUsersPage($selfUrl)
return $retval;
}
-?> \ No newline at end of file
diff --git a/libraries/server_variables.lib.php b/libraries/server_variables.lib.php
index 30a81eb77c..ec9164313b 100644
--- a/libraries/server_variables.lib.php
+++ b/libraries/server_variables.lib.php
@@ -167,11 +167,14 @@ function PMA_getHtmlForLinkTemplates()
* Prints Html for Server Variables
*
* @param Array $variable_doc_links documentation links
+ * @param Array $serverVars global variables
+ * @param Array $serverVarsSession session variables
*
* @return string
*/
-function PMA_getHtmlForServerVariables($variable_doc_links)
-{
+function PMA_getHtmlForServerVariables(
+ $variable_doc_links, $serverVars, $serverVarsSession
+) {
$value = ! empty($_REQUEST['filter'])
? htmlspecialchars($_REQUEST['filter'])
: '';
@@ -194,7 +197,9 @@ function PMA_getHtmlForServerVariables($variable_doc_links)
. '</tr>'
. '</thead>';
- $output .= PMA_getHtmlForServerVariablesItems($variable_doc_links);
+ $output .= PMA_getHtmlForServerVariablesItems(
+ $variable_doc_links, $serverVars, $serverVarsSession
+ );
$output .= '</table>';
@@ -206,17 +211,16 @@ function PMA_getHtmlForServerVariables($variable_doc_links)
* Prints Html for Server Variables Items
*
* @param Array $variable_doc_links documentation links
+ * @param Array $serverVars global variables
+ * @param Array $serverVarsSession session variables
*
* @return string
*/
-function PMA_getHtmlForServerVariablesItems($variable_doc_links)
-{
- /**
- * Sends the queries and buffers the results
- */
- $serverVarsSession
- = $GLOBALS['dbi']->fetchResult('SHOW SESSION VARIABLES;', 0, 1);
- $serverVars = $GLOBALS['dbi']->fetchResult('SHOW GLOBAL VARIABLES;', 0, 1);
+function PMA_getHtmlForServerVariablesItems(
+ $variable_doc_links, $serverVars, $serverVarsSession
+) {
+ // list of static system variables
+ $static_variables = PMA_getStaticSystemVariables();
$output = '<tbody>';
$odd_row = true;
@@ -229,8 +233,19 @@ function PMA_getHtmlForServerVariablesItems($variable_doc_links)
$output .= '<tr class="var-row' . $row_class . '">';
$output .= '<td class="var-action">';
- $output .= '<a href="#" class="editLink">'
- . PMA_Util::getIcon('b_edit.png', __('Edit')) . '</a>';
+
+ // Edit Link active only for Dynamic System variables
+ if (! in_array(strtolower($name), $static_variables)) {
+ $output .= '<a href="#" class="editLink">'
+ . PMA_Util::getIcon('b_edit.png', __('Edit')) . '</a>';
+ } else {
+ $output .= '<span title="'
+ . __('This is a read-only variable and can not be edited')
+ . '" class="read_only_var" >'
+ . PMA_Util::getIcon('bd_edit.png', __('Edit'))
+ . '</span>';
+ }
+
$output .= '</td>';
$output .= '<td class="var-name">';
@@ -282,9 +297,11 @@ function PMA_getHtmlForServerVariablesItems($variable_doc_links)
* Returns Array of documentation links
*
* $variable_doc_links[string $name] = array(
+ * string $name,
* string $anchor,
* string $chapter,
- * string $type);
+ * string $type,
+ * string $format);
* string $name: name of the system variable
* string $anchor: anchor to the documentation page
* string $chapter: chapter of "HTML, one page per chapter" documentation
@@ -334,6 +351,10 @@ function PMA_getArrayForDocumentLinks()
'replication-options-binary-log',
'sysvar',
'byte');
+ $variable_doc_links['binlog_checksum'] = array(
+ 'binlog_checksum',
+ 'replication-options-binary-log',
+ 'sysvar');
$variable_doc_links['binlog_direct_non_transactional_updates'] = array(
'binlog_direct_non_transactional_updates',
'replication-options-binary-log',
@@ -342,11 +363,31 @@ function PMA_getArrayForDocumentLinks()
'binlog-format',
'server-options',
'sysvar');
+ $variable_doc_links['binlog_max_flush_queue_time'] = array(
+ 'binlog_max_flush_queue_time',
+ 'replication-options-binary-log',
+ 'sysvar');
+ $variable_doc_links['binlog_order_commits'] = array(
+ 'binlog_order_commits',
+ 'replication-options-binary-log',
+ 'sysvar');
+ $variable_doc_links['binlog_row_image'] = array(
+ 'binlog_row_image',
+ 'replication-options-binary-log',
+ 'sysvar');
+ $variable_doc_links['binlog_rows_query_log_events'] = array(
+ 'binlog_rows_query_log_events',
+ 'replication-options-binary-log',
+ 'sysvar');
$variable_doc_links['binlog_stmt_cache_size'] = array(
'binlog_stmt_cache_size',
'replication-options-binary-log',
'sysvar',
'byte');
+ $variable_doc_links['block_encryption_mode'] = array(
+ 'block_encryption_mode',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['bulk_insert_buffer_size'] = array(
'bulk_insert_buffer_size',
'server-system-variables',
@@ -408,6 +449,10 @@ function PMA_getArrayForDocumentLinks()
'connect_timeout',
'server-system-variables',
'sysvar');
+ $variable_doc_links['core_file'] = array(
+ 'core_file',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['datadir'] = array(
'datadir',
'server-options',
@@ -432,6 +477,10 @@ function PMA_getArrayForDocumentLinks()
'default-storage-engine',
'server-options',
'option_mysqld');
+ $variable_doc_links['default_tmp_storage_engine'] = array(
+ 'default_tmp_storage_engine',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['default_week_format'] = array(
'default_week_format',
'server-system-variables',
@@ -452,10 +501,26 @@ function PMA_getArrayForDocumentLinks()
'delayed_queue_size',
'server-system-variables',
'sysvar');
+ $variable_doc_links['disconnect_on_expired_password'] = array(
+ 'disconnect_on_expired_password',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['div_precision_increment'] = array(
'div_precision_increment',
'server-system-variables',
'sysvar');
+ $variable_doc_links['end_markers_in_json'] = array(
+ 'end_markers_in_json',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['enforce_gtid_consistency'] = array(
+ 'enforce_gtid_consistency',
+ 'replication-options-gtids',
+ 'sysvar');
+ $variable_doc_links['eq_range_index_dive_limit'] = array(
+ 'eq_range_index_dive_limit',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['engine_condition_pushdown'] = array(
'engine-condition-pushdown',
'server-options',
@@ -472,6 +537,10 @@ function PMA_getArrayForDocumentLinks()
'expire_logs_days',
'server-system-variables',
'sysvar');
+ $variable_doc_links['explicit_defaults_for_timestamp'] = array(
+ 'explicit_defaults_for_timestamp',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['external_user'] = array(
'external_user',
'server-system-variables',
@@ -520,6 +589,22 @@ function PMA_getArrayForDocumentLinks()
'group_concat_max_len',
'server-system-variables',
'sysvar');
+ $variable_doc_links['gtid_executed'] = array(
+ 'gtid_executed',
+ 'replication-options-gtids',
+ 'sysvar');
+ $variable_doc_links['gtid_mode'] = array(
+ 'gtid_mode',
+ 'replication-options-gtids',
+ 'sysvar');
+ $variable_doc_links['gtid_owned'] = array(
+ 'gtid_owned',
+ 'replication-options-gtids',
+ 'sysvar');
+ $variable_doc_links['gtid_purged'] = array(
+ 'gtid_purged',
+ 'replication-options-gtids',
+ 'sysvar');
$variable_doc_links['have_compress'] = array(
'have_compress',
'server-system-variables',
@@ -544,6 +629,10 @@ function PMA_getArrayForDocumentLinks()
'have_innodb',
'server-system-variables',
'sysvar');
+ $variable_doc_links['have_ndbcluster'] = array(
+ 'have_ndbcluster',
+ 'mysql-cluster-system-variables',
+ 'sysvar');
$variable_doc_links['have_openssl'] = array(
'have_openssl',
'server-system-variables',
@@ -572,6 +661,10 @@ function PMA_getArrayForDocumentLinks()
'have_symlink',
'server-system-variables',
'sysvar');
+ $variable_doc_links['host_cache_size'] = array(
+ 'host_cache_size',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['hostname'] = array(
'hostname',
'server-system-variables',
@@ -584,6 +677,10 @@ function PMA_getArrayForDocumentLinks()
'ignore-builtin-innodb',
'innodb-parameters',
'option_mysqld');
+ $variable_doc_links['ignore_db_dirs'] = array(
+ 'ignore_db_dirs',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['init_connect'] = array(
'init_connect',
'server-system-variables',
@@ -600,15 +697,43 @@ function PMA_getArrayForDocumentLinks()
'innodb_adaptive_flushing',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_adaptive_flushing_lwm'] = array(
+ 'innodb_adaptive_flushing_lwm',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_adaptive_hash_index'] = array(
'innodb_adaptive_hash_index',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_adaptive_max_sleep_delay'] = array(
+ 'innodb_adaptive_max_sleep_delay',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_additional_mem_pool_size'] = array(
'innodb_additional_mem_pool_size',
'innodb-parameters',
'sysvar',
'byte');
+ $variable_doc_links['innodb_api_bk_commit_interval'] = array(
+ 'innodb_api_bk_commit_interval',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_api_disable_rowlock'] = array(
+ 'innodb_api_disable_rowlock',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_api_enable_binlog'] = array(
+ 'innodb_api_enable_binlog',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_api_enable_mdl'] = array(
+ 'innodb_api_enable_mdl',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_api_trx_level'] = array(
+ 'innodb_api_trx_level',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_autoextend_increment'] = array(
'innodb_autoextend_increment',
'innodb-parameters',
@@ -617,27 +742,75 @@ function PMA_getArrayForDocumentLinks()
'innodb_autoinc_lock_mode',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_buffer_pool_dump_at_shutdown'] = array(
+ 'innodb_buffer_pool_dump_at_shutdown',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_buffer_pool_dump_now'] = array(
+ 'innodb_buffer_pool_dump_now',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_buffer_pool_filename'] = array(
+ 'innodb_buffer_pool_filename',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_buffer_pool_instances'] = array(
'innodb_buffer_pool_instances',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_buffer_pool_load_abort'] = array(
+ 'innodb_buffer_pool_load_abort',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_buffer_pool_load_at_startup'] = array(
+ 'innodb_buffer_pool_load_at_startup',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_buffer_pool_load_now'] = array(
+ 'innodb_buffer_pool_load_now',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_buffer_pool_size'] = array(
'innodb_buffer_pool_size',
'innodb-parameters',
'sysvar',
'byte');
+ $variable_doc_links['innodb_change_buffer_max_size'] = array(
+ 'innodb_change_buffer_max_size',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_change_buffering'] = array(
'innodb_change_buffering',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_checksum_algorithm'] = array(
+ 'innodb_checksum_algorithm',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_checksums'] = array(
'innodb_checksums',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_cmp_per_index_enabled'] = array(
+ 'innodb_cmp_per_index_enabled',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_commit_concurrency'] = array(
'innodb_commit_concurrency',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_compression_failure_threshold_pct'] = array(
+ 'innodb_compression_failure_threshold_pct',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_compression_level'] = array(
+ 'innodb_compression_level',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_compression_pad_pct_max'] = array(
+ 'innodb_compression_pad_pct_max',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_concurrency_tickets'] = array(
'innodb_concurrency_tickets',
'innodb-parameters',
@@ -650,6 +823,10 @@ function PMA_getArrayForDocumentLinks()
'innodb_data_home_dir',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_disable_sort_file_cache'] = array(
+ 'innodb_disable_sort_file_cache',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_doublewrite'] = array(
'innodb_doublewrite',
'innodb-parameters',
@@ -674,6 +851,10 @@ function PMA_getArrayForDocumentLinks()
'innodb_file_per_table',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_flush_log_at_timeout'] = array(
+ 'innodb_flush_log_at_timeout',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_flush_log_at_trx_commit'] = array(
'innodb_flush_log_at_trx_commit',
'innodb-parameters',
@@ -682,14 +863,82 @@ function PMA_getArrayForDocumentLinks()
'innodb_flush_method',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_flush_neighbors'] = array(
+ 'innodb_flush_neighbors',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_flushing_avg_loops'] = array(
+ 'innodb_flushing_avg_loops',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_force_load_corrupted'] = array(
+ 'innodb_force_load_corrupted',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_force_recovery'] = array(
'innodb_force_recovery',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_ft_aux_table'] = array(
+ 'innodb_ft_aux_table',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_cache_size'] = array(
+ 'innodb_ft_cache_size',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_enable_diag_print'] = array(
+ 'innodb_ft_enable_diag_print',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_enable_stopword'] = array(
+ 'innodb_ft_enable_stopword',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_max_token_size'] = array(
+ 'innodb_ft_max_token_size',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_min_token_size'] = array(
+ 'innodb_ft_min_token_size',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_num_word_optimize'] = array(
+ 'innodb_ft_num_word_optimize',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_result_cache_limit'] = array(
+ 'innodb_ft_result_cache_limit',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_server_stopword_table'] = array(
+ 'innodb_ft_server_stopword_table',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_sort_pll_degree'] = array(
+ 'innodb_ft_sort_pll_degree',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_total_cache_size'] = array(
+ 'innodb_ft_total_cache_size',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_ft_user_stopword_table'] = array(
+ 'innodb_ft_user_stopword_table',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_io_capacity'] = array(
'innodb_io_capacity',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_io_capacity_max'] = array(
+ 'innodb_io_capacity_max',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_large_prefix'] = array(
+ 'innodb_large_prefix',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_lock_wait_timeout'] = array(
'innodb_lock_wait_timeout',
'innodb-parameters',
@@ -703,6 +952,10 @@ function PMA_getArrayForDocumentLinks()
'innodb-parameters',
'sysvar',
'byte');
+ $variable_doc_links['innodb_log_compressed_pages'] = array(
+ 'innodb_log_compressed_pages',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_log_file_size'] = array(
'innodb_log_file_size',
'innodb-parameters',
@@ -716,18 +969,46 @@ function PMA_getArrayForDocumentLinks()
'innodb_log_group_home_dir',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_lru_scan_depth'] = array(
+ 'innodb_lru_scan_depth',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_max_dirty_pages_pct'] = array(
'innodb_max_dirty_pages_pct',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_max_dirty_pages_pct_lwm'] = array(
+ 'innodb_max_dirty_pages_pct_lwm',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_max_purge_lag'] = array(
'innodb_max_purge_lag',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_max_purge_lag_delay'] = array(
+ 'innodb_max_purge_lag_delay',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_mirrored_log_groups'] = array(
'innodb_mirrored_log_groups',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_monitor_disable'] = array(
+ 'innodb_monitor_disable',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_monitor_enable'] = array(
+ 'innodb_monitor_enable',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_monitor_reset'] = array(
+ 'innodb_monitor_reset',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_monitor_reset_all'] = array(
+ 'innodb_monitor_reset_all',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_old_blocks_pct'] = array(
'innodb_old_blocks_pct',
'innodb-parameters',
@@ -736,10 +1017,26 @@ function PMA_getArrayForDocumentLinks()
'innodb_old_blocks_time',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_online_alter_log_max_size'] = array(
+ 'innodb_online_alter_log_max_size',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_open_files'] = array(
'innodb_open_files',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_optimize_fulltext_only'] = array(
+ 'innodb_optimize_fulltext_only',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_page_size'] = array(
+ 'innodb_page_size',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_print_all_deadlocks'] = array(
+ 'innodb_print_all_deadlocks',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_purge_batch_size'] = array(
'innodb_purge_batch_size',
'innodb-parameters',
@@ -748,6 +1045,10 @@ function PMA_getArrayForDocumentLinks()
'innodb_purge_threads',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_random_read_ahead'] = array(
+ 'innodb_random_read_ahead',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_read_ahead_threshold'] = array(
'innodb_read_ahead_threshold',
'innodb-parameters',
@@ -756,6 +1057,10 @@ function PMA_getArrayForDocumentLinks()
'innodb_read_io_threads',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_read_only'] = array(
+ 'innodb_read_only',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_replication_delay'] = array(
'innodb_replication_delay',
'innodb-parameters',
@@ -764,18 +1069,54 @@ function PMA_getArrayForDocumentLinks()
'innodb_rollback_on_timeout',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_rollback_segments'] = array(
+ 'innodb_rollback_segments',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_sort_buffer_size'] = array(
+ 'innodb_sort_buffer_size',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_spin_wait_delay'] = array(
'innodb_spin_wait_delay',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_stats_auto_recalc'] = array(
+ 'innodb_stats_auto_recalc',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_stats_method'] = array(
+ 'innodb_stats_method',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_stats_on_metadata'] = array(
'innodb_stats_on_metadata',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_stats_persistent'] = array(
+ 'innodb_stats_persistent',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_stats_persistent_sample_pages'] = array(
+ 'innodb_stats_persistent_sample_pages',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_stats_sample_pages'] = array(
'innodb_stats_sample_pages',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_stats_transient_sample_pages'] = array(
+ 'innodb_stats_transient_sample_pages',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_status_output'] = array(
+ 'innodb_status_output',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_status_output_locks'] = array(
+ 'innodb_status_output_locks',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_strict_mode'] = array(
'innodb_strict_mode',
'innodb-parameters',
@@ -784,6 +1125,10 @@ function PMA_getArrayForDocumentLinks()
'innodb_support_xa',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_sync_array_size'] = array(
+ 'innodb_sync_array_size',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_sync_spin_loops'] = array(
'innodb_sync_spin_loops',
'innodb-parameters',
@@ -800,6 +1145,18 @@ function PMA_getArrayForDocumentLinks()
'innodb_thread_sleep_delay',
'innodb-parameters',
'sysvar');
+ $variable_doc_links['innodb_undo_directory'] = array(
+ 'innodb_undo_directory',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_undo_logs'] = array(
+ 'innodb_undo_logs',
+ 'innodb-parameters',
+ 'sysvar');
+ $variable_doc_links['innodb_undo_tablespaces'] = array(
+ 'innodb_undo_tablespaces',
+ 'innodb-parameters',
+ 'sysvar');
$variable_doc_links['innodb_use_native_aio'] = array(
'innodb_use_native_aio',
'innodb-parameters',
@@ -906,16 +1263,28 @@ function PMA_getArrayForDocumentLinks()
'option_mysqld');
$variable_doc_links['log_bin'] = array(
'log_bin',
- 'server-system-variables',
+ 'replication-options-binary-log',
'sysvar');
$variable_doc_links['log-bin'] = array(
'log-bin',
'replication-options-binary-log',
'option_mysqld');
+ $variable_doc_links['log_bin_basename'] = array(
+ 'log_bin_basename',
+ 'replication-options-binary-log',
+ 'sysvar');
+ $variable_doc_links['log_bin_index'] = array(
+ 'log_bin_index',
+ 'replication-options-binary-log',
+ 'sysvar');
$variable_doc_links['log_bin_trust_function_creators'] = array(
'log-bin-trust-function-creators',
'replication-options-binary-log',
'option_mysqld');
+ $variable_doc_links['log_bin_use_v1_row_events'] = array(
+ 'log_bin_use_v1_row_events',
+ 'replication-options-binary-log',
+ 'sysvar');
$variable_doc_links['log_error'] = array(
'log-error',
'server-options',
@@ -932,6 +1301,18 @@ function PMA_getArrayForDocumentLinks()
'log-slave-updates',
'replication-options-slave',
'option_mysqld');
+ $variable_doc_links['log_slow_admin_statements'] = array(
+ 'log_slow_admin_statements',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['log_slow_slave_statements'] = array(
+ 'log_slow_slave_statements',
+ 'replication-options-slave',
+ 'sysvar');
+ $variable_doc_links['log_throttle_queries_not_using_indexes'] = array(
+ 'log_throttle_queries_not_using_indexes',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['log_slow_queries'] = array(
'log-slow-queries',
'server-options',
@@ -956,6 +1337,14 @@ function PMA_getArrayForDocumentLinks()
'lower_case_table_names',
'server-system-variables',
'sysvar');
+ $variable_doc_links['master_info_repository'] = array(
+ 'master_info_repository',
+ 'replication-options-slave',
+ 'sysvar');
+ $variable_doc_links['master_verify_checksum'] = array(
+ 'master_verify_checksum',
+ 'replication-options-binary-log',
+ 'sysvar');
$variable_doc_links['master-bind'] = array(
'',
'replication-options',
@@ -1012,6 +1401,10 @@ function PMA_getArrayForDocumentLinks()
'max_length_for_sort_data',
'server-system-variables',
'sysvar');
+ $variable_doc_links['max_long_data_size'] = array(
+ 'max_long_data_size',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['max_prepared_stmt_count'] = array(
'max_prepared_stmt_count',
'server-system-variables',
@@ -1045,6 +1438,14 @@ function PMA_getArrayForDocumentLinks()
'max_write_lock_count',
'server-system-variables',
'sysvar');
+ $variable_doc_links['metadata_locks_cache_size'] = array(
+ 'metadata_locks_cache_size',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['metadata_locks_hash_instances'] = array(
+ 'metadata_locks_hash_instances',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['memlock'] = array(
'memlock',
'server-options',
@@ -1053,6 +1454,10 @@ function PMA_getArrayForDocumentLinks()
'min-examined-row-limit',
'server-options',
'option_mysqld');
+ $variable_doc_links['multi_range_count'] = array(
+ 'multi_range_count',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['myisam_data_pointer_size'] = array(
'myisam_data_pointer_size',
'server-system-variables',
@@ -1141,6 +1546,26 @@ function PMA_getArrayForDocumentLinks()
'optimizer_switch',
'server-system-variables',
'sysvar');
+ $variable_doc_links['optimizer_trace'] = array(
+ 'optimizer_trace',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['optimizer_trace_features'] = array(
+ 'optimizer_trace_features',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['optimizer_trace_limit'] = array(
+ 'optimizer_trace_limit',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['optimizer_trace_max_mem_size'] = array(
+ 'optimizer_trace_max_mem_size',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['optimizer_trace_offset'] = array(
+ 'optimizer_trace_offset',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['partition'] = array(
'partition',
'server-options',
@@ -1149,6 +1574,34 @@ function PMA_getArrayForDocumentLinks()
'performance_schema',
'performance-schema-system-variables',
'sysvar');
+ $variable_doc_links['performance_schema_accounts_size'] = array(
+ 'performance_schema_accounts_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_digests_size'] = array(
+ 'performance_schema_digests_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_events_stages_history_long_size']
+ = array(
+ 'performance_schema_events_stages_history_long_size',
+ 'performance-schema-system-variables',
+ 'sysvar',
+ );
+ $variable_doc_links['performance_schema_events_stages_history_size'] = array(
+ 'performance_schema_events_stages_history_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_events_statements_history_long_size']
+ = array(
+ 'performance_schema_events_statements_history_long_size',
+ 'performance-schema-system-variables',
+ 'sysvar',
+ );
+ $variable_doc_links['performance_schema_events_statements_history_size'] = array(
+ 'performance_schema_events_statements_history_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
$variable_doc_links['performance_schema_events_waits_history_long_size'] = array(
'performance_schema_events_waits_history_long_size',
'performance-schema-system-variables',
@@ -1157,6 +1610,10 @@ function PMA_getArrayForDocumentLinks()
'performance_schema_events_waits_history_size',
'performance-schema-system-variables',
'sysvar');
+ $variable_doc_links['performance_schema_hosts_size'] = array(
+ 'performance_schema_hosts_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
$variable_doc_links['performance_schema_max_cond_classes'] = array(
'performance_schema_max_cond_classes',
'performance-schema-system-variables',
@@ -1193,6 +1650,22 @@ function PMA_getArrayForDocumentLinks()
'performance_schema_max_rwlock_instances',
'performance-schema-system-variables',
'sysvar');
+ $variable_doc_links['performance_schema_max_socket_classes'] = array(
+ 'performance_schema_max_socket_classes',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_max_socket_instances'] = array(
+ 'performance_schema_max_socket_instances',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_max_stage_classes'] = array(
+ 'performance_schema_max_stage_classes',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_max_statement_classes'] = array(
+ 'performance_schema_max_statement_classes',
+ 'performance-schema-system-variables',
+ 'sysvar');
$variable_doc_links['performance_schema_max_table_handles'] = array(
'performance_schema_max_table_handles',
'performance-schema-system-variables',
@@ -1209,6 +1682,22 @@ function PMA_getArrayForDocumentLinks()
'performance_schema_max_thread_instances',
'performance-schema-system-variables',
'sysvar');
+ $variable_doc_links['performance_schema_session_connect_attrs_size'] = array(
+ 'performance_schema_session_connect_attrs_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_setup_actors_size'] = array(
+ 'performance_schema_setup_actors_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_setup_objects_size'] = array(
+ 'performance_schema_setup_objects_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
+ $variable_doc_links['performance_schema_users_size'] = array(
+ 'performance_schema_users_size',
+ 'performance-schema-system-variables',
+ 'sysvar');
$variable_doc_links['pid_file'] = array(
'pid-file',
'server-options',
@@ -1305,6 +1794,14 @@ function PMA_getArrayForDocumentLinks()
'server-system-variables',
'sysvar',
'byte');
+ $variable_doc_links['relay_log'] = array(
+ 'relay_log',
+ 'replication-options-slave',
+ 'sysvar');
+ $variable_doc_links['relay_log_basename'] = array(
+ 'relay_log_basename',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['relay-log-index'] = array(
'relay-log-index',
'replication-options-slave',
@@ -1317,6 +1814,10 @@ function PMA_getArrayForDocumentLinks()
'relay_log_info_file',
'replication-options-slave',
'sysvar');
+ $variable_doc_links['relay_log_info_repository'] = array(
+ 'relay_log_info_repository',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['relay_log_purge'] = array(
'relay_log_purge',
'server-system-variables',
@@ -1345,6 +1846,10 @@ function PMA_getArrayForDocumentLinks()
'report-user',
'replication-options-slave',
'option_mysqld');
+ $variable_doc_links['rpl_stop_slave_timeout'] = array(
+ 'rpl_stop_slave_timeout',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['rpl_recovery_rank'] = array(
'rpl_recovery_rank',
'replication-options-slave',
@@ -1389,6 +1894,14 @@ function PMA_getArrayForDocumentLinks()
'server-id',
'replication-options',
'option_mysqld');
+ $variable_doc_links['server_id_bits'] = array(
+ 'server_id_bits',
+ 'mysql-cluster-system-variables',
+ 'sysvar');
+ $variable_doc_links['server_uuid'] = array(
+ 'server_uuid',
+ 'replication-options',
+ 'sysvar');
$variable_doc_links['shared_memory'] = array(
'shared_memory',
'server-system-variables',
@@ -1413,6 +1926,18 @@ function PMA_getArrayForDocumentLinks()
'skip-show-database',
'server-options',
'option_mysqld');
+ $variable_doc_links['slave_allow_batching'] = array(
+ 'slave_allow_batching',
+ 'mysql-cluster-system-variables',
+ 'sysvar');
+ $variable_doc_links['slave_checkpoint_group'] = array(
+ 'slave_checkpoint_group',
+ 'replication-options-slave',
+ 'sysvar');
+ $variable_doc_links['slave_checkpoint_period'] = array(
+ 'slave_checkpoint_period',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['slave_compressed_protocol'] = array(
'slave_compressed_protocol',
'replication-options-slave',
@@ -1425,14 +1950,34 @@ function PMA_getArrayForDocumentLinks()
'slave-load-tmpdir',
'replication-options-slave',
'option_mysqld');
+ $variable_doc_links['slave_max_allowed_packet'] = array(
+ 'slave_max_allowed_packet',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['slave_net_timeout'] = array(
'slave-net-timeout',
'replication-options-slave',
'option_mysqld');
+ $variable_doc_links['slave_parallel_workers'] = array(
+ 'slave_parallel_workers',
+ 'replication-options-slave',
+ 'sysvar');
+ $variable_doc_links['slave_pending_jobs_size_max'] = array(
+ 'slave_pending_jobs_size_max',
+ 'replication-options-slave',
+ 'sysvar');
+ $variable_doc_links['slave_rows_search_algorithms'] = array(
+ 'slave_rows_search_algorithms',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['slave_skip_errors'] = array(
'slave-skip-errors',
'replication-options-slave',
'option_mysqld');
+ $variable_doc_links['slave_sql_verify_checksum'] = array(
+ 'slave_sql_verify_checksum',
+ 'replication-options-slave',
+ 'sysvar');
$variable_doc_links['slave_transaction_retries'] = array(
'slave_transaction_retries',
'replication-options-slave',
@@ -1542,6 +2087,14 @@ function PMA_getArrayForDocumentLinks()
'ssl-cipher',
'ssl-options',
'option_general');
+ $variable_doc_links['ssl_crl'] = array(
+ 'ssl_crl',
+ 'server-system-variables',
+ 'sysvar');
+ $variable_doc_links['ssl_crlpath'] = array(
+ 'ssl_crlpath',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['ssl_key'] = array(
'ssl-key',
'ssl-options',
@@ -1550,6 +2103,10 @@ function PMA_getArrayForDocumentLinks()
'storage_engine',
'server-system-variables',
'sysvar');
+ $variable_doc_links['stored_program_cache'] = array(
+ 'stored_program_cache',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['sync_binlog'] = array(
'sync_binlog',
'replication-options-binary-log',
@@ -1586,6 +2143,10 @@ function PMA_getArrayForDocumentLinks()
'table_open_cache',
'server-system-variables',
'sysvar');
+ $variable_doc_links['table_open_cache_instances'] = array(
+ 'table_open_cache_instances',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['table_type'] = array(
'table_type',
'server-system-variables',
@@ -1645,6 +2206,10 @@ function PMA_getArrayForDocumentLinks()
'tx_isolation',
'server-system-variables',
'sysvar');
+ $variable_doc_links['tx_read_only'] = array(
+ 'tx_read_only',
+ 'server-system-variables',
+ 'sysvar');
$variable_doc_links['unique_checks'] = array(
'unique_checks',
'server-system-variables',
@@ -1680,4 +2245,217 @@ function PMA_getArrayForDocumentLinks()
return $variable_doc_links;
}
-?>
+/**
+ * Returns array of static system variables (i.e. read-only)
+ *
+ * @return array
+ */
+function PMA_getStaticSystemVariables()
+{
+ $static_variables = array(
+ 'back_log',
+ 'basedir',
+ 'bind_address',
+ 'binlog_row_image',
+ 'character_set_system',
+ 'character_sets_dir',
+ 'core_file',
+ 'datadir',
+ 'date_format',
+ 'datetime_format',
+ 'disconnect_on_expired_password',
+ 'engine_condition_pushdown',
+ 'error_count',
+ 'explicit_defaults_for_timestamp',
+ 'external_user',
+ 'ft_max_word_len',
+ 'ft_min_word_len',
+ 'ft_query_expansion_limit',
+ 'ft_stopword_file',
+ 'gtid_executed',
+ 'gtid_owned',
+ 'have_compress',
+ 'have_crypt',
+ 'have_csv',
+ 'have_dynamic_loading',
+ 'have_geometry',
+ 'have_innodb',
+ 'have_ndbcluster',
+ 'have_openssl',
+ 'have_partitioning',
+ 'have_profiling',
+ 'have_query_cache',
+ 'have_rtree_keys',
+ 'have_ssl',
+ 'have_symlink',
+ 'hostname',
+ 'ignore_builtin_innodb',
+ 'ignore_db_dirs',
+ 'init_file',
+ 'innodb_additional_mem_pool_size',
+ 'innodb_api_disable_rowlock',
+ 'innodb_api_enable_binlog',
+ 'innodb_api_enable_mdl',
+ 'innodb_autoinc_lock_mode',
+ 'innodb_buffer_pool_instances',
+ 'innodb_buffer_pool_load_at_startup',
+ 'innodb_checksums',
+ 'innodb_data_file_path',
+ 'innodb_data_home_dir',
+ 'innodb_doublewrite',
+ 'innodb_file_format_check',
+ 'innodb_flush_method',
+ 'innodb_force_load_corrupted',
+ 'innodb_force_recovery',
+ 'innodb_ft_cache_size',
+ 'innodb_ft_max_token_size',
+ 'innodb_ft_min_token_size',
+ 'innodb_ft_sort_pll_degree',
+ 'innodb_ft_total_cache_size',
+ 'innodb_locks_unsafe_for_binlog',
+ 'innodb_log_buffer_size',
+ 'innodb_log_file_size',
+ 'innodb_log_files_in_group',
+ 'innodb_log_group_home_dir',
+ 'innodb_mirrored_log_groups',
+ 'innodb_open_files',
+ 'innodb_page_size',
+ 'innodb_purge_threads',
+ 'innodb_read_io_threads',
+ 'innodb_read_only',
+ 'innodb_rollback_on_timeout',
+ 'innodb_sort_buffer_size',
+ 'innodb_sync_array_size',
+ 'innodb_undo_directory',
+ 'innodb_undo_tablespaces',
+ 'innodb_use_native_aio',
+ 'innodb_use_sys_malloc',
+ 'innodb_version',
+ 'innodb_write_io_threads',
+ 'language',
+ 'large_files_support',
+ 'large_page_size',
+ 'large_pages',
+ 'lc_messages_dir',
+ 'license',
+ 'locked_in_memory',
+ 'log',
+ 'log_bin',
+ 'log-bin',
+ 'log_bin_basename',
+ 'log_bin_index',
+ 'log_bin_use_v1_row_events',
+ 'log_error',
+ 'log_slave_updates',
+ 'log_slow_queries',
+ 'lower_case_file_system',
+ 'lower_case_table_names',
+ 'master-bind',
+ 'max_long_data_size',
+ 'max_tmp_tables',
+ 'metadata_locks_cache_size',
+ 'metadata_locks_hash_instances',
+ 'memlock',
+ 'multi_range_count',
+ 'myisam_mmap_size',
+ 'myisam_recover_options',
+ 'named_pipe',
+ 'old',
+ 'open_files_limit',
+ 'partition',
+ 'performance_schema',
+ 'performance_schema_accounts_size',
+ 'performance_schema_digests_size',
+ 'performance_schema_events_stages_history_long_size',
+ 'performance_schema_events_stages_history_size',
+ 'performance_schema_events_statements_history_long_size',
+ 'performance_schema_events_statements_history_size',
+ 'performance_schema_events_waits_history_long_size',
+ 'performance_schema_events_waits_history_size',
+ 'performance_schema_hosts_size',
+ 'performance_schema_max_cond_classes',
+ 'performance_schema_max_cond_instances',
+ 'performance_schema_max_file_classes',
+ 'performance_schema_max_file_handles',
+ 'performance_schema_max_file_instances',
+ 'performance_schema_max_mutex_classes',
+ 'performance_schema_max_mutex_instances',
+ 'performance_schema_max_rwlock_classes',
+ 'performance_schema_max_rwlock_instances',
+ 'performance_schema_max_socket_classes',
+ 'performance_schema_max_socket_instances',
+ 'performance_schema_max_stage_classes',
+ 'performance_schema_max_statement_classes',
+ 'performance_schema_max_table_handles',
+ 'performance_schema_max_table_instances',
+ 'performance_schema_max_thread_classes',
+ 'performance_schema_max_thread_instances',
+ 'performance_schema_session_connect_attrs_size',
+ 'performance_schema_setup_actors_size',
+ 'performance_schema_setup_objects_size',
+ 'performance_schema_users_size',
+ 'pid_file',
+ 'plugin_dir',
+ 'port',
+ 'protocol_version',
+ 'proxy_user',
+ 'relay_log',
+ 'relay_log_basename',
+ 'relay-log-index',
+ 'relay_log_index',
+ 'relay_log_info_file',
+ 'relay_log_recovery',
+ 'relay_log_space_limit',
+ 'report_host',
+ 'report_password',
+ 'report_port',
+ 'report_user',
+ 'rpl_recovery_rank',
+ 'safe_show_database',
+ 'secure_file_priv',
+ 'server_id_bits',
+ 'server_uuid',
+ 'shared_memory',
+ 'shared_memory_base_name',
+ 'skip_external_locking',
+ 'skip_name_resolve',
+ 'skip_networking',
+ 'skip_show_database',
+ 'slave_checkpoint_group',
+ 'slave_checkpoint_period',
+ 'slave_load_tmpdir',
+ 'slave_rows_search_algorithms',
+ 'slave_skip_errors',
+ 'slave_type_conversions',
+ 'socket',
+ 'sql_big_tables',
+ 'sql_log_update',
+ 'sql_low_priority_updates',
+ 'sql_max_join_size',
+ 'ssl_ca',
+ 'ssl_capath',
+ 'ssl_cert',
+ 'ssl_cipher',
+ 'ssl_crl',
+ 'ssl_crlpath',
+ 'ssl_key',
+ 'system_time_zone',
+ 'table_lock_wait_timeout',
+ 'table_open_cache_instances',
+ 'table_type',
+ 'thread_concurrency',
+ 'thread_handling',
+ 'thread_stack',
+ 'time_format',
+ 'tmpdir',
+ 'version',
+ 'version_comment',
+ 'version_compile_machine',
+ 'version_compile_os',
+ 'warning_count',
+ );
+
+ return $static_variables;
+
+}
+
diff --git a/libraries/session.inc.php b/libraries/session.inc.php
index 22185acb5e..fcd4507094 100644
--- a/libraries/session.inc.php
+++ b/libraries/session.inc.php
@@ -17,7 +17,7 @@ if (! defined('PHPMYADMIN')) {
if (!@function_exists('session_name')) {
PMA_warnMissingExtension('session', true);
-} elseif (ini_get('session.auto_start') == true && session_name() != 'phpMyAdmin') {
+} elseif (ini_get('session.auto_start') !== '' && session_name() != 'phpMyAdmin') {
// Do not delete the existing session, it might be used by other
// applications; instead just close it.
session_write_close();
@@ -102,6 +102,11 @@ if (! isset($_COOKIE[$session_name])) {
}
/**
+ * Disable setting of session cookies for further session_start() calls.
+ */
+@ini_set('session.use_cookies', 'true');
+
+/**
* Token which is used for authenticating access queries.
* (we use "space PMA_token space" to prevent overwriting)
*/
@@ -127,4 +132,3 @@ function PMA_secureSession()
}
$_SESSION[' PMA_token '] = md5(uniqid(rand(), true));
}
-?>
diff --git a/libraries/special_schema_links.lib.php b/libraries/special_schema_links.lib.php
index 5e8c5e0231..73faa80e59 100644
--- a/libraries/special_schema_links.lib.php
+++ b/libraries/special_schema_links.lib.php
@@ -65,7 +65,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'Db'
),
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'column_name' => array(
'link_param' => 'field',
@@ -116,7 +118,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'database_name'
),
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'index_name' => array(
'link_param' => 'index',
@@ -142,7 +146,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'database_name'
),
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
),
'proc' => array(
@@ -232,7 +238,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'Db'
),
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
),
'user' => array(
@@ -258,7 +266,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'column_name' => array(
'link_param' => 'field',
@@ -284,7 +294,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'constraint_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'column_name' => array(
'link_param' => 'field',
@@ -308,7 +320,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'referenced_table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'referenced_column_name' => array(
'link_param' => 'field',
@@ -334,7 +348,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
)
),
'processlist' => array(
@@ -358,7 +374,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'constraint_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'referenced_table_name' => array(
'link_param' => 'table',
@@ -368,7 +386,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'constraint_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
)
),
'routines' => array(
@@ -390,7 +410,9 @@ $GLOBALS['special_schema_links'] = array(
'schemata' => array(
'schema_name' => array(
'link_param' => 'db',
- 'default_page' => $GLOBALS['cfg']['DefaultTabDatabase']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
)
),
'statistics' => array(
@@ -402,7 +424,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
'column_name' => array(
'link_param' => 'field',
@@ -428,7 +452,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
),
'table_constraints' => array(
@@ -440,7 +466,9 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
),
'views' => array(
@@ -452,10 +480,11 @@ $GLOBALS['special_schema_links'] = array(
'column_name' => 'table_schema'
)
),
- 'default_page' => $GLOBALS['cfg']['DefaultTabTable']
+ 'default_page' => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ )
),
),
)
);
-?>
diff --git a/libraries/sql-formatter/LICENSE.txt b/libraries/sql-formatter/LICENSE.txt
deleted file mode 100644
index e822279b46..0000000000
--- a/libraries/sql-formatter/LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Jeremy Dorn <jeremy@jeremydorn.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/libraries/sql-formatter/README.md b/libraries/sql-formatter/README.md
deleted file mode 100644
index a144323cf8..0000000000
--- a/libraries/sql-formatter/README.md
+++ /dev/null
@@ -1,185 +0,0 @@
-SqlFormatter
-=============
-
-A lightweight php class for formatting sql statements.
-
-It can automatically indent and add line breaks in addition to syntax highlighting.
-
-History
-============
-
-I found myself having to debug auto-generated SQL statements all the time and
-wanted some way to easily output formatted HTML without having to include a
-huge library or copy and paste into online formatters.
-
-I was originally planning to extract the formatting code from PhpMyAdmin,
-but that was 10,000+ lines of code and used global variables.
-
-I saw that other people had the same problem and used Stack Overflow user
-losif's answer as a starting point. http://stackoverflow.com/a/3924147
-
-Usage
-============
-
-The SqlFormatter class has a static method 'format' which takes a SQL string
-as input and returns a formatted HTML block inside a pre tag.
-
-Sample usage:
-
-```php
-<?php
-require_once('SqlFormatter.php');
-
-$query = "SELECT count(*),`Column1`,`Testing`, `Testing Three` FROM `Table1`
- WHERE Column1 = 'testing' AND ( (`Column2` = `Column3` OR Column4 >= NOW()) )
- GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10";
-
-echo SqlFormatter::format($query);
-```
-
-Output:
-
-![](http://jdorn.github.com/sql-formatter/format-highlight.png)
-
-Formatting Only
--------------------------
-If you don't want syntax highlighting and only want the indentations and
-line breaks, pass in false as the second parameter.
-
-This is useful for outputting to error logs or other non-html formats.
-
-```php
-<?php
-echo SqlFormatter::format($query, false);
-```
-
-Output:
-
-![](http://jdorn.github.com/sql-formatter/format.png)
-
-Syntax Highlighting Only
--------------------------
-
-There is a separate method 'highlight' that preserves all original whitespace
-and just adds syntax highlighting.
-
-This is useful for sql that is already well formatted and just needs to be a little
-easier to read.
-
-```php
-<?php
-echo SqlFormatter::highlight($query);
-```
-
-Output:
-
-![](http://jdorn.github.com/sql-formatter/highlight.png)
-
-Compress Query
---------------------------
-
-The compress method removes all comments and compresses whitespace.
-
-This is useful for outputting queries that can be copy pasted to the command line easily.
-
-```
--- This is a comment
- SELECT
- /* This is another comment
- On more than one line */
- Id #This is one final comment
- as temp, DateCreated as Created FROM MyTable;
-```
-
-```php
-echo SqlFormatter::compress($query)
-```
-
-Output:
-
-```
-SELECT Id as temp, DateCreated as Created FROM MyTable;
-```
-
-Remove Comments
-------------------------
-If you want to keep all original whitespace formatting and just remove comments,
-you can use the removeComments method instead of compress.
-
-```
--- This is a comment
- SELECT
- /* This is another comment
- On more than one line */
- Id #This is one final comment
- as temp, DateCreated as Created FROM MyTable;
-```
-
-```php
-<?php
-echo SqlFormatter::removeComments($query);
-```
-
-Output:
-```
-
- SELECT
-
- Id
- as temp, DateCreated as Created FROM MyTable;
-```
-
-Split SQL String into Queries
---------------------------
-
-Another feature, which is unrelated to formatting, is the ability to break up a SQL string into multiple queries.
-
-For Example:
-
-```sql
-DROP TABLE IF EXISTS MyTable;
-CREATE TABLE MyTable ( id int );
-INSERT INTO MyTable (id)
- VALUES
- (1),(2),(3),(4);
-SELECT * FROM MyTable;
-```
-
-```php
-<?php
-$queries = SqlFormatter::splitQuery($sql);
-```
-
-Result:
-
-1. `DROP TABLE IF EXISTS MyTable`;
-2. `CREATE TABLE MyTable ( id int )`;
-3. `INSERT INTO MyTable (id) VALUES (1),(2),(3),(4)`;
-4. `SELECT * FROM MyTable`;
-
-### Why Not Regular Expressions?
-
-Why not just use `explode(';', $sql)` or a regular expression?
-
-The following example sql and others like it are _impossible_ to split correctly using regular expressions, no matter how complex.
-
-```
-SELECT ";"; SELECT ";\"; a;";
-SELECT ";
- abc";
-SELECT a,b #comment;
-FROM test;
-```
-
-SqlFormatter breaks the string into tokens instead of using regular expressions and will correctly produce:
-
-1. `SELECT ";"`;
-2. `SELECT ";\"; a;"`;
-3. `SELECT "; abc"`;
-4. `SELECT a,b #comment;
-FROM test`;
-
-Please note, the splitQuery method will still fail in the following cases:
-* The DELIMITER command can be used to change the delimiter from the default ';' to something else.
-* The CREATE PROCEDURE command has a ';' in the middle of it
-* The USE command is not terminated with a ';'
diff --git a/libraries/sql-formatter/lib/SqlFormatter.php b/libraries/sql-formatter/lib/SqlFormatter.php
deleted file mode 100644
index 82927e432a..0000000000
--- a/libraries/sql-formatter/lib/SqlFormatter.php
+++ /dev/null
@@ -1,1085 +0,0 @@
-<?php
-/**
- * SQL Formatter is a collection of utilities for debugging SQL queries.
- * It includes methods for formatting, syntax highlighting, removing comments, etc.
- *
- * @package SqlFormatter
- * @author Jeremy Dorn <jeremy@jeremydorn.com>
- * @author Florin Patan <florinpatan@gmail.com>
- * @copyright 2013 Jeremy Dorn
- * @license http://opensource.org/licenses/MIT
- * @link http://github.com/jdorn/sql-formatter
- * @version 1.2.18
- */
-class SqlFormatter
-{
- // Constants for token types
- const TOKEN_TYPE_WHITESPACE = 0;
- const TOKEN_TYPE_WORD = 1;
- const TOKEN_TYPE_QUOTE = 2;
- const TOKEN_TYPE_BACKTICK_QUOTE = 3;
- const TOKEN_TYPE_RESERVED = 4;
- const TOKEN_TYPE_RESERVED_TOPLEVEL = 5;
- const TOKEN_TYPE_RESERVED_NEWLINE = 6;
- const TOKEN_TYPE_BOUNDARY = 7;
- const TOKEN_TYPE_COMMENT = 8;
- const TOKEN_TYPE_BLOCK_COMMENT = 9;
- const TOKEN_TYPE_NUMBER = 10;
- const TOKEN_TYPE_ERROR = 11;
- const TOKEN_TYPE_VARIABLE = 12;
-
- // Constants for different components of a token
- const TOKEN_TYPE = 0;
- const TOKEN_VALUE = 1;
-
- // Reserved words (for syntax highlighting)
- protected static $reserved = array(
- 'ACCESSIBLE', 'ACTION', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AS', 'ASC',
- 'AUTOCOMMIT', 'AUTO_INCREMENT', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED', 'CHARACTER SET',
- 'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT',
- 'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE',
- 'DAY_SECOND', 'DEFAULT', 'DEFINER', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV',
- 'DO', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINE_TYPE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXEC',
- 'EXECUTE', 'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FULL', 'FULLTEXT',
- 'FUNCTION', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP_CONCAT', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE',
- 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IFNULL', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL',
- 'INTO', 'INVOKER', 'IS', 'ISOLATION', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEVEL', 'LIKE', 'LINEAR',
- 'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE',
- 'MATCH','MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS',
- 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY',
- 'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NOW()','NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY',
- 'ON UPDATE', 'ON DELETE', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE',
- 'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RANGE', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE','RAID_TYPE', 'READ', 'READ_ONLY',
- 'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT',
- 'RETURN', 'RETURNS', 'REVOKE', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SEPARATOR',
- 'SERIALIZABLE', 'SESSION', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT',
- 'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF', 'SQL_LOG_UPDATE',
- 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES', 'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER',
- 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'SQL_CACHE', 'SQL_NO_CACHE', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE',
- 'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL', 'TRUE',
- 'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'USAGE', 'USE', 'USING', 'VARIABLES',
- 'VIEW', 'WHEN', 'WITH', 'WORK', 'WRITE', 'YEAR_MONTH'
- );
-
- // For SQL formatting
- // These keywords will all be on their own line
- protected static $reserved_toplevel = array(
- 'SELECT', 'FROM', 'WHERE', 'SET', 'ORDER BY', 'GROUP BY', 'LIMIT', 'DROP',
- 'VALUES', 'UPDATE', 'HAVING', 'ADD', 'AFTER', 'ALTER TABLE', 'DELETE FROM', 'UNION ALL', 'UNION', 'EXCEPT', 'INTERSECT'
- );
-
- protected static $reserved_newline = array(
- 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'OUTER JOIN', 'INNER JOIN', 'JOIN', 'XOR', 'OR', 'AND'
- );
-
- protected static $functions = array (
- 'ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_DECRYPT', 'AES_ENCRYPT', 'AREA', 'ASBINARY', 'ASCII', 'ASIN', 'ASTEXT', 'ATAN', 'ATAN2',
- 'AVG', 'BDMPOLYFROMTEXT', 'BDMPOLYFROMWKB', 'BDPOLYFROMTEXT', 'BDPOLYFROMWKB', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_COUNT', 'BIT_LENGTH',
- 'BIT_OR', 'BIT_XOR', 'BOUNDARY', 'BUFFER', 'CAST', 'CEIL', 'CEILING', 'CENTROID', 'CHAR', 'CHARACTER_LENGTH', 'CHARSET', 'CHAR_LENGTH',
- 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONTAINS', 'CONV', 'CONVERT', 'CONVERT_TZ',
- 'CONVEXHULL', 'COS', 'COT', 'COUNT', 'CRC32', 'CROSSES', 'CURDATE', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER',
- 'CURTIME', 'DATABASE', 'DATE', 'DATEDIFF', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK',
- 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'DIFFERENCE', 'DIMENSION', 'DISJOINT', 'DISTANCE', 'ELT', 'ENCODE',
- 'ENCRYPT', 'ENDPOINT', 'ENVELOPE', 'EQUALS', 'EXP', 'EXPORT_SET', 'EXTERIORRING', 'EXTRACT', 'EXTRACTVALUE', 'FIELD', 'FIND_IN_SET', 'FLOOR',
- 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GEOMCOLLFROMTEXT', 'GEOMCOLLFROMWKB', 'GEOMETRYCOLLECTION', 'GEOMETRYCOLLECTIONFROMTEXT',
- 'GEOMETRYCOLLECTIONFROMWKB', 'GEOMETRYFROMTEXT', 'GEOMETRYFROMWKB', 'GEOMETRYN', 'GEOMETRYTYPE', 'GEOMFROMTEXT', 'GEOMFROMWKB', 'GET_FORMAT',
- 'GET_LOCK', 'GLENGTH', 'GREATEST', 'GROUP_CONCAT', 'GROUP_UNIQUE_USERS', 'HEX', 'HOUR', 'IF', 'IFNULL', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR',
- 'INTERIORRINGN', 'INTERSECTION', 'INTERSECTS', 'INTERVAL', 'ISCLOSED', 'ISEMPTY', 'ISNULL', 'ISRING', 'ISSIMPLE', 'IS_FREE_LOCK', 'IS_USED_LOCK',
- 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LINEFROMTEXT', 'LINEFROMWKB', 'LINESTRING', 'LINESTRINGFROMTEXT', 'LINESTRINGFROMWKB',
- 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG10', 'LOG2', 'LOWER', 'LPAD', 'LTRIM', 'MAKEDATE', 'MAKETIME', 'MAKE_SET',
- 'MASTER_POS_WAIT', 'MAX', 'MBRCONTAINS', 'MBRDISJOINT', 'MBREQUAL', 'MBRINTERSECTS', 'MBROVERLAPS', 'MBRTOUCHES', 'MBRWITHIN', 'MD5', 'MICROSECOND',
- 'MID', 'MIN', 'MINUTE', 'MLINEFROMTEXT', 'MLINEFROMWKB', 'MOD', 'MONTH', 'MONTHNAME', 'MPOINTFROMTEXT', 'MPOINTFROMWKB', 'MPOLYFROMTEXT', 'MPOLYFROMWKB',
- 'MULTILINESTRING', 'MULTILINESTRINGFROMTEXT', 'MULTILINESTRINGFROMWKB', 'MULTIPOINT', 'MULTIPOINTFROMTEXT', 'MULTIPOINTFROMWKB', 'MULTIPOLYGON',
- 'MULTIPOLYGONFROMTEXT', 'MULTIPOLYGONFROMWKB', 'NAME_CONST', 'NULLIF', 'NUMGEOMETRIES', 'NUMINTERIORRINGS', 'NUMPOINTS', 'OCT', 'OCTET_LENGTH',
- 'OLD_PASSWORD', 'ORD', 'OVERLAPS', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POINT', 'POINTFROMTEXT', 'POINTFROMWKB', 'POINTN', 'POINTONSURFACE',
- 'POLYFROMTEXT', 'POLYFROMWKB', 'POLYGON', 'POLYGONFROMTEXT', 'POLYGONFROMWKB', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND',
- 'RELATED', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', 'SCHEMA', 'SECOND', 'SEC_TO_TIME',
- 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SIN', 'SLEEP', 'SOUNDEX', 'SPACE', 'SQRT', 'SRID', 'STARTPOINT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP',
- 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTR', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYMDIFFERENCE', 'SYSDATE', 'SYSTEM_USER', 'TAN',
- 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TOUCHES', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE',
- 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIQUE_USERS', 'UNIX_TIMESTAMP', 'UPDATEXML', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP',
- 'UUID', 'VARIANCE', 'VAR_POP', 'VAR_SAMP', 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'WITHIN', 'X', 'Y', 'YEAR', 'YEARWEEK'
- );
-
- // Punctuation that can be used as a boundary between other tokens
- protected static $boundaries = array(',', ';',':', ')', '(', '.', '=', '<', '>', '+', '-', '*', '/', '!', '^', '%', '|', '&', '#');
-
- // For HTML syntax highlighting
- // Styles applied to different token types
- public static $quote_attributes = 'style="color: blue;"';
- public static $backtick_quote_attributes = 'style="color: purple;"';
- public static $reserved_attributes = 'style="font-weight:bold;"';
- public static $boundary_attributes = '';
- public static $number_attributes = 'style="color: green;"';
- public static $word_attributes = 'style="color: #333;"';
- public static $error_attributes = 'style="background-color: red;"';
- public static $comment_attributes = 'style="color: #aaa;"';
- public static $variable_attributes = 'style="color: orange;"';
- public static $pre_attributes = 'style="color: black; background-color: white;"';
-
- // Boolean - whether or not the current environment is the CLI
- // This affects the type of syntax highlighting
- // If not defined, it will be determined automatically
- public static $cli;
-
- // For CLI syntax highlighting
- public static $cli_quote = "\x1b[34;1m";
- public static $cli_backtick_quote = "\x1b[35;1m";
- public static $cli_reserved = "\x1b[37m";
- public static $cli_boundary = "";
- public static $cli_number = "\x1b[32;1m";
- public static $cli_word = "";
- public static $cli_error = "\x1b[31;1;7m";
- public static $cli_comment = "\x1b[30;1m";
- public static $cli_functions = "\x1b[37m";
- public static $cli_variable = "\x1b[36;1m";
-
- // The tab character to use when formatting SQL
- public static $tab = ' ';
-
- // This flag tells us if queries need to be enclosed in <pre> tags
- public static $use_pre = true;
-
- // This flag tells us if SqlFormatted has been initialized
- protected static $init;
-
- // Regular expressions for tokenizing
- protected static $regex_boundaries;
- protected static $regex_reserved;
- protected static $regex_reserved_newline;
- protected static $regex_reserved_toplevel;
- protected static $regex_function;
-
- // Cache variables
- // Only tokens shorter than this size will be cached. Somewhere between 10 and 20 seems to work well for most cases.
- public static $max_cachekey_size = 15;
- protected static $token_cache = array();
- protected static $cache_hits = 0;
- protected static $cache_misses = 0;
-
- /**
- * Get stats about the token cache
- * @return Array An array containing the keys 'hits', 'misses', 'entries', and 'size' in bytes
- */
- public static function getCacheStats()
- {
- return array(
- 'hits'=>self::$cache_hits,
- 'misses'=>self::$cache_misses,
- 'entries'=>count(self::$token_cache),
- 'size'=>strlen(serialize(self::$token_cache))
- );
- }
-
- /**
- * Stuff that only needs to be done once. Builds regular expressions and sorts the reserved words.
- */
- protected static function init()
- {
- if (self::$init) return;
-
- // Sort reserved word list from longest word to shortest, 3x faster than usort
- $reservedMap = array_combine(self::$reserved, array_map('strlen', self::$reserved));
- arsort($reservedMap);
- self::$reserved = array_keys($reservedMap);
-
- // Set up regular expressions
- self::$regex_boundaries = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$boundaries)).')';
- self::$regex_reserved = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved)).')';
- self::$regex_reserved_toplevel = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_toplevel)).')');
- self::$regex_reserved_newline = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_newline)).')');
-
- self::$regex_function = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$functions)).')';
-
- self::$init = true;
- }
-
- /**
- * Return the next token and token type in a SQL string.
- * Quoted strings, comments, reserved words, whitespace, and punctuation are all their own tokens.
- *
- * @param String $string The SQL string
- * @param array $previous The result of the previous getNextToken() call
- *
- * @return Array An associative array containing the type and value of the token.
- */
- protected static function getNextToken($string, $previous = null)
- {
- // Whitespace
- if (preg_match('/^\s+/',$string,$matches)) {
- return array(
- self::TOKEN_VALUE => $matches[0],
- self::TOKEN_TYPE=>self::TOKEN_TYPE_WHITESPACE
- );
- }
-
- // Comment
- if ($string[0] === '#' || (isset($string[1])&&($string[0]==='-'&&$string[1]==='-') || ($string[0]==='/'&&$string[1]==='*'))) {
- // Comment until end of line
- if ($string[0] === '-' || $string[0] === '#') {
- $last = strpos($string, "\n");
- $type = self::TOKEN_TYPE_COMMENT;
- } else { // Comment until closing comment tag
- $last = strpos($string, "*/", 2) + 2;
- $type = self::TOKEN_TYPE_BLOCK_COMMENT;
- }
-
- if ($last === false) {
- $last = strlen($string);
- }
-
- return array(
- self::TOKEN_VALUE => substr($string, 0, $last),
- self::TOKEN_TYPE => $type
- );
- }
-
- // Quoted String
- if ($string[0]==='"' || $string[0]==='\'' || $string[0]==='`' || $string[0]==='[') {
- $return = array(
- self::TOKEN_TYPE => (($string[0]==='`' || $string[0]==='[')? self::TOKEN_TYPE_BACKTICK_QUOTE : self::TOKEN_TYPE_QUOTE),
- self::TOKEN_VALUE => self::getQuotedString($string)
- );
-
- return $return;
- }
-
- // User-defined Variable
- if ($string[0] === '@' && isset($string[1])) {
- $ret = array(
- self::TOKEN_VALUE => null,
- self::TOKEN_TYPE => self::TOKEN_TYPE_VARIABLE
- );
-
- // If the variable name is quoted
- if ($string[1]==='"' || $string[1]==='\'' || $string[1]==='`') {
- $ret[self::TOKEN_VALUE] = '@'.self::getQuotedString(substr($string,1));
- }
- // Non-quoted variable name
- else {
- preg_match('/^(@[a-zA-Z0-9\._\$]+)/',$string,$matches);
- if ($matches) {
- $ret[self::TOKEN_VALUE] = $matches[1];
- }
- }
-
- if($ret[self::TOKEN_VALUE] !== null) return $ret;
- }
-
- // Number (decimal, binary, or hex)
- if (preg_match('/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|'.self::$regex_boundaries.')/',$string,$matches)) {
- return array(
- self::TOKEN_VALUE => $matches[1],
- self::TOKEN_TYPE=>self::TOKEN_TYPE_NUMBER
- );
- }
-
- // Boundary Character (punctuation and symbols)
- if (preg_match('/^('.self::$regex_boundaries.')/',$string,$matches)) {
- return array(
- self::TOKEN_VALUE => $matches[1],
- self::TOKEN_TYPE => self::TOKEN_TYPE_BOUNDARY
- );
- }
-
- // A reserved word cannot be preceded by a '.'
- // this makes it so in "mytable.from", "from" is not considered a reserved word
- if (!$previous || !isset($previous[self::TOKEN_VALUE]) || $previous[self::TOKEN_VALUE] !== '.') {
- $upper = strtoupper($string);
- // Top Level Reserved Word
- if (preg_match('/^('.self::$regex_reserved_toplevel.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
- return array(
- self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_TOPLEVEL,
- self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
- );
- }
- // Newline Reserved Word
- if (preg_match('/^('.self::$regex_reserved_newline.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
- return array(
- self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_NEWLINE,
- self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
- );
- }
- // Other Reserved Word
- if (preg_match('/^('.self::$regex_reserved.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
- return array(
- self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED,
- self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
- );
- }
- }
-
- // A function must be suceeded by '('
- // this makes it so "count(" is considered a function, but "count" alone is not
- $upper = strtoupper($string);
- // function
- if (preg_match('/^('.self::$regex_function.'[(]|\s|[)])/', $upper,$matches)) {
- return array(
- self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED,
- self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])-1)
- );
- }
-
- // Non reserved word
- preg_match('/^(.*?)($|\s|["\'`]|'.self::$regex_boundaries.')/',$string,$matches);
-
- return array(
- self::TOKEN_VALUE => $matches[1],
- self::TOKEN_TYPE => self::TOKEN_TYPE_WORD
- );
- }
-
- protected static function getQuotedString($string)
- {
- $ret = null;
-
- // This checks for the following patterns:
- // 1. backtick quoted string using `` to escape
- // 2. square bracket quoted string (SQL Server) using ]] to escape
- // 3. double quoted string using "" or \" to escape
- // 4. single quoted string using '' or \' to escape
- if ( preg_match('/^(((`[^`]*($|`))+)|((\[[^\]]*($|\]))(\][^\]]*($|\]))*)|(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/s', $string, $matches)) {
- $ret = $matches[1];
- }
-
- return $ret;
- }
-
- /**
- * Takes a SQL string and breaks it into tokens.
- * Each token is an associative array with type and value.
- *
- * @param String $string The SQL string
- *
- * @return Array An array of tokens.
- */
- protected static function tokenize($string)
- {
- self::init();
-
- $tokens = array();
-
- // Used for debugging if there is an error while tokenizing the string
- $original_length = strlen($string);
-
- // Used to make sure the string keeps shrinking on each iteration
- $old_string_len = strlen($string) + 1;
-
- $token = null;
-
- $current_length = strlen($string);
-
- // Keep processing the string until it is empty
- while ($current_length) {
- // If the string stopped shrinking, there was a problem
- if ($old_string_len <= $current_length) {
- $tokens[] = array(
- self::TOKEN_VALUE=>$string,
- self::TOKEN_TYPE=>self::TOKEN_TYPE_ERROR
- );
-
- return $tokens;
- }
- $old_string_len = $current_length;
-
- // Determine if we can use caching
- if ($current_length >= self::$max_cachekey_size) {
- $cacheKey = substr($string,0,self::$max_cachekey_size);
- } else {
- $cacheKey = false;
- }
-
- // See if the token is already cached
- if ($cacheKey && isset(self::$token_cache[$cacheKey])) {
- // Retrieve from cache
- $token = self::$token_cache[$cacheKey];
- $token_length = strlen($token[self::TOKEN_VALUE]);
- self::$cache_hits++;
- } else {
- // Get the next token and the token type
- $token = self::getNextToken($string, $token);
- $token_length = strlen($token[self::TOKEN_VALUE]);
- self::$cache_misses++;
-
- // If the token is shorter than the max length, store it in cache
- if ($cacheKey && $token_length < self::$max_cachekey_size) {
- self::$token_cache[$cacheKey] = $token;
- }
- }
-
- $tokens[] = $token;
-
- // Advance the string
- $string = substr($string, $token_length);
-
- $current_length -= $token_length;
- }
-
- return $tokens;
- }
-
- /**
- * Format the whitespace in a SQL string to make it easier to read.
- *
- * @param String $string The SQL string
- * @param boolean $highlight If true, syntax highlighting will also be performed
- *
- * @return String The SQL string with HTML styles and formatting wrapped in a <pre> tag
- */
- public static function format($string, $highlight=true)
- {
- // This variable will be populated with formatted html
- $return = '';
-
- // Use an actual tab while formatting and then switch out with self::$tab at the end
- $tab = "\t";
-
- $indent_level = 0;
- $newline = false;
- $inline_parentheses = false;
- $increase_special_indent = false;
- $increase_block_indent = false;
- $indent_types = array();
- $added_newline = false;
- $inline_count = 0;
- $inline_indented = false;
- $clause_limit = false;
-
- // Tokenize String
- $original_tokens = self::tokenize($string);
-
- // Remove existing whitespace
- $tokens = array();
- foreach ($original_tokens as $i=>$token) {
- if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
- $token['i'] = $i;
- $tokens[] = $token;
- }
- }
-
- // Format token by token
- foreach ($tokens as $i=>$token) {
- // Get highlighted token if doing syntax highlighting
- if ($highlight) {
- $highlighted = self::highlightToken($token);
- } else { // If returning raw text
- $highlighted = $token[self::TOKEN_VALUE];
- }
-
- // If we are increasing the special indent level now
- if ($increase_special_indent) {
- $indent_level++;
- $increase_special_indent = false;
- array_unshift($indent_types,'special');
- }
- // If we are increasing the block indent level now
- if ($increase_block_indent) {
- $indent_level++;
- $increase_block_indent = false;
- array_unshift($indent_types,'block');
- }
-
- // If we need a new line before the token
- if ($newline) {
- $return .= "\n" . str_repeat($tab, $indent_level);
- $newline = false;
- $added_newline = true;
- } else {
- $added_newline = false;
- }
-
- // Display comments directly where they appear in the source
- if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
- if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
- $indent = str_repeat($tab,$indent_level);
- $return .= "\n" . $indent;
- $highlighted = str_replace("\n","\n".$indent,$highlighted);
- }
-
- $return .= $highlighted;
- $newline = true;
- continue;
- }
-
- if ($inline_parentheses) {
- // End of inline parentheses
- if ($token[self::TOKEN_VALUE] === ')') {
- $return = rtrim($return,' ');
-
- if ($inline_indented) {
- array_shift($indent_types);
- $indent_level --;
- $return .= "\n" . str_repeat($tab, $indent_level);
- }
-
- $inline_parentheses = false;
-
- $return .= $highlighted . ' ';
- continue;
- }
-
- if ($token[self::TOKEN_VALUE] === ',') {
- if ($inline_count >= 30) {
- $inline_count = 0;
- $newline = true;
- }
- }
-
- $inline_count += strlen($token[self::TOKEN_VALUE]);
- }
-
- // Opening parentheses increase the block indent level and start a new line
- if ($token[self::TOKEN_VALUE] === '(') {
- // First check if this should be an inline parentheses block
- // Examples are "NOW()", "COUNT(*)", "int(10)", key(`somecolumn`), DECIMAL(7,2)
- // Allow up to 3 non-whitespace tokens inside inline parentheses
- $length = 0;
- for ($j=1;$j<=250;$j++) {
- // Reached end of string
- if (!isset($tokens[$i+$j])) break;
-
- $next = $tokens[$i+$j];
-
- // Reached closing parentheses, able to inline it
- if ($next[self::TOKEN_VALUE] === ')') {
- $inline_parentheses = true;
- $inline_count = 0;
- $inline_indented = false;
- break;
- }
-
- // Reached an invalid token for inline parentheses
- if ($next[self::TOKEN_VALUE]===';' || $next[self::TOKEN_VALUE]==='(') {
- break;
- }
-
- // Reached an invalid token type for inline parentheses
- if ($next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_TOPLEVEL || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_NEWLINE || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_COMMENT || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_BLOCK_COMMENT) {
- break;
- }
-
- $length += strlen($next[self::TOKEN_VALUE]);
- }
-
- if ($inline_parentheses && $length > 30) {
- $increase_block_indent = true;
- $inline_indented = true;
- $newline = true;
- }
-
- // Take out the preceding space unless there was whitespace there in the original query
- if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
- $return = rtrim($return,' ');
- }
-
- if (!$inline_parentheses) {
- $increase_block_indent = true;
- // Add a newline after the parentheses
- $newline = true;
- }
-
- }
-
- // Closing parentheses decrease the block indent level
- elseif ($token[self::TOKEN_VALUE] === ')') {
- // Remove whitespace before the closing parentheses
- $return = rtrim($return,' ');
-
- $indent_level--;
-
- // Reset indent level
- while ($j=array_shift($indent_types)) {
- if ($j==='special') {
- $indent_level--;
- } else {
- break;
- }
- }
-
- if ($indent_level < 0) {
- // This is an error
- $indent_level = 0;
-
- if ($highlight) {
- $return .= "\n".self::highlightError($token[self::TOKEN_VALUE]);
- continue;
- }
- }
-
- // Add a newline before the closing parentheses (if not already added)
- if (!$added_newline) {
- $return .= "\n" . str_repeat($tab, $indent_level);
- }
- }
-
- // Top level reserved words start a new line and increase the special indent level
- elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
- $increase_special_indent = true;
-
- // If the last indent type was 'special', decrease the special indent for this round
- reset($indent_types);
- if (current($indent_types)==='special') {
- $indent_level--;
- array_shift($indent_types);
- }
-
- // Add a newline after the top level reserved word
- $newline = true;
- // Add a newline before the top level reserved word (if not already added)
- if (!$added_newline) {
- $return .= "\n" . str_repeat($tab, $indent_level);
- }
- // If we already added a newline, redo the indentation since it may be different now
- else {
- $return = rtrim($return,$tab).str_repeat($tab, $indent_level);
- }
-
- // If the token may have extra whitespace
- if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) {
- $highlighted = preg_replace('/\s+/',' ',$highlighted);
- }
- //if SQL 'LIMIT' clause, start variable to reset newline
- if ($token[self::TOKEN_VALUE] === 'LIMIT' && !$inline_parentheses) {
- $clause_limit = true;
- }
- }
-
- // Checks if we are out of the limit clause
- elseif ($clause_limit && $token[self::TOKEN_VALUE] !== "," && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_NUMBER && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
- $clause_limit = false;
- }
-
- // Commas start a new line (unless within inline parentheses or SQL 'LIMIT' clause)
- elseif ($token[self::TOKEN_VALUE] === ',' && !$inline_parentheses) {
- //If the previous TOKEN_VALUE is 'LIMIT', resets new line
- if ($clause_limit === true) {
- $newline = false;
- $clause_limit = false;
- }
- // All other cases of commas
- else {
- $newline = true;
- }
- }
-
- // Newline reserved words start a new line
- elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE) {
- // Add a newline before the reserved word (if not already added)
- if (!$added_newline) {
- $return .= "\n" . str_repeat($tab, $indent_level);
- }
-
- // If the token may have extra whitespace
- if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) {
- $highlighted = preg_replace('/\s+/',' ',$highlighted);
- }
- }
-
- // Multiple boundary characters in a row should not have spaces between them (not including parentheses)
- elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) {
- if (isset($tokens[$i-1]) && $tokens[$i-1][self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) {
- if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
- $return = rtrim($return,' ');
- }
- }
- }
-
- // If the token shouldn't have a space before it
- if ($token[self::TOKEN_VALUE] === '.' || $token[self::TOKEN_VALUE] === ',' || $token[self::TOKEN_VALUE] === ';') {
- $return = rtrim($return, ' ');
- }
-
- $return .= $highlighted.' ';
-
- // If the token shouldn't have a space after it
- if ($token[self::TOKEN_VALUE] === '(' || $token[self::TOKEN_VALUE] === '.') {
- $return = rtrim($return,' ');
- }
-
- // If this is the "-" of a negative number, it shouldn't have a space after it
- if($token[self::TOKEN_VALUE] === '-' && isset($tokens[$i+1]) && $tokens[$i+1][self::TOKEN_TYPE] === self::TOKEN_TYPE_NUMBER && isset($tokens[$i-1])) {
- $prev = $tokens[$i-1][self::TOKEN_TYPE];
- if($prev !== self::TOKEN_TYPE_QUOTE && $prev !== self::TOKEN_TYPE_BACKTICK_QUOTE && $prev !== self::TOKEN_TYPE_WORD && $prev !== self::TOKEN_TYPE_NUMBER) {
- $return = rtrim($return,' ');
- }
- }
- }
-
- // If there are unmatched parentheses
- if ($highlight && array_search('block',$indent_types) !== false) {
- $return .= "\n".self::highlightError("WARNING: unclosed parentheses or section");
- }
-
- // Replace tab characters with the configuration tab character
- $return = trim(str_replace("\t",self::$tab,$return));
-
- if ($highlight) {
- $return = self::output($return);
- }
-
- return $return;
- }
-
- /**
- * Add syntax highlighting to a SQL string
- *
- * @param String $string The SQL string
- *
- * @return String The SQL string with HTML styles applied
- */
- public static function highlight($string)
- {
- $tokens = self::tokenize($string);
-
- $return = '';
-
- foreach ($tokens as $token) {
- $return .= self::highlightToken($token);
- }
-
- return self::output($return);
- }
-
- /**
- * Split a SQL string into multiple queries.
- * Uses ";" as a query delimiter.
- *
- * @param String $string The SQL string
- *
- * @return Array An array of individual query strings without trailing semicolons
- */
- public static function splitQuery($string)
- {
- $queries = array();
- $current_query = '';
- $empty = true;
-
- $tokens = self::tokenize($string);
-
- foreach ($tokens as $token) {
- // If this is a query separator
- if ($token[self::TOKEN_VALUE] === ';') {
- if (!$empty) {
- $queries[] = $current_query.';';
- }
- $current_query = '';
- $empty = true;
- continue;
- }
-
- // If this is a non-empty character
- if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_COMMENT && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_BLOCK_COMMENT) {
- $empty = false;
- }
-
- $current_query .= $token[self::TOKEN_VALUE];
- }
-
- if (!$empty) {
- $queries[] = trim($current_query);
- }
-
- return $queries;
- }
-
- /**
- * Remove all comments from a SQL string
- *
- * @param String $string The SQL string
- *
- * @return String The SQL string without comments
- */
- public static function removeComments($string)
- {
- $result = '';
-
- $tokens = self::tokenize($string);
-
- foreach ($tokens as $token) {
- // Skip comment tokens
- if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
- continue;
- }
-
- $result .= $token[self::TOKEN_VALUE];
- }
- $result = self::format( $result,false);
-
- return $result;
- }
-
- /**
- * Compress a query by collapsing white space and removing comments
- *
- * @param String $string The SQL string
- *
- * @return String The SQL string without comments
- */
- public static function compress($string)
- {
- $result = '';
-
- $tokens = self::tokenize($string);
-
- $whitespace = true;
- foreach ($tokens as $token) {
- // Skip comment tokens
- if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
- continue;
- }
- // Remove extra whitespace in reserved words (e.g "OUTER JOIN" becomes "OUTER JOIN")
- elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
- $token[self::TOKEN_VALUE] = preg_replace('/\s+/',' ',$token[self::TOKEN_VALUE]);
- }
-
- if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_WHITESPACE) {
- // If the last token was whitespace, don't add another one
- if ($whitespace) {
- continue;
- } else {
- $whitespace = true;
- // Convert all whitespace to a single space
- $token[self::TOKEN_VALUE] = ' ';
- }
- } else {
- $whitespace = false;
- }
-
- $result .= $token[self::TOKEN_VALUE];
- }
-
- return rtrim($result);
- }
-
- /**
- * Highlights a token depending on its type.
- *
- * @param Array $token An associative array containing type and value.
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightToken($token)
- {
- $type = $token[self::TOKEN_TYPE];
-
- if (self::is_cli()) {
- $token = $token[self::TOKEN_VALUE];
- } else {
- if (defined('ENT_IGNORE')) {
- $token = htmlentities($token[self::TOKEN_VALUE],ENT_COMPAT | ENT_IGNORE ,'UTF-8');
- } else {
- $token = htmlentities($token[self::TOKEN_VALUE],ENT_COMPAT,'UTF-8');
- }
- }
-
- if ($type===self::TOKEN_TYPE_BOUNDARY) {
- return self::highlightBoundary($token);
- } elseif ($type===self::TOKEN_TYPE_WORD) {
- return self::highlightWord($token);
- } elseif ($type===self::TOKEN_TYPE_BACKTICK_QUOTE) {
- return self::highlightBacktickQuote($token);
- } elseif ($type===self::TOKEN_TYPE_QUOTE) {
- return self::highlightQuote($token);
- } elseif ($type===self::TOKEN_TYPE_RESERVED) {
- return self::highlightReservedWord($token);
- } elseif ($type===self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
- return self::highlightReservedWord($token);
- } elseif ($type===self::TOKEN_TYPE_RESERVED_NEWLINE) {
- return self::highlightReservedWord($token);
- } elseif ($type===self::TOKEN_TYPE_NUMBER) {
- return self::highlightNumber($token);
- } elseif ($type===self::TOKEN_TYPE_VARIABLE) {
- return self::highlightVariable($token);
- } elseif ($type===self::TOKEN_TYPE_COMMENT || $type===self::TOKEN_TYPE_BLOCK_COMMENT) {
- return self::highlightComment($token);
- }
-
- return $token;
- }
-
- /**
- * Highlights a quoted string
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightQuote($value)
- {
- if (self::is_cli()) {
- return self::$cli_quote . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$quote_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a backtick quoted string
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightBacktickQuote($value)
- {
- if (self::is_cli()) {
- return self::$cli_backtick_quote . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$backtick_quote_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a reserved word
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightReservedWord($value)
- {
- if (self::is_cli()) {
- return self::$cli_reserved . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$reserved_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a boundary token
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightBoundary($value)
- {
- if ($value==='(' || $value===')') return $value;
-
- if (self::is_cli()) {
- return self::$cli_boundary . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$boundary_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a number
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightNumber($value)
- {
- if (self::is_cli()) {
- return self::$cli_number . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$number_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights an error
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightError($value)
- {
- if (self::is_cli()) {
- return self::$cli_error . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$error_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a comment
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightComment($value)
- {
- if (self::is_cli()) {
- return self::$cli_comment . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$comment_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a word token
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightWord($value)
- {
- if (self::is_cli()) {
- return self::$cli_word . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$word_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Highlights a variable token
- *
- * @param String $value The token's value
- *
- * @return String HTML code of the highlighted token.
- */
- protected static function highlightVariable($value)
- {
- if (self::is_cli()) {
- return self::$cli_variable . $value . "\x1b[0m";
- } else {
- return '<span ' . self::$variable_attributes . '>' . $value . '</span>';
- }
- }
-
- /**
- * Helper function for building regular expressions for reserved words and boundary characters
- *
- * @param String $a The string to be quoted
- *
- * @return String The quoted string
- */
- private static function quote_regex($a)
- {
- return preg_quote($a,'/');
- }
-
- /**
- * Helper function for building string output
- *
- * @param String $string The string to be quoted
- *
- * @return String The quoted string
- */
- private static function output($string)
- {
- if (self::is_cli()) {
- return $string."\n";
- } else {
- $string=trim($string);
- if (!self::$use_pre) {
- return $string;
- }
-
- return '<pre '.self::$pre_attributes.'>' . $string . '</pre>';
- }
- }
-
- private static function is_cli()
- {
- if (isset(self::$cli)) return self::$cli;
- else return php_sapi_name() === 'cli';
- }
-
-}
diff --git a/libraries/sql-parser/ClassLoader.php b/libraries/sql-parser/ClassLoader.php
new file mode 100644
index 0000000000..3ff2f69de3
--- /dev/null
+++ b/libraries/sql-parser/ClassLoader.php
@@ -0,0 +1,250 @@
+<?php
+
+/**
+ * This file is based on Composer's autoloader.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * @package SqlParser
+ * @subpackage Autoload
+ */
+namespace SqlParser\Autoload;
+
+/**
+ * ClassLoader implements a PSR-4 class loader,
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ * This class is a stripped version of Composer's ClassLoader.
+ *
+ * @package SqlParser
+ * @subpackage Autoload
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class ClassLoader
+{
+ public $prefixLengths = array();
+ public $prefixDirs = array();
+ public $fallbackDirs = array();
+
+ public $classMap = array();
+
+ public $classMapAuthoritative = false;
+
+ /**
+ * @param array $classMap Class to filename map
+ *
+ * @return void
+ */
+ public function addClassMap(array $classMap)
+ {
+ if (!empty($this->classMap)) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-0 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirs = array_merge(
+ (array) $paths,
+ $this->fallbackDirs
+ );
+ } else {
+ $this->fallbackDirs = array_merge(
+ $this->fallbackDirs,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirs[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengths[$prefix[0]][$prefix] = $length;
+ $this->prefixDirs[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirs[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirs[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirs[$prefix] = array_merge(
+ $this->prefixDirs[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirs = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengths[$prefix[0]][$prefix] = $length;
+ $this->prefixDirs[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ *
+ * @return void
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ *
+ * @return void
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ *
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
+ if ('\\' == $class[0]) {
+ $class = substr($class, 1);
+ }
+
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative) {
+ return false;
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if ($file === null && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if ($file === null) {
+ // Remember that this class does not exist.
+ return $this->classMap[$class] = false;
+ }
+
+ return $file;
+ }
+
+ /**
+ * Finds a file that defines the specified class and has the specified
+ * extension.
+ *
+ * @param string $class The name of the class
+ * @param string $ext The extension of the file
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFileWithExtension($class, $ext)
+ {
+ $logicalPath = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengths[$first])) {
+ foreach ($this->prefixLengths[$first] as $prefix => $length) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($this->prefixDirs[$prefix] as $dir) {
+ if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPath, $length))) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ foreach ($this->fallbackDirs as $dir) {
+ if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPath)) {
+ return $file;
+ }
+ }
+
+ return false;
+ }
+}
+
+if (!function_exists('SqlParser\\Autoload\\includeFile')) {
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file The name of the file
+ *
+ * @return void
+ */
+ function includeFile($file)
+ {
+ include $file;
+ }
+}
diff --git a/libraries/sql-parser/autoload.php b/libraries/sql-parser/autoload.php
new file mode 100644
index 0000000000..85f0d6c986
--- /dev/null
+++ b/libraries/sql-parser/autoload.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * The autoloader used for loading sql-parser's components.
+ *
+ * This file is based on Composer's autoloader.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * @package SqlParser
+ * @subpackage Autoload
+ */
+namespace SqlParser\Autoload;
+
+if (!class_exists('SqlParser\\Autoload\\ClassLoader')) {
+ include_once './libraries/sql-parser/ClassLoader.php';
+}
+
+use SqlParser\Autoload\ClassLoader;
+
+/**
+ * Initializes the autoloader.
+ *
+ * @package SqlParser
+ * @subpackage Autoload
+ */
+class AutoloaderInit
+{
+
+ /**
+ * The loader instance.
+ *
+ * @var ClassLoader
+ */
+ public static $loader;
+
+ /**
+ * Constructs and returns the class loader.
+ *
+ * @param array $map Array containing path to each namespace.
+ *
+ * @return ClassLoader
+ */
+ public static function getLoader(array $map)
+ {
+ if (null !== self::$loader) {
+ return self::$loader;
+ }
+
+ self::$loader = $loader = new ClassLoader();
+
+ foreach ($map as $namespace => $path) {
+ $loader->set($namespace, $path);
+ }
+
+ $loader->register(true);
+
+ return $loader;
+ }
+}
+
+// Initializing the autoloader.
+return AutoloaderInit::getLoader(
+ array(
+ 'SqlParser\\' => array(dirname(__FILE__) . '/src'),
+ )
+);
diff --git a/libraries/sql-parser/src/Component.php b/libraries/sql-parser/src/Component.php
new file mode 100644
index 0000000000..eff88e66be
--- /dev/null
+++ b/libraries/sql-parser/src/Component.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * Defines a component that is later extended to parse specialized components or
+ * keywords.
+ *
+ * There is a small difference between *Component and *Keyword classes: usually,
+ * *Component parsers can be reused in multiple situations and *Keyword parsers
+ * count on the *Component classes to do their job.
+ *
+ * @package SqlParser
+ */
+
+namespace {
+
+ if (!function_exists('__')) {
+
+ /**
+ * Translates the given string.
+ *
+ * @param string $str String to be translated.
+ *
+ * @return string
+ */
+ function __($str)
+ {
+ return $str;
+ }
+ }
+}
+
+namespace SqlParser {
+
+ /**
+ * A component (of a statement) is a part of a statement that is common to
+ * multiple query types.
+ *
+ * @category Components
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+ abstract class Component
+ {
+
+ /**
+ * Parses the tokens contained in the given list in the context of the given
+ * parser.
+ *
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @throws \Exception Not implemented yet.
+ *
+ * @return mixed
+ */
+ public static function parse(
+ Parser $parser, TokensList $list, array $options = array()
+ ) {
+ // This method should be abstract, but it can't be both static and
+ // abstract.
+ throw new \Exception(\__('Not implemented yet.'));
+ }
+
+ /**
+ * Builds the string representation of a component of this type.
+ *
+ * In other words, this function represents the inverse function of
+ * `static::parse`.
+ *
+ * @param mixed $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @throws \Exception Not implemented yet.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ // This method should be abstract, but it can't be both static and
+ // abstract.
+ throw new \Exception(\__('Not implemented yet.'));
+ }
+
+ /**
+ * Builds the string representation of a component of this type.
+ *
+ * @see static::build
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return static::build($this);
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/AlterOperation.php b/libraries/sql-parser/src/Components/AlterOperation.php
new file mode 100644
index 0000000000..ee9302c54d
--- /dev/null
+++ b/libraries/sql-parser/src/Components/AlterOperation.php
@@ -0,0 +1,226 @@
+<?php
+
+/**
+ * Parses an alter operation.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses an alter operation.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class AlterOperation extends Component
+{
+
+ /**
+ * All alter operations.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ // table_options
+ 'ENGINE' => array(1, 'var='),
+ 'AUTO_INCREMENT' => array(1, 'var='),
+ 'AVG_ROW_LENGTH' => array(1, 'var'),
+ 'MAX_ROWS' => array(1, 'var'),
+ 'ROW_FORMAT' => array(1, 'var'),
+
+ 'ADD' => 1,
+ 'ALTER' => 1,
+ 'ANALYZE' => 1,
+ 'CHANGE' => 1,
+ 'CHECK' => 1,
+ 'COALESCE' => 1,
+ 'CONVERT' => 1,
+ 'DISABLE' => 1,
+ 'DISCARD' => 1,
+ 'DROP' => 1,
+ 'ENABLE' => 1,
+ 'IMPORT' => 1,
+ 'MODIFY' => 1,
+ 'OPTIMIZE' => 1,
+ 'ORDER' => 1,
+ 'PARTITION' => 1,
+ 'REBUILD' => 1,
+ 'REMOVE' => 1,
+ 'RENAME' => 1,
+ 'REORGANIZE' => 1,
+ 'REPAIR' => 1,
+
+ 'COLUMN' => 2,
+ 'CONSTRAINT' => 2,
+ 'DEFAULT' => 2,
+ 'TO' => 2,
+ 'BY' => 2,
+ 'FOREIGN' => 2,
+ 'FULLTEXT' => 2,
+ 'KEY' => 2,
+ 'KEYS' => 2,
+ 'PARTITIONING' => 2,
+ 'PRIMARY KEY' => 2,
+ 'SPATIAL' => 2,
+ 'TABLESPACE' => 2,
+ 'INDEX' => 2,
+
+ 'DEFAULT CHARACTER SET' => array(3, 'var'),
+ 'DEFAULT CHARSET' => array(3, 'var'),
+
+ 'COLLATE' => array(4, 'var'),
+ );
+
+ /**
+ * Options of this operation.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * The altered field.
+ *
+ * @var Expression
+ */
+ public $field;
+
+ /**
+ * Unparsed tokens.
+ *
+ * @var Token[]|string
+ */
+ public $unknown = array();
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return AlterOperation
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new AlterOperation();
+
+ /**
+ * Counts brackets.
+ *
+ * @var int $brackets
+ */
+ $brackets = 0;
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ---------------------[ options ]---------------------> 1
+ *
+ * 1 ----------------------[ field ]----------------------> 2
+ *
+ * 2 -------------------------[ , ]-----------------------> 0
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping comments.
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ // Skipping whitespaces.
+ if ($token->type === Token::TYPE_WHITESPACE) {
+ if ($state === 2) {
+ // When parsing the unknown part, the whitespaces are
+ // included to not break anything.
+ $ret->unknown[] = $token;
+ }
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
+ $state = 1;
+ } elseif ($state === 1) {
+ $ret->field = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ )
+ );
+ if ($ret->field === null) {
+ // No field was read. We go back one token so the next
+ // iteration will parse the same token, but in state 2.
+ --$list->idx;
+ }
+ $state = 2;
+ } elseif ($state === 2) {
+ if ($token->type === Token::TYPE_OPERATOR) {
+ if ($token->value === '(') {
+ ++$brackets;
+ } elseif ($token->value === ')') {
+ --$brackets;
+ } elseif (($token->value === ',') && ($brackets === 0)) {
+ break;
+ }
+ }
+ $ret->unknown[] = $token;
+ }
+ }
+
+ if ($ret->options->isEmpty()) {
+ $parser->error(
+ __('Unrecognized alter operation.'),
+ $list->tokens[$list->idx]
+ );
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param AlterOperation $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ $ret = $component->options . ' ';
+ if ((isset($component->field)) && ($component->field !== '')) {
+ $ret .= $component->field . ' ';
+ }
+ $ret .= TokensList::build($component->unknown);
+ return $ret;
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Array2d.php b/libraries/sql-parser/src/Components/Array2d.php
new file mode 100644
index 0000000000..e4c0ed7504
--- /dev/null
+++ b/libraries/sql-parser/src/Components/Array2d.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * `VALUES` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `VALUES` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Array2d extends Component
+{
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return ArrayObj[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ /**
+ * The number of values in each set.
+ *
+ * @var int $count
+ */
+ $count = -1;
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ----------------------[ array ]----------------------> 1
+ *
+ * 1 ------------------------[ , ]------------------------> 0
+ * 1 -----------------------[ else ]----------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ // No keyword is expected.
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ break;
+ }
+
+ if ($state === 0) {
+ if ($token->value === '(') {
+ $arr = ArrayObj::parse($parser, $list, $options);
+ $arrCount = count($arr->values);
+ if ($count === -1) {
+ $count = $arrCount;
+ } elseif ($arrCount != $count) {
+ $parser->error(
+ sprintf(
+ __('%1$d values were expected, but found %2$d.'),
+ $count,
+ $arrCount
+ ),
+ $token
+ );
+ }
+ $ret[] = $arr;
+ $state = 1;
+ } else {
+ break;
+ }
+ } elseif ($state === 1) {
+ if ($token->value === ',') {
+ $state = 0;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if ($state === 0) {
+ $parser->error(
+ __('An opening bracket followed by a set of values was expected.'),
+ $list->tokens[$list->idx]
+ );
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param ArrayObj[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ return ArrayObj::build($component);
+ }
+}
diff --git a/libraries/sql-parser/src/Components/ArrayObj.php b/libraries/sql-parser/src/Components/ArrayObj.php
new file mode 100644
index 0000000000..9f4e972991
--- /dev/null
+++ b/libraries/sql-parser/src/Components/ArrayObj.php
@@ -0,0 +1,160 @@
+<?php
+
+/**
+ * Parses an array.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses an array.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ArrayObj extends Component
+{
+
+ /**
+ * The array that contains the unprocessed value of each token.
+ *
+ * @var array
+ */
+ public $raw = array();
+
+ /**
+ * The array that contains the processed value of each token.
+ *
+ * @var array
+ */
+ public $values = array();
+
+ /**
+ * Constructor.
+ *
+ * @param array $raw The unprocessed values.
+ * @param array $values The processed values.
+ */
+ public function __construct(array $raw = array(), array $values = array())
+ {
+ $this->raw = $raw;
+ $this->values = $values;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return mixed
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = empty($options['type']) ? new ArrayObj() : array();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -----------------------[ ( ]------------------------> 1
+ *
+ * 1 ------------------[ array element ]-----------------> 2
+ *
+ * 2 ------------------------[ , ]-----------------------> 1
+ * 2 ------------------------[ ) ]-----------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ if (($token->type !== Token::TYPE_OPERATOR) || ($token->value !== '(')) {
+ $parser->error(
+ __('An opening bracket was expected.'),
+ $token
+ );
+ break;
+ }
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ')')) {
+ // Empty array.
+ break;
+ }
+ if (empty($options['type'])) {
+ $ret->values[] = $token->value;
+ $ret->raw[] = $token->token;
+ } else {
+ $ret[] = $options['type']::parse(
+ $parser,
+ $list,
+ empty($options['typeOptions']) ? array() : $options['typeOptions']
+ );
+ }
+ $state = 2;
+ } elseif ($state === 2) {
+ if (($token->type !== Token::TYPE_OPERATOR) || (($token->value !== ',') && ($token->value !== ')'))) {
+ $parser->error(
+ __('A comma or a closing bracket was expected'),
+ $token
+ );
+ break;
+ }
+ if ($token->value === ',') {
+ $state = 1;
+ } else { // )
+ break;
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @param ArrayObj|ArrayObj[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return implode(', ', $component);
+ } elseif (!empty($component->raw)) {
+ return '(' . implode(', ', $component->raw) . ')';
+ } else {
+ return '(' . implode(', ', $component->values) . ')';
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Condition.php b/libraries/sql-parser/src/Components/Condition.php
new file mode 100644
index 0000000000..43347a8799
--- /dev/null
+++ b/libraries/sql-parser/src/Components/Condition.php
@@ -0,0 +1,212 @@
+<?php
+
+/**
+ * `WHERE` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `WHERE` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Condition extends Component
+{
+
+ /**
+ * Logical operators that can be used to delimit expressions.
+ *
+ * @var array
+ */
+ public static $DELIMITERS = array('&&', 'AND', 'OR', 'XOR', '||');
+
+ /**
+ * Hash map containing reserved keywords that are also operators.
+ *
+ * @var array
+ */
+ public static $OPERATORS = array(
+ 'AND' => 1,
+ 'BETWEEN' => 1,
+ 'IN' => 1,
+ 'IS' => 1,
+ 'LIKE' => 1,
+ 'NOT NULL' => 1,
+ 'NULL' => 1,
+ 'OR' => 1,
+ 'XOR' => 1,
+ );
+
+ /**
+ * Identifiers recognized.
+ *
+ * @var array
+ */
+ public $identifiers = array();
+
+ /**
+ * Whether this component is an operator.
+ *
+ * @var bool
+ */
+ public $isOperator = false;
+
+ /**
+ * The condition.
+ *
+ * @var string
+ */
+ public $expr;
+
+ /**
+ * Constructor.
+ *
+ * @param string $expr The condition or the operator.
+ */
+ public function __construct($expr = null)
+ {
+ $this->expr = trim($expr);
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return Condition[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new Condition();
+
+ /**
+ * Counts brackets.
+ *
+ * @var int $brackets
+ */
+ $brackets = 0;
+
+ /**
+ * Whether there was a `BETWEEN` keyword before or not.
+ * It is required to keep track of them because their structure contains
+ * the keyword `AND`, which is also an operator that delimits
+ * expressions.
+ *
+ * @var bool $betweenBefore
+ */
+ $betweenBefore = false;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ // Replacing all whitespaces (new lines, tabs, etc.) with a single
+ // space character.
+ if ($token->type === Token::TYPE_WHITESPACE) {
+ $expr->expr .= ' ';
+ continue;
+ }
+
+ // Conditions are delimited by logical operators.
+ if (in_array($token->value, static::$DELIMITERS, true)) {
+ if (($betweenBefore) && ($token->value === 'AND')) {
+ $betweenBefore = false;
+ } else {
+ $expr->expr = trim($expr->expr);
+ if (!empty($expr->expr)) {
+ // Adding the condition that is delimited by this operator.
+ $ret[] = $expr;
+ }
+
+ // Adding the operator.
+ $expr = new Condition($token->value);
+ $expr->isOperator = true;
+ $ret[] = $expr;
+
+ $expr = new Condition();
+ continue;
+ }
+ }
+
+ if ($token->type === Token::TYPE_OPERATOR) {
+ if ($token->value === '(') {
+ ++$brackets;
+ } elseif ($token->value === ')') {
+ --$brackets;
+ }
+ }
+
+ // No keyword is expected.
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ if ($token->value === 'BETWEEN') {
+ $betweenBefore = true;
+ }
+ if (($brackets === 0) && (empty(static::$OPERATORS[$token->value]))) {
+ break;
+ }
+ }
+
+ $expr->expr .= $token->token;
+ if (($token->type === Token::TYPE_NONE)
+ || (($token->type === Token::TYPE_KEYWORD) && (!($token->flags & Token::FLAG_KEYWORD_RESERVED)))
+ || ($token->type === Token::TYPE_STRING)
+ || ($token->type === Token::TYPE_SYMBOL)
+ ) {
+ $expr->identifiers[] = $token->value;
+ }
+ }
+
+ // Last iteration was not processed.
+ $expr->expr = trim($expr->expr);
+ if (!empty($expr->expr)) {
+ $ret[] = $expr;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param Condition[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return implode(' ', $component);
+ } else {
+ return $component->expr;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/CreateDefinition.php b/libraries/sql-parser/src/Components/CreateDefinition.php
new file mode 100644
index 0000000000..0ef7c4a1a1
--- /dev/null
+++ b/libraries/sql-parser/src/Components/CreateDefinition.php
@@ -0,0 +1,314 @@
+<?php
+
+/**
+ * Parses the create definition of a column or a key.
+ *
+ * Used for parsing `CREATE TABLE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Context;
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses the create definition of a column or a key.
+ *
+ * Used for parsing `CREATE TABLE` statement.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class CreateDefinition extends Component
+{
+
+ /**
+ * All field options.
+ *
+ * @var array
+ */
+ public static $FIELD_OPTIONS = array(
+
+ // Tells the `OptionsArray` to not sort the options.
+ // See the note below.
+ '_UNSORTED' => true,
+
+ 'NOT NULL' => 1,
+ 'NULL' => 1,
+ 'DEFAULT' => array(2, 'var'),
+ 'AUTO_INCREMENT' => 3,
+ 'PRIMARY' => 4,
+ 'PRIMARY KEY' => 4,
+ 'UNIQUE' => 4,
+ 'UNIQUE KEY' => 4,
+ 'COMMENT' => array(5, 'var'),
+ 'COLUMN_FORMAT' => array(6, 'var'),
+ 'ON UPDATE' => array(7, 'var'),
+
+ // Generated columns options.
+ 'GENERATED ALWAYS' => 8,
+ 'AS' => array(9, 'expr', array('bracketsDelimited' => true)),
+ 'VIRTUAL' => 10,
+ 'PERSISTENT' => 11,
+ 'STORED' => 11,
+ // Common entries.
+ //
+ // NOTE: Some of the common options are not in the same order which
+ // causes troubles when checking if the options are in the right order.
+ // I should find a way to define multiple sets of options and make the
+ // parser select the right set.
+ //
+ // 'UNIQUE' => 4,
+ // 'UNIQUE KEY' => 4,
+ // 'COMMENT' => array(5, 'var'),
+ // 'NOT NULL' => 1,
+ // 'NULL' => 1,
+ // 'PRIMARY' => 4,
+ // 'PRIMARY KEY' => 4,
+ );
+
+ /**
+ * The name of the new column.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * Whether this field is a constraint or not.
+ *
+ * @var bool
+ */
+ public $isConstraint;
+
+ /**
+ * The data type of thew new column.
+ *
+ * @var DataType
+ */
+ public $type;
+
+ /**
+ * The key.
+ *
+ * @var Key
+ */
+ public $key;
+
+ /**
+ * The table that is referenced.
+ *
+ * @var Reference
+ */
+ public $references;
+
+ /**
+ * The options of this field.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The name of the field.
+ * @param OptionsArray $options The options of this field.
+ * @param DataType|Key $type The data type of this field or the key.
+ * @param bool $isConstraint Whether this field is a constraint or not.
+ * @param Reference $references References.
+ */
+ public function __construct($name = null, $options = null, $type = null,
+ $isConstraint = false, $references = null
+ ) {
+ $this->name = $name;
+ $this->options = $options;
+ if ($type instanceof DataType) {
+ $this->type = $type;
+ } elseif ($type instanceof Key) {
+ $this->key = $type;
+ $this->isConstraint = $isConstraint;
+ $this->references = $references;
+ }
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return CreateDefinition[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new CreateDefinition();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -----------------------[ ( ]------------------------> 1
+ *
+ * 1 --------------------[ CONSTRAINT ]------------------> 1
+ * 1 -----------------------[ key ]----------------------> 2
+ * 1 -------------[ constraint / column name ]-----------> 2
+ *
+ * 2 --------------------[ data type ]-------------------> 3
+ *
+ * 3 ---------------------[ options ]--------------------> 4
+ *
+ * 4 --------------------[ REFERENCES ]------------------> 4
+ *
+ * 5 ------------------------[ , ]-----------------------> 1
+ * 5 ------------------------[ ) ]-----------------------> 6 (-1)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $state = 1;
+ } else {
+ $parser->error(
+ __('An opening bracket was expected.'),
+ $token
+ );
+ break;
+ }
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'CONSTRAINT')) {
+ $expr->isConstraint = true;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_KEY)) {
+ $expr->key = Key::parse($parser, $list);
+ $state = 4;
+ } else {
+ $expr->name = $token->value;
+ if (!$expr->isConstraint) {
+ $state = 2;
+ }
+ }
+ } elseif ($state === 2) {
+ $expr->type = DataType::parse($parser, $list);
+ $state = 3;
+ } elseif ($state === 3) {
+ $expr->options = OptionsArray::parse($parser, $list, static::$FIELD_OPTIONS);
+ $state = 4;
+ } elseif ($state === 4) {
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'REFERENCES')) {
+ ++$list->idx; // Skipping keyword 'REFERENCES'.
+ $expr->references = Reference::parse($parser, $list);
+ } else {
+ --$list->idx;
+ }
+ $state = 5;
+ } elseif ($state === 5) {
+ if ((!empty($expr->type)) || (!empty($expr->key))) {
+ $ret[] = $expr;
+ }
+ $expr = new CreateDefinition();
+ if ($token->value === ',') {
+ $state = 1;
+ } elseif ($token->value === ')') {
+ $state = 6;
+ ++$list->idx;
+ break;
+ } else {
+ $parser->error(
+ __('A comma or a closing bracket was expected.'),
+ $token
+ );
+ $state = 0;
+ break;
+ }
+ }
+ }
+
+ // Last iteration was not saved.
+ if ((!empty($expr->type)) || (!empty($expr->key))) {
+ $ret[] = $expr;
+ }
+
+ if (($state !== 0) && ($state !== 6)) {
+ $parser->error(
+ __('A closing bracket was expected.'),
+ $list->tokens[$list->idx - 1]
+ );
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param CreateDefinition|CreateDefinition[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return "(\n " . implode(",\n ", $component) . "\n)";
+ } else {
+ $tmp = '';
+
+ if ($component->isConstraint) {
+ $tmp .= 'CONSTRAINT ';
+ }
+
+ if ((isset($component->name)) && ($component->name !== '')) {
+ $tmp .= Context::escape($component->name) . ' ';
+ }
+
+ if (!empty($component->type)) {
+ $tmp .= DataType::build(
+ $component->type,
+ array('lowercase' => true)
+ ) . ' ';
+ }
+
+ if (!empty($component->key)) {
+ $tmp .= $component->key . ' ';
+ }
+
+ if (!empty($component->references)) {
+ $tmp .= 'REFERENCES ' . $component->references . ' ';
+ }
+
+ $tmp .= $component->options;
+
+ return trim($tmp);
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/DataType.php b/libraries/sql-parser/src/Components/DataType.php
new file mode 100644
index 0000000000..a3aca73d6f
--- /dev/null
+++ b/libraries/sql-parser/src/Components/DataType.php
@@ -0,0 +1,170 @@
+<?php
+
+/**
+ * Parses a data type.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses a data type.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class DataType extends Component
+{
+
+ /**
+ * All data type options.
+ *
+ * @var array
+ */
+ public static $DATA_TYPE_OPTIONS = array(
+ 'BINARY' => 1,
+ 'CHARACTER SET' => array(2, 'var'),
+ 'CHARSET' => array(2, 'var'),
+ 'COLLATE' => array(3, 'var'),
+ 'UNSIGNED' => 4,
+ 'ZEROFILL' => 5,
+ );
+
+ /**
+ * The name of the data type.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * The parameters of this data type.
+ *
+ * Some data types have no parameters.
+ * Numeric types might have parameters for the maximum number of digits,
+ * precision, etc.
+ * String types might have parameters for the maximum length stored.
+ * `ENUM` and `SET` have parameters for possible values.
+ *
+ * For more information, check the MySQL manual.
+ *
+ * @var array
+ */
+ public $parameters = array();
+
+ /**
+ * The options of this data type.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The name of this data type.
+ * @param array $parameters The parameters (size or possible values).
+ * @param OptionsArray $options The options of this data type.
+ */
+ public function __construct($name = null, array $parameters = array(),
+ $options = null
+ ) {
+ $this->name = $name;
+ $this->parameters = $parameters;
+ $this->options = $options;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return DataType
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new DataType();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -------------------[ data type ]--------------------> 1
+ *
+ * 1 ----------------[ size and options ]----------------> 2
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->name = strtoupper($token->value);
+ if (($token->type !== Token::TYPE_KEYWORD) || (!($token->flags & Token::FLAG_KEYWORD_DATA_TYPE))) {
+ $parser->error(__('Unrecognized data type.'), $token);
+ }
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $parameters = ArrayObj::parse($parser, $list);
+ ++$list->idx;
+ $ret->parameters = (($ret->name === 'ENUM') || ($ret->name === 'SET')) ?
+ $parameters->raw : $parameters->values;
+ }
+ $ret->options = OptionsArray::parse($parser, $list, static::$DATA_TYPE_OPTIONS);
+ ++$list->idx;
+ break;
+ }
+
+ }
+
+ if (empty($ret->name)) {
+ return null;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param DataType $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ $name = (empty($options['lowercase'])) ?
+ $component->name : strtolower($component->name);
+
+ $parameters = '';
+ if (!empty($component->parameters)) {
+ $parameters = '(' . implode(',', $component->parameters) . ')';
+ }
+
+ return trim($name . $parameters . ' ' . $component->options);
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Expression.php b/libraries/sql-parser/src/Components/Expression.php
new file mode 100644
index 0000000000..1f8752ed76
--- /dev/null
+++ b/libraries/sql-parser/src/Components/Expression.php
@@ -0,0 +1,386 @@
+<?php
+
+/**
+ * Parses a reference to an expression (column, table or database name, function
+ * call, mathematical expression, etc.).
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Context;
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses a reference to an expression (column, table or database name, function
+ * call, mathematical expression, etc.).
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Expression extends Component
+{
+
+ /**
+ * The name of this database.
+ *
+ * @var string
+ */
+ public $database;
+
+ /**
+ * The name of this table.
+ *
+ * @var string
+ */
+ public $table;
+
+ /**
+ * The name of the column.
+ *
+ * @var string
+ */
+ public $column;
+
+ /**
+ * The sub-expression.
+ *
+ * @var string
+ */
+ public $expr = '';
+
+ /**
+ * The alias of this expression.
+ *
+ * @var string
+ */
+ public $alias;
+
+ /**
+ * The name of the function.
+ *
+ * @var mixed
+ */
+ public $function;
+
+ /**
+ * The type of subquery.
+ *
+ * @var string
+ */
+ public $subquery;
+
+ /**
+ * Constructor.
+ *
+ * Syntax:
+ * new Expression('expr')
+ * new Expression('expr', 'alias')
+ * new Expression('database', 'table', 'column')
+ * new Expression('database', 'table', 'column', 'alias')
+ *
+ * If the database, table or column name is not required, pass an empty
+ * string.
+ *
+ * @param string $database The name of the database or the the expression.
+ * the the expression.
+ * @param string $table The name of the table or the alias of the expression.
+ * the alias of the expression.
+ * @param string $column The name of the column.
+ * @param string $alias The name of the alias.
+ */
+ public function __construct($database = null, $table = null, $column = null, $alias = null)
+ {
+ if (($column === null) && ($alias === null)) {
+ $this->expr = $database; // case 1
+ $this->alias = $table; // case 2
+ } else {
+ $this->database = $database; // case 3
+ $this->table = $table; // case 3
+ $this->column = $column; // case 3
+ $this->alias = $alias; // case 4
+ }
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return Expression
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new Expression();
+
+ /**
+ * Whether current tokens make an expression or a table reference.
+ *
+ * @var bool $isExpr
+ */
+ $isExpr = false;
+
+ /**
+ * Whether a period was previously found.
+ *
+ * @var bool $dot
+ */
+ $dot = false;
+
+ /**
+ * Whether an alias is expected. Is 2 if `AS` keyword was found.
+ *
+ * @var int $alias
+ */
+ $alias = 0;
+
+ /**
+ * Counts brackets.
+ *
+ * @var int $brackets
+ */
+ $brackets = 0;
+
+ /**
+ * Keeps track of the previous token.
+ * Possible values:
+ * string, if function was previously found;
+ * true, if opening bracket was previously found;
+ * null, in any other case.
+ *
+ * @var string|bool $prev
+ */
+ $prev = null;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ if (($isExpr) && (!$alias)) {
+ $ret->expr .= $token->token;
+ }
+ if (($alias === 0) && (empty($options['noAlias'])) && (!$isExpr) && (!$dot) && (!empty($ret->expr))) {
+ $alias = 1;
+ }
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD)
+ && ($token->flags & Token::FLAG_KEYWORD_RESERVED)
+ && ($token->value !== 'DUAL')
+ ) {
+ // Keywords may be found only between brackets.
+ if ($brackets === 0) {
+ if ((empty($options['noAlias'])) && ($token->value === 'AS')) {
+ $alias = 2;
+ continue;
+ }
+ if (!($token->flags & Token::FLAG_KEYWORD_FUNCTION)) {
+ break;
+ }
+ } elseif ($prev === true) {
+ if ((empty($ret->subquery) && (!empty(Parser::$STATEMENT_PARSERS[$token->value])))) {
+ // A `(` was previously found and this keyword is the
+ // beginning of a statement, so this is a subquery.
+ $ret->subquery = $token->value;
+ }
+ }
+ }
+
+ if ($token->type === Token::TYPE_OPERATOR) {
+ if ((!empty($options['noBrackets']))
+ && (($token->value === '(') || ($token->value === ')'))
+ ) {
+ break;
+ }
+ if ($token->value === '(') {
+ ++$brackets;
+ if ((empty($ret->function)) && ($prev !== null) && ($prev !== true)) {
+ // A function name was previously found and now an open
+ // bracket, so this is a function call.
+ $ret->function = $prev;
+ }
+ $isExpr = true;
+ } elseif ($token->value === ')') {
+ --$brackets;
+ if ($brackets === 0) {
+ if (!empty($options['bracketsDelimited'])) {
+ // The current token is the last brackets, the next
+ // one will be outside.
+ $ret->expr .= $token->token;
+ ++$list->idx;
+ break;
+ }
+ } elseif ($brackets < 0) {
+ $parser->error(__('Unexpected closing bracket.'), $token);
+ $brackets = 0;
+ }
+ } elseif ($token->value === ',') {
+ if ($brackets === 0) {
+ break;
+ }
+ }
+ }
+
+ if (($token->type === Token::TYPE_NUMBER) || ($token->type === Token::TYPE_BOOL)
+ || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE))
+ || (($token->type === Token::TYPE_OPERATOR)) && ($token->value !== '.')
+ ) {
+ // Numbers, booleans and operators are usually part of expressions.
+ $isExpr = true;
+ }
+
+ if ($alias) {
+ // An alias is expected (the keyword `AS` was previously found).
+ if (!empty($ret->alias)) {
+ $parser->error(__('An alias was previously found.'), $token);
+ }
+ $ret->alias = $token->value;
+ $alias = 0;
+ } else {
+ if (!$isExpr) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '.')) {
+ // Found a `.` which means we expect a column name and
+ // the column name we parsed is actually the table name
+ // and the table name is actually a database name.
+ if ((!empty($ret->database)) || ($dot)) {
+ $parser->error(__('Unexpected dot.'), $token);
+ }
+ $ret->database = $ret->table;
+ $ret->table = $ret->column;
+ $ret->column = null;
+ $dot = true;
+ } else {
+ // We found the name of a column (or table if column
+ // field should be skipped; used to parse table names).
+ $field = (!empty($options['skipColumn'])) ? 'table' : 'column';
+ if (!empty($ret->$field)) {
+
+ // No alias is expected.
+ if (!empty($options['noAlias'])) {
+ break;
+ }
+
+ // Parsing aliases without `AS` keyword and any
+ // whitespace.
+ // Example: SELECT 1`foo`
+ if (($token->type === Token::TYPE_STRING)
+ || (($token->type === Token::TYPE_SYMBOL)
+ && ($token->flags & Token::FLAG_SYMBOL_BACKTICK))
+ ) {
+ if (!empty($ret->alias)) {
+ $parser->error(
+ __('An alias was previously found.'),
+ $token
+ );
+ }
+ $ret->alias = $token->value;
+ }
+ } else {
+ $ret->$field = $token->value;
+ }
+ $dot = false;
+ }
+ } else {
+ // Parsing aliases without `AS` keyword.
+ // Example: SELECT 'foo' `bar`
+ if (($brackets === 0) && (empty($options['noAlias']))) {
+ if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING)
+ || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK))
+ ) {
+ if (!empty($ret->alias)) {
+ $parser->error(
+ __('An alias was previously found.'),
+ $token
+ );
+ }
+ $ret->alias = $token->value;
+ continue;
+ }
+ }
+ }
+
+ $ret->expr .= $token->token;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_FUNCTION)) {
+ $prev = strtoupper($token->value);
+ } elseif (($token->type === Token::TYPE_OPERATOR) || ($token->value === '(')) {
+ $prev = true;
+ } else {
+ $prev = null;
+ }
+ }
+
+ if ($alias === 2) {
+ $parser->error(
+ __('An alias was expected.'),
+ $list->tokens[$list->idx - 1]
+ );
+ }
+
+ // Whitespaces might be added at the end.
+ $ret->expr = trim($ret->expr);
+
+ if (empty($ret->expr)) {
+ return null;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param Expression|Expression[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return implode($component, ', ');
+ } else {
+ if (!empty($component->expr)) {
+ $ret = $component->expr;
+ } else {
+ $fields = array();
+ if ((isset($component->database)) && ($component->database !== '')) {
+ $fields[] = $component->database;
+ }
+ if ((isset($component->table)) && ($component->table !== '')) {
+ $fields[] = $component->table;
+ }
+ if ((isset($component->column)) && ($component->column !== '')) {
+ $fields[] = $component->column;
+ }
+ $ret = implode('.', Context::escape($fields));
+ }
+
+ if (!empty($component->alias)) {
+ $ret .= ' AS ' . Context::escape($component->alias);
+ }
+
+ return $ret;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/ExpressionArray.php b/libraries/sql-parser/src/Components/ExpressionArray.php
new file mode 100644
index 0000000000..8327296fe4
--- /dev/null
+++ b/libraries/sql-parser/src/Components/ExpressionArray.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * Parses a a list of expressions delimited by a comma.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses a a list of expressions delimited by a comma.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ExpressionArray extends Component
+{
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return Expression[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ----------------------[ array ]---------------------> 1
+ *
+ * 1 ------------------------[ , ]------------------------> 0
+ * 1 -----------------------[ else ]----------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD)
+ && ($token->flags & Token::FLAG_KEYWORD_RESERVED)
+ && ($token->value !== 'DUAL')
+ ) {
+ // No keyword is expected.
+ break;
+ }
+
+ if ($state === 0) {
+ $expr = Expression::parse($parser, $list, $options);
+ if ($expr === null) {
+ break;
+ }
+ $ret[] = $expr;
+ $state = 1;
+ } elseif ($state === 1) {
+ if ($token->value === ',') {
+ $state = 0;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if ($state === 0) {
+ $parser->error(
+ __('An expression was expected.'),
+ $list->tokens[$list->idx]
+ );
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param Expression[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ $ret = array();
+ foreach ($component as $frag) {
+ $ret[] = $frag::build($frag);
+ }
+ return implode($ret, ', ');
+ }
+}
diff --git a/libraries/sql-parser/src/Components/FunctionCall.php b/libraries/sql-parser/src/Components/FunctionCall.php
new file mode 100644
index 0000000000..54e95ac25a
--- /dev/null
+++ b/libraries/sql-parser/src/Components/FunctionCall.php
@@ -0,0 +1,126 @@
+<?php
+
+/**
+ * Parses a function call.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses a function call.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class FunctionCall extends Component
+{
+
+ /**
+ * The name of this function.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * The list of parameters
+ *
+ * @var ArrayObj
+ */
+ public $parameters;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The name of the function to be called.
+ * @param array|ArrayObj $parameters The parameters of this function.
+ */
+ public function __construct($name = null, $parameters = null)
+ {
+ $this->name = $name;
+ if (is_array($parameters)) {
+ $this->parameters = new ArrayObj($parameters);
+ } elseif ($parameters instanceof ArrayObj) {
+ $this->parameters = $parameters;
+ }
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return FunctionCall
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new FunctionCall();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ----------------------[ name ]-----------------------> 1
+ *
+ * 1 --------------------[ parameters ]-------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->name = $token->value;
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $ret->parameters = ArrayObj::parse($parser, $list);
+ }
+ break;
+ }
+
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @param FunctionCall $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ return $component->name . $component->parameters;
+ }
+}
diff --git a/libraries/sql-parser/src/Components/IntoKeyword.php b/libraries/sql-parser/src/Components/IntoKeyword.php
new file mode 100644
index 0000000000..b230308fc6
--- /dev/null
+++ b/libraries/sql-parser/src/Components/IntoKeyword.php
@@ -0,0 +1,150 @@
+<?php
+
+/**
+ * `INTO` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `INTO` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class IntoKeyword extends Component
+{
+
+ /**
+ * Type of target (OUTFILE or SYMBOL).
+ *
+ * @var string
+ */
+ public $type;
+
+ /**
+ * The destination, which can be a table or a file.
+ *
+ * @var string|Expression
+ */
+ public $dest;
+
+ /**
+ * The name of the columns.
+ *
+ * @var array
+ */
+ public $columns;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return IntoKeyword
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new IntoKeyword();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -----------------------[ name ]----------------------> 1
+ * 0 ---------------------[ OUTFILE ]---------------------> 2
+ *
+ * 1 ------------------------[ ( ]------------------------> (END)
+ *
+ * 2 ---------------------[ filename ]--------------------> 1
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ if (($state === 0) && ($token->value === 'OUTFILE')) {
+ $ret->type = 'OUTFILE';
+ $state = 2;
+ continue;
+ }
+
+ // No other keyword is expected.
+ break;
+ }
+
+ if ($state === 0) {
+ $ret->dest = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ )
+ );
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $ret->columns = ArrayObj::parse($parser, $list)->values;
+ ++$list->idx;
+ }
+ break;
+ } elseif ($state === 2) {
+ $ret->dest = $token->value;
+ ++$list->idx;
+ break;
+ }
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param IntoKeyword $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if ($component->dest instanceof Expression) {
+ $columns = !empty($component->columns) ?
+ '(' . implode(', ', $component->columns) . ')' : '';
+ return $component->dest . $columns;
+ } else {
+ return 'OUTFILE "' . $component->dest . '"';
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/JoinKeyword.php b/libraries/sql-parser/src/Components/JoinKeyword.php
new file mode 100644
index 0000000000..529763bed5
--- /dev/null
+++ b/libraries/sql-parser/src/Components/JoinKeyword.php
@@ -0,0 +1,167 @@
+<?php
+
+/**
+ * `JOIN` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `JOIN` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class JoinKeyword extends Component
+{
+
+ /**
+ * Types of join.
+ *
+ * @var array
+ */
+ public static $JOINS = array(
+ 'FULL JOIN' => 'FULL',
+ 'INNER JOIN' => 'INNER',
+ 'JOIN' => 'JOIN',
+ 'LEFT JOIN' => 'LEFT',
+ 'RIGHT JOIN' => 'RIGHT',
+ );
+
+ /**
+ * Type of this join.
+ *
+ * @see static::$JOINS
+ * @var string
+ */
+ public $type;
+
+ /**
+ * Join expression.
+ *
+ * @var Expression
+ */
+ public $expr;
+
+ /**
+ * Join conditions.
+ *
+ * @var Condition[]
+ */
+ public $on;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return JoinKeyword[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new JoinKeyword();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -----------------------[ JOIN ]----------------------> 1
+ *
+ * 1 -----------------------[ expr ]----------------------> 2
+ *
+ * 2 ------------------------[ ON ]-----------------------> 3
+ *
+ * 3 --------------------[ conditions ]-------------------> 0
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ // By design, the parser will parse first token after the keyword.
+ // In this case, the keyword must be analyzed too, in order to determine
+ // the type of this join.
+ if ($list->idx > 0) {
+ --$list->idx;
+ }
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ if (($token->type === Token::TYPE_KEYWORD)
+ && (!empty(static::$JOINS[$token->value]))
+ ) {
+ $expr->type = static::$JOINS[$token->value];
+ $state = 1;
+ } else {
+ break;
+ }
+ } elseif ($state === 1) {
+ $expr->expr = Expression::parse($parser, $list, array('skipColumn' => true));
+ $state = 2;
+ } elseif ($state === 2) {
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'ON')) {
+ $state = 3;
+ }
+ } else if ($state === 3) {
+ $expr->on = Condition::parse($parser, $list);
+ $ret[] = $expr;
+ $expr = new JoinKeyword();
+ $state = 0;
+ }
+
+ }
+
+ if (!empty($expr->type)) {
+ $ret[] = $expr;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param JoinKeyword[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ $ret = array();
+ foreach ($component as $c) {
+ $ret[] = (($c->type === 'JOIN') ? 'JOIN ' : ($c->type . ' JOIN '))
+ . $c->expr . ' ON ' . Condition::build($c->on);
+ }
+ return implode(' ', $ret);
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Key.php b/libraries/sql-parser/src/Components/Key.php
new file mode 100644
index 0000000000..89371fa9f5
--- /dev/null
+++ b/libraries/sql-parser/src/Components/Key.php
@@ -0,0 +1,170 @@
+<?php
+
+/**
+ * Parses the definition of a key.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Context;
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses the definition of a key.
+ *
+ * Used for parsing `CREATE TABLE` statement.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Key extends Component
+{
+
+ /**
+ * All key options.
+ *
+ * @var array
+ */
+ public static $KEY_OPTIONS = array(
+ 'KEY_BLOCK_SIZE' => array(1, 'var'),
+ 'USING' => array(2, 'var'),
+ 'WITH PARSER' => array(3, 'var'),
+ );
+
+ /**
+ * The name of this key.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * Columns.
+ *
+ * @var array
+ */
+ public $columns;
+
+ /**
+ * The type of this key.
+ *
+ * @var string
+ */
+ public $type;
+
+ /**
+ * The options of this key.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The name of the key.
+ * @param array $columns The columns covered by this key.
+ * @param string $type The type of this key.
+ * @param OptionsArray $options The options of this key.
+ */
+ public function __construct($name = null, array $columns = array(),
+ $type = null, $options = null
+ ) {
+ $this->name = $name;
+ $this->columns = $columns;
+ $this->type = $type;
+ $this->options = $options;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return Key[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new Key();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ----------------------[ type ]-----------------------> 1
+ *
+ * 1 ----------------------[ name ]-----------------------> 1
+ * 1 ---------------------[ columns ]---------------------> 2
+ *
+ * 2 ---------------------[ options ]---------------------> 3
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->type = $token->value;
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $ret->columns = ArrayObj::parse($parser, $list)->values;
+ $state = 2;
+ } else {
+ $ret->name = $token->value;
+ }
+ } elseif ($state === 2) {
+ $ret->options = OptionsArray::parse($parser, $list, static::$KEY_OPTIONS);
+ ++$list->idx;
+ break;
+ }
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param Key $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ $ret = $component->type . ' ';
+ if (!empty($component->name)) {
+ $ret .= Context::escape($component->name) . ' ';
+ }
+ $ret .= '(' . implode(',', Context::escape($component->columns)) . ') '
+ . $component->options;
+ return trim($ret);
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Limit.php b/libraries/sql-parser/src/Components/Limit.php
new file mode 100644
index 0000000000..edf663aab1
--- /dev/null
+++ b/libraries/sql-parser/src/Components/Limit.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * `LIMIT` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `LIMIT` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Limit extends Component
+{
+
+ /**
+ * The number of rows skipped.
+ *
+ * @var int
+ */
+ public $offset;
+
+ /**
+ * The number of rows to be returned.
+ *
+ * @var int
+ */
+ public $rowCount;
+
+ /**
+ * Constructor.
+ *
+ * @param int $rowCount The row count.
+ * @param int $offset The offset.
+ */
+ public function __construct($rowCount = 0, $offset = 0)
+ {
+ $this->rowCount = $rowCount;
+ $this->offset = $offset;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return Limit
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new Limit();
+
+ $offset = false;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ break;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'OFFSET')) {
+ if ($offset) {
+ $parser->error(__('An offset was expected.'), $token);
+ }
+ $offset = true;
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
+ $ret->offset = $ret->rowCount;
+ $ret->rowCount = 0;
+ continue;
+ }
+
+ if ($offset) {
+ $ret->offset = $token->value;
+ $offset = false;
+ } else {
+ $ret->rowCount = $token->value;
+ }
+ }
+
+ if ($offset) {
+ $parser->error(
+ __('An offset was expected.'),
+ $list->tokens[$list->idx - 1]
+ );
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param Limit $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (empty($component->offset)) {
+ return $component->rowCount;
+ } else {
+ return $component->offset . ', ' . $component->rowCount;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/OptionsArray.php b/libraries/sql-parser/src/Components/OptionsArray.php
new file mode 100644
index 0000000000..f24635ad47
--- /dev/null
+++ b/libraries/sql-parser/src/Components/OptionsArray.php
@@ -0,0 +1,344 @@
+<?php
+
+/**
+ * Parses a list of options.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses a list of options.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class OptionsArray extends Component
+{
+
+ /**
+ * ArrayObj of selected options.
+ *
+ * @var array
+ */
+ public $options = array();
+
+ /**
+ * Constructor.
+ *
+ * @param array $options The array of options. Options that have a value
+ * must be an array with at least two keys `name` and
+ * `expr` or `value`.
+ */
+ public function __construct(array $options = array())
+ {
+ $this->options = $options;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return OptionsArray
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new OptionsArray();
+
+ /**
+ * The ID that will be assigned to duplicate options.
+ *
+ * @var int $lastAssignedId
+ */
+ $lastAssignedId = count($options) + 1;
+
+ /**
+ * The option that was processed last time.
+ *
+ * @var array $lastOption
+ */
+ $lastOption = null;
+
+ /**
+ * The index of the option that was processed last time.
+ *
+ * @var int $lastOptionId
+ */
+ $lastOptionId = 0;
+
+ /**
+ * Counts brackets.
+ *
+ * @var int $brackets
+ */
+ $brackets = 0;
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ---------------------[ option ]----------------------> 1
+ *
+ * 1 -------------------[ = (optional) ]------------------> 2
+ *
+ * 2 ----------------------[ value ]----------------------> 0
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping comments.
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ // Skipping whitespace if not parsing value.
+ if (($token->type === Token::TYPE_WHITESPACE) && ($brackets === 0)) {
+ continue;
+ }
+
+ if ($lastOption === null) {
+ $upper = strtoupper($token->token);
+ if (isset($options[$upper])) {
+ $lastOption = $options[$upper];
+ $lastOptionId = is_array($lastOption) ?
+ $lastOption[0] : $lastOption;
+ $state = 0;
+
+ // Checking for option conflicts.
+ // For example, in `SELECT` statements the keywords `ALL`
+ // and `DISTINCT` conflict and if used together, they
+ // produce an invalid query.
+ //
+ // Usually, tokens can be identified in the array by the
+ // option ID, but if conflicts occur, a generated option ID
+ // is used.
+ //
+ // The first pseudo duplicate ID is the maximum value of the
+ // real options (e.g. if there are 5 options, the first
+ // fake ID is 6).
+ if (isset($ret->options[$lastOptionId])) {
+ $parser->error(
+ sprintf(
+ __('This option conflicts with "%1$s".'),
+ $ret->options[$lastOptionId]
+ ),
+ $token
+ );
+ $lastOptionId = $lastAssignedId++;
+ }
+ } else {
+ // There is no option to be processed.
+ break;
+ }
+ }
+
+ if ($state === 0) {
+ if (!is_array($lastOption)) {
+ // This is a just keyword option without any value.
+ // This is the beginning and the end of it.
+ $ret->options[$lastOptionId] = $token->value;
+ $lastOption = null;
+ $state = 0;
+ } elseif (($lastOption[1] === 'var') || ($lastOption[1] === 'var=')) {
+ // This is a keyword that is followed by a value.
+ // This is only the beginning. The value is parsed in state
+ // 1 and 2. State 1 is used to skip the first equals sign
+ // and state 2 to parse the actual value.
+ $ret->options[$lastOptionId] = array(
+ // @var string The name of the option.
+ 'name' => $token->value,
+ // @var bool Whether it contains an equal sign.
+ // This is used by the builder to rebuild it.
+ 'equals' => $lastOption[1] === 'var=',
+ // @var string Raw value.
+ 'expr' => '',
+ // @var string Processed value.
+ 'value' => '',
+ );
+ $state = 1;
+ } elseif ($lastOption[1] === 'expr') {
+ // This is a keyword that is followed by an expression.
+ // The expression is used by the specialized parser.
+
+ // Skipping this option in order to parse the expression.
+ ++$list->idx;
+ $ret->options[$lastOptionId] = array(
+ // @var string The name of the option.
+ 'name' => $token->value,
+ // @var Expression The parsed expression.
+ 'expr' => null,
+ );
+ $state = 1;
+ }
+ } elseif ($state === 1) {
+ $state = 2;
+ if ($token->value === '=') {
+ $ret->options[$lastOptionId]['equals'] = true;
+ continue;
+ }
+ }
+
+ // This is outside the `elseif` group above because the change might
+ // change this iteration.
+ if ($state === 2) {
+ if ($lastOption[1] === 'expr') {
+ $ret->options[$lastOptionId]['expr'] = Expression::parse(
+ $parser,
+ $list,
+ empty($lastOption[2]) ? array() : $lastOption[2]
+ );
+ $ret->options[$lastOptionId]['value']
+ = $ret->options[$lastOptionId]['expr']->expr;
+ $lastOption = null;
+ $state = 0;
+ } else {
+ if ($token->token === '(') {
+ ++$brackets;
+ } elseif ($token->token === ')') {
+ --$brackets;
+ }
+
+ $ret->options[$lastOptionId]['expr'] .= $token->token;
+
+ if (!((($token->token === '(') && ($brackets === 1))
+ || (($token->token === ')') && ($brackets === 0)))
+ ) {
+ // First pair of brackets is being skipped.
+ $ret->options[$lastOptionId]['value'] .= $token->value;
+ }
+
+ // Checking if we finished parsing.
+ if ($brackets === 0) {
+ $lastOption = null;
+ }
+ }
+ }
+ }
+
+ if (empty($options['_UNSORTED'])) {
+ ksort($ret->options);
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param OptionsArray $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (empty($component->options)) {
+ return '';
+ }
+
+ $options = array();
+ foreach ($component->options as $option) {
+ if (!is_array($option)) {
+ $options[] = $option;
+ } else {
+ $options[] = $option['name']
+ . (!empty($option['equals']) ? '=' : ' ')
+ . (!empty($option['expr']) ? $option['expr'] : $option['value']);
+ }
+ }
+ return implode(' ', $options);
+ }
+
+ /**
+ * Checks if it has the specified option and returns it value or true.
+ *
+ * @param string $key The key to be checked.
+ * @param bool $getExpr Gets the expression instead of the value.
+ * The value is the processed form of the expression.
+ *
+ * @return mixed
+ */
+ public function has($key, $getExpr = false)
+ {
+ foreach ($this->options as $option) {
+ if ($key === $option) {
+ return true;
+ } elseif ((is_array($option)) && ($key === $option['name'])) {
+ return $getExpr ? $option['expr'] : $option['value'];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Removes the option from the array.
+ *
+ * @param string $key The key to be removed.
+ *
+ * @return bool Whether the key was found and deleted or not.
+ */
+ public function remove($key)
+ {
+ foreach ($this->options as $idx => $option) {
+ if (($key === $option)
+ || ((is_array($option)) && ($key === $option['name']))
+ ) {
+ unset($this->options[$idx]);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Merges the specified options with these ones. Values with same ID will be
+ * replaced.
+ *
+ * @param array|OptionsArray $options The options to be merged.
+ *
+ * @return void
+ */
+ public function merge($options)
+ {
+ if (is_array($options)) {
+ $this->options = array_merge_recursive($this->options, $options);
+ } elseif ($options instanceof OptionsArray) {
+ $this->options = array_merge_recursive($this->options, $options->options);
+ }
+ }
+
+ /**
+ * Checks tf there are no options set.
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return empty($this->options);
+ }
+}
diff --git a/libraries/sql-parser/src/Components/OrderKeyword.php b/libraries/sql-parser/src/Components/OrderKeyword.php
new file mode 100644
index 0000000000..9c1ad5920d
--- /dev/null
+++ b/libraries/sql-parser/src/Components/OrderKeyword.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * `ORDER BY` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `ORDER BY` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class OrderKeyword extends Component
+{
+
+ /**
+ * The expression that is used for ordering.
+ *
+ * @var Expression
+ */
+ public $expr;
+
+ /**
+ * The order type.
+ *
+ * @var string
+ */
+ public $type;
+
+ /**
+ * Constructor.
+ *
+ * @param Expression $expr The expression that we are sorting by.
+ * @param string $type The sorting type.
+ */
+ public function __construct($expr = null, $type = 'ASC')
+ {
+ $this->expr = $expr;
+ $this->type = $type;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return OrderKeyword[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new OrderKeyword();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 --------------------[ expression ]-------------------> 1
+ *
+ * 1 ------------------------[ , ]------------------------> 0
+ * 1 -------------------[ ASC / DESC ]--------------------> 1
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $expr->expr = Expression::parse($parser, $list);
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_KEYWORD) && (($token->value === 'ASC') || ($token->value === 'DESC'))) {
+ $expr->type = $token->value;
+ } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
+ if (!empty($expr->expr)) {
+ $ret[] = $expr;
+ }
+ $expr = new OrderKeyword();
+ $state = 0;
+ } else {
+ break;
+ }
+ }
+
+ }
+
+ // Last iteration was not processed.
+ if (!empty($expr->expr)) {
+ $ret[] = $expr;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param OrderKeyword|OrderKeyword[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return implode(', ', $component);
+ } else {
+ return $component->expr . ' ' . $component->type;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/ParameterDefinition.php b/libraries/sql-parser/src/Components/ParameterDefinition.php
new file mode 100644
index 0000000000..9ed9cfccb0
--- /dev/null
+++ b/libraries/sql-parser/src/Components/ParameterDefinition.php
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * The definition of a parameter of a function or procedure.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Context;
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * The definition of a parameter of a function or procedure.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ParameterDefinition extends Component
+{
+
+ /**
+ * The name of the new column.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * Parameter's direction (IN, OUT or INOUT).
+ *
+ * @var string
+ */
+ public $inOut;
+
+ /**
+ * The data type of thew new column.
+ *
+ * @var DataType
+ */
+ public $type;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return ParameterDefinition[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new ParameterDefinition();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -----------------------[ ( ]------------------------> 1
+ *
+ * 1 ----------------[ IN / OUT / INOUT ]----------------> 1
+ * 1 ----------------------[ name ]----------------------> 2
+ *
+ * 2 -------------------[ data type ]--------------------> 3
+ *
+ * 3 ------------------------[ , ]-----------------------> 1
+ * 3 ------------------------[ ) ]-----------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $state = 1;
+ }
+ continue;
+ } elseif ($state === 1) {
+ if (($token->value === 'IN') || ($token->value === 'OUT') || ($token->value === 'INOUT')) {
+ $expr->inOut = $token->value;
+ ++$list->idx;
+ } elseif ($token->value === ')') {
+ ++$list->idx;
+ break;
+ } else {
+ $expr->name = $token->value;
+ $state = 2;
+ }
+ } elseif ($state === 2) {
+ $expr->type = DataType::parse($parser, $list);
+ $state = 3;
+ } elseif ($state === 3) {
+ $ret[] = $expr;
+ $expr = new ParameterDefinition();
+ if ($token->value === ',') {
+ $state = 1;
+ } elseif ($token->value === ')') {
+ ++$list->idx;
+ break;
+ }
+ }
+ }
+
+ // Last iteration was not saved.
+ if ((isset($expr->name)) && ($expr->name !== '')) {
+ $ret[] = $expr;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param ParameterDefinition[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return '(' . implode(', ', $component) . ')';
+ } else {
+ $tmp = '';
+ if (!empty($component->inOut)) {
+ $tmp .= $component->inOut . ' ';
+ }
+
+ return trim(
+ $tmp . Context::escape($component->name) . ' ' . $component->type
+ );
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/PartitionDefinition.php b/libraries/sql-parser/src/Components/PartitionDefinition.php
new file mode 100644
index 0000000000..34acbb8244
--- /dev/null
+++ b/libraries/sql-parser/src/Components/PartitionDefinition.php
@@ -0,0 +1,215 @@
+<?php
+
+/**
+ * Parses the create definition of a partition.
+ *
+ * Used for parsing `CREATE TABLE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Context;
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Parses the create definition of a partition.
+ *
+ * Used for parsing `CREATE TABLE` statement.
+ *
+ * @category Components
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class PartitionDefinition extends Component
+{
+
+ /**
+ * All field options.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'STORAGE' => array(1, 'var'),
+ 'STORAGE ENGINE' => array(1, 'var'),
+ 'COMMENT' => array(2, 'var'),
+ 'DATA DIRECTORY' => array(3, 'var'),
+ 'INDEX DIRECTORY' => array(4, 'var'),
+ 'MAX_ROWS' => array(5, 'var'),
+ 'MIN_ROWS' => array(6, 'var'),
+ 'TABLESPACE' => array(7, 'var'),
+ 'NODEGROUP' => array(8, 'var'),
+ );
+
+ /**
+ * Whether this entry is a subpartition or a partition.
+ *
+ * @var bool
+ */
+ public $isSubpartition;
+
+ /**
+ * The name of this partition.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * The type of this partition (what follows the `VALUES` keyword).
+ *
+ * @var string
+ */
+ public $type;
+
+ /**
+ * The expression used to defined this partition.
+ *
+ * @var Expression|string
+ */
+ public $expr;
+
+ /**
+ * The subpartitions of this partition.
+ *
+ * @var PartitionDefinition[]
+ */
+ public $subpartitions;
+
+ /**
+ * The options of this field.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return PartitionDefinition
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new PartitionDefinition();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -------------[ PARTITION | SUBPARTITION ]------------> 1
+ *
+ * 1 -----------------------[ name ]----------------------> 2
+ *
+ * 2 ----------------------[ VALUES ]---------------------> 3
+ *
+ * 3 ---------------------[ LESS THAN ]-------------------> 4
+ * 3 ------------------------[ IN ]-----------------------> 4
+ *
+ * 4 -----------------------[ expr ]----------------------> 5
+ *
+ * 5 ----------------------[ options ]--------------------> 6
+ *
+ * 6 ------------------[ subpartitions ]------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->isSubpartition = ($token->type === Token::TYPE_KEYWORD) && ($token->value === 'SUBPARTITION');
+ $state = 1;
+ } elseif ($state === 1) {
+ $ret->name = $token->value;
+ $state = $ret->isSubpartition ? 5 : 2;
+ } elseif ($state === 2) {
+ $state = 3;
+ } elseif ($state === 3) {
+ $ret->type = $token->value;
+ $state = 4;
+ } elseif ($state === 4) {
+ if ($token->value === 'MAXVALUE') {
+ $ret->expr = $token->value;
+ } else {
+ $ret->expr = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'bracketsDelimited' => true,
+ 'noAlias' => true,
+ )
+ );
+ }
+ $state = 5;
+ } elseif ($state === 5) {
+ $ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
+ $state = 6;
+ } elseif ($state === 6) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $ret->subpartitions = ArrayObj::parse(
+ $parser,
+ $list,
+ array(
+ 'type' => 'SqlParser\\Components\\PartitionDefinition'
+ )
+ );
+ ++$list->idx;
+ }
+ break;
+ }
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param PartitionDefinition|PartitionDefinition[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return "(\n" . implode(",\n", $component) . "\n)";
+ } else {
+ if ($component->isSubpartition) {
+ return 'SUBPARTITION ' . $component->name;
+ } else {
+ $subpartitions = empty($component->subpartitions)
+ ? '' : ' ' . PartitionDefinition::build($component->subpartitions);
+ return 'PARTITION ' . $component->name
+ . ' VALUES ' . $component->type . ' ' . $component->expr
+ . $subpartitions;
+ }
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Reference.php b/libraries/sql-parser/src/Components/Reference.php
new file mode 100644
index 0000000000..6826f7f4ae
--- /dev/null
+++ b/libraries/sql-parser/src/Components/Reference.php
@@ -0,0 +1,152 @@
+<?php
+
+/**
+ * `REFERENCES` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Context;
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `REFERENCES` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Reference extends Component
+{
+
+ /**
+ * All references options.
+ *
+ * @var array
+ */
+ public static $REFERENCES_OPTIONS = array(
+ 'MATCH' => array(1, 'var'),
+ 'ON DELETE' => array(2, 'var'),
+ 'ON UPDATE' => array(3, 'var'),
+ );
+
+ /**
+ * The referenced table.
+ *
+ * @var string
+ */
+ public $table;
+
+ /**
+ * The referenced columns.
+ *
+ * @var array
+ */
+ public $columns;
+
+ /**
+ * The options of the referencing.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * Constructor.
+ *
+ * @param string $table The name of the table referenced.
+ * @param array $columns The columns referenced.
+ * @param OptionsArray $options The options.
+ */
+ public function __construct($table = null, array $columns = array(), $options = null)
+ {
+ $this->table = $table;
+ $this->columns = $columns;
+ $this->options = $options;
+ }
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return Reference
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new Reference();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ----------------------[ table ]---------------------> 1
+ *
+ * 1 ---------------------[ columns ]--------------------> 2
+ *
+ * 2 ---------------------[ options ]--------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->table = $token->value;
+ $state = 1;
+ } elseif ($state === 1) {
+ $ret->columns = ArrayObj::parse($parser, $list)->values;
+ $state = 2;
+ } elseif ($state === 2) {
+ $ret->options = OptionsArray::parse($parser, $list, static::$REFERENCES_OPTIONS);
+ ++$list->idx;
+ break;
+ }
+
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param Reference $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ return trim(
+ Context::escape($component->table)
+ . ' (' . implode(', ', Context::escape($component->columns)) . ') '
+ . $component->options
+ );
+ }
+}
diff --git a/libraries/sql-parser/src/Components/RenameOperation.php b/libraries/sql-parser/src/Components/RenameOperation.php
new file mode 100644
index 0000000000..5f7c9a5723
--- /dev/null
+++ b/libraries/sql-parser/src/Components/RenameOperation.php
@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * `RENAME TABLE` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `RENAME TABLE` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class RenameOperation extends Component
+{
+
+ /**
+ * The old table name.
+ *
+ * @var Expression
+ */
+ public $old;
+
+ /**
+ * The new table name.
+ *
+ * @var Expression
+ */
+ public $new;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return RenameOperation[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new RenameOperation();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 ---------------------[ old name ]--------------------> 1
+ *
+ * 1 ------------------------[ TO ]-----------------------> 2
+ *
+ * 2 ---------------------[ old name ]--------------------> 3
+ *
+ * 3 ------------------------[ , ]------------------------> 0
+ * 3 -----------------------[ else ]----------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $expr->old = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ )
+ );
+ if (empty($expr->old)) {
+ $parser->error(
+ __('The old name of the table was expected.'),
+ $token
+ );
+ }
+ $state = 1;
+ } elseif ($state === 1) {
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'TO')) {
+ $state = 2;
+ } else {
+ $parser->error(
+ __('Keyword "TO" was expected.'),
+ $token
+ );
+ break;
+ }
+ } elseif ($state === 2) {
+ $expr->new = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ 'noAlias' => true,
+ )
+ );
+ if (empty($expr->new)) {
+ $parser->error(
+ __('The new name of the table was expected.'),
+ $token
+ );
+ }
+ $state = 3;
+ } elseif ($state === 3) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
+ $ret[] = $expr;
+ $expr = new RenameOperation();
+ $state = 0;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if ($state !== 3) {
+ $parser->error(
+ __('A rename operation was expected.'),
+ $list->tokens[$list->idx - 1]
+ );
+ }
+
+ // Last iteration was not saved.
+ if (!empty($expr->old)) {
+ $ret[] = $expr;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param RenameOperation $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return implode(', ', $component);
+ } else {
+ return $component->old . ' TO ' . $component->new;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/SetOperation.php b/libraries/sql-parser/src/Components/SetOperation.php
new file mode 100644
index 0000000000..3d04320fb2
--- /dev/null
+++ b/libraries/sql-parser/src/Components/SetOperation.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * `SET` keyword parser.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * `SET` keyword parser.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class SetOperation extends Component
+{
+
+ /**
+ * The name of the column that is being updated.
+ *
+ * @var string
+ */
+ public $column;
+
+ /**
+ * The new value.
+ *
+ * @var string
+ */
+ public $value;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return SetOperation[]
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = array();
+
+ $expr = new SetOperation();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -------------------[ column name ]-------------------> 1
+ *
+ * 1 ------------------------[ , ]------------------------> 0
+ * 1 ----------------------[ value ]----------------------> 1
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ // No keyword is expected.
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ break;
+ }
+
+ if ($state === 0) {
+ if ($token->token === '=') {
+ $state = 1;
+ } else {
+ $expr->column .= $token->token;
+ }
+ } elseif ($state === 1) {
+ if ($token->token === ',') {
+ $expr->column = trim($expr->column);
+ $expr->value = trim($expr->value);
+ $ret[] = $expr;
+ $expr = new SetOperation();
+ $state = 0;
+ } else {
+ $expr->value .= $token->token;
+ }
+ }
+ }
+
+ // Last iteration was not saved.
+ if (!empty($expr->column)) {
+ $expr->column = trim($expr->column);
+ $expr->value = trim($expr->value);
+ $ret[] = $expr;
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param SetOperation|SetOperation[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ if (is_array($component)) {
+ return implode(', ', $component);
+ } else {
+ return $component->column . ' = ' . $component->value;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/UnionKeyword.php b/libraries/sql-parser/src/Components/UnionKeyword.php
new file mode 100644
index 0000000000..d1a1ef5ac4
--- /dev/null
+++ b/libraries/sql-parser/src/Components/UnionKeyword.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * `UNION` keyword builder.
+ *
+ * @package SqlParser
+ * @subpackage Components
+ */
+namespace SqlParser\Components;
+
+use SqlParser\Component;
+use SqlParser\Statements\SelectStatement;
+
+/**
+ * `UNION` keyword builder.
+ *
+ * @category Keywords
+ * @package SqlParser
+ * @subpackage Components
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class UnionKeyword extends Component
+{
+
+ /**
+ * @param SelectStatement[] $component The component to be built.
+ * @param array $options Parameters for building.
+ *
+ * @return string
+ */
+ public static function build($component, array $options = array())
+ {
+ return implode(' UNION ', $component);
+ }
+}
diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php
new file mode 100644
index 0000000000..d6602ce29d
--- /dev/null
+++ b/libraries/sql-parser/src/Context.php
@@ -0,0 +1,524 @@
+<?php
+
+/**
+ * Defines a context class that is later extended to define other contexts.
+ *
+ * A context is a collection of keywords, operators and functions used for
+ * parsing.
+ *
+ * @package SqlParser
+ */
+namespace SqlParser;
+
+/**
+ * Holds the configuration of the context that is currently used.
+ *
+ * @category Contexts
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+abstract class Context
+{
+
+ /**
+ * The maximum length of a keyword.
+ *
+ * @see static::$TOKEN_KEYWORD
+ *
+ * @var int
+ */
+ const KEYWORD_MAX_LENGTH = 30;
+
+ /**
+ * The maximum length of an operator.
+ *
+ * @see static::$TOKEN_OPERATOR
+ *
+ * @var int
+ */
+ const OPERATOR_MAX_LENGTH = 4;
+
+ /**
+ * The name of the default content.
+ *
+ * @var string
+ */
+ public static $defaultContext = '\\SqlParser\\Contexts\\ContextMySql50700';
+
+ /**
+ * The name of the loaded context.
+ *
+ * @var string
+ */
+ public static $loadedContext = '\\SqlParser\\Contexts\\ContextMySql50700';
+
+ /**
+ * The prefix concatenated to the context name when an incomplete class name
+ * is specified.
+ *
+ * @var string
+ */
+ public static $contextPrefix = '\\SqlParser\\Contexts\\Context';
+
+ /**
+ * List of keywords.
+ *
+ * Because, PHP's associative arrays are basically hash tables, it is more
+ * efficient to store keywords as keys instead of values.
+ *
+ * The value associated to each keyword represents its flags.
+ *
+ * @see Token::FLAG_KEYWORD_*
+ *
+ * Elements are sorted by flags, length and keyword.
+ *
+ * @var array
+ */
+ public static $KEYWORDS = array();
+
+ /**
+ * List of operators and their flags.
+ *
+ * @var array
+ */
+ public static $OPERATORS = array(
+
+ // Some operators (*, =) may have ambiguous flags, because they depend on
+ // the context they are being used in.
+ // For example: 1. SELECT * FROM table; # SQL specific (wildcard)
+ // SELECT 2 * 3; # arithmetic
+ // 2. SELECT * FROM table WHERE foo = 'bar';
+ // SET @i = 0;
+
+ // @see Token::FLAG_OPERATOR_ARITHMETIC
+ '%' => 1, '*' => 1, '+' => 1, '-' => 1, '/' => 1,
+
+ // @see Token::FLAG_OPERATOR_LOGICAL
+ '!' => 2, '!=' => 2, '&&' => 2, '<' => 2, '<=' => 2,
+ '<=>' => 2, '<>' => 2, '=' => 2, '>' => 2, '>=' => 2,
+ '||' => 2,
+
+ // @see Token::FLAG_OPERATOR_BITWISE
+ '&' => 4, '<<' => 4, '>>' => 4, '^' => 4, '|' => 4,
+ '~' => 4,
+
+ // @see Token::FLAG_OPERATOR_ASSIGNMENT
+ ':=' => 8,
+
+ // @see Token::FLAG_OPERATOR_SQL
+ '(' => 16, ')' => 16, '.' => 16, ',' => 16,
+ );
+
+ /**
+ * The mode of the MySQL server that will be used in lexing, parsing and
+ * building the statements.
+ *
+ * @var int
+ */
+ public static $MODE = 0;
+
+ /*
+ * Server SQL Modes
+ * https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html
+ */
+
+ // Compatibility mode for Microsoft's SQL server.
+ // This is the equivalent of ANSI_QUOTES.
+ const COMPAT_MYSQL = 2;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_allow_invalid_dates
+ const ALLOW_INVALID_DATES = 1;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_ansi_quotes
+ const ANSI_QUOTES = 2;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_error_for_division_by_zero
+ const ERROR_FOR_DIVISION_BY_ZERO = 4;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_high_not_precedence
+ const HIGH_NOT_PRECEDENCE = 8;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_ignore_space
+ const IGNORE_SPACE = 16;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_auto_create_user
+ const NO_AUTO_CREATE_USER = 32;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_auto_value_on_zero
+ const NO_AUTO_VALUE_ON_ZERO = 64;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_backslash_escapes
+ const NO_BACKSLASH_ESCAPES = 128;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_dir_in_create
+ const NO_DIR_IN_CREATE = 256;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_dir_in_create
+ const NO_ENGINE_SUBSTITUTION = 512;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_field_options
+ const NO_FIELD_OPTIONS = 1024;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_key_options
+ const NO_KEY_OPTIONS = 2048;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_table_options
+ const NO_TABLE_OPTIONS = 4096;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_unsigned_subtraction
+ const NO_UNSIGNED_SUBTRACTION = 8192;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_zero_date
+ const NO_ZERO_DATE = 16384;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_zero_in_date
+ const NO_ZERO_IN_DATE = 32768;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_only_full_group_by
+ const ONLY_FULL_GROUP_BY = 65536;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_pipes_as_concat
+ const PIPES_AS_CONCAT = 131072;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_real_as_float
+ const REAL_AS_FLOAT = 262144;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_all_tables
+ const STRICT_ALL_TABLES = 524288;
+
+ // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_trans_tables
+ const STRICT_TRANS_TABLES = 1048576;
+
+ /*
+ * Combination SQL Modes
+ * https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sql-mode-combo
+ */
+
+ // REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE
+ const SQL_MODE_ANSI = 393234;
+
+ // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
+ // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS,
+ const SQL_MODE_DB2 = 138258;
+
+ // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
+ // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER
+ const SQL_MODE_MAXDB = 138290;
+
+ // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
+ // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS
+ const SQL_MODE_MSSQL = 138258;
+
+ // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
+ // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER
+ const SQL_MODE_ORACLE = 138290;
+
+ // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
+ // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS
+ const SQL_MODE_POSTGRESQL = 138258;
+
+ // STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE,
+ // ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER
+ const SQL_MODE_TRADITIONAL = 1622052;
+
+ // -------------------------------------------------------------------------
+ // Keyword.
+
+ /**
+ * Checks if the given string is a keyword.
+ *
+ * @param string $str String to be checked.
+ * @param bool $isReserved Checks if the keyword is reserved.
+ *
+ * @return int
+ */
+ public static function isKeyword($str, $isReserved = false)
+ {
+ $str = strtoupper($str);
+
+ if (isset(static::$KEYWORDS[$str])) {
+ if ($isReserved) {
+ if (!(static::$KEYWORDS[$str] & Token::FLAG_KEYWORD_RESERVED)) {
+ return null;
+ }
+ }
+ return static::$KEYWORDS[$str];
+ }
+
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+ // Operator.
+
+ /**
+ * Checks if the given string is an operator.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return int The appropriate flag for the operator.
+ */
+ public static function isOperator($str)
+ {
+ if (!isset(static::$OPERATORS[$str])) {
+ return null;
+ }
+ return static::$OPERATORS[$str];
+ }
+
+ // -------------------------------------------------------------------------
+ // Whitespace.
+
+ /**
+ * Checks if the given character is a whitespace.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return bool
+ */
+ public static function isWhitespace($str)
+ {
+ return ($str === ' ') || ($str === "\r") || ($str === "\n") || ($str === "\t");
+ }
+
+ // -------------------------------------------------------------------------
+ // Comment.
+
+ /**
+ * Checks if the given string is the beginning of a whitespace.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return int The appropriate flag for the comment type.
+ */
+ public static function isComment($str)
+ {
+ $len = strlen($str);
+ if ($str[0] === '#') {
+ return Token::FLAG_COMMENT_BASH;
+ } elseif (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
+ return (($len > 2) && ($str[2] == '!')) ?
+ Token::FLAG_COMMENT_MYSQL_CMD : Token::FLAG_COMMENT_C;
+ } elseif (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
+ return Token::FLAG_COMMENT_C;
+ } elseif (($len > 2) && ($str[0] === '-')
+ && ($str[1] === '-') && (static::isWhitespace($str[2]))
+ ) {
+ return Token::FLAG_COMMENT_SQL;
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+ // Bool.
+
+ /**
+ * Checks if the given string is a boolean value.
+ * This actually check only for `TRUE` and `FALSE` because `1` or `0` are
+ * actually numbers and are parsed by specific methods.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return bool
+ */
+ public static function isBool($str)
+ {
+ $str = strtoupper($str);
+ return ($str === 'TRUE') || ($str === 'FALSE');
+ }
+
+ // -------------------------------------------------------------------------
+ // Number.
+
+ /**
+ * Checks if the given character can be a part of a number.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return bool
+ */
+ public static function isNumber($str)
+ {
+ return (($str >= '0') && ($str <= '9')) || ($str === '.')
+ || ($str === '-') || ($str === '+') || ($str === 'e') || ($str === 'E');
+ }
+
+ // -------------------------------------------------------------------------
+ // Symbol.
+
+ /**
+ * Checks if the given character is the beginning of a symbol. A symbol
+ * can be either a variable or a field name.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return int The appropriate flag for the symbol type.
+ */
+ public static function isSymbol($str)
+ {
+ if ($str[0] === '@') {
+ return Token::FLAG_SYMBOL_VARIABLE;
+ } elseif ($str[0] === '`') {
+ return Token::FLAG_SYMBOL_BACKTICK;
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+ // String.
+
+ /**
+ * Checks if the given character is the beginning of a string.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return int The appropriate flag for the string type.
+ */
+ public static function isString($str)
+ {
+ if ($str[0] === '\'') {
+ return Token::FLAG_STRING_SINGLE_QUOTES;
+ } elseif ($str[0] === '"') {
+ return Token::FLAG_STRING_DOUBLE_QUOTES;
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+ // Delimiter.
+
+ /**
+ * Checks if the given character can be a separator for two lexeme.
+ *
+ * @param string $str String to be checked.
+ *
+ * @return bool
+ */
+ public static function isSeparator($str)
+ {
+ // NOTES: Only ASCII characters may be separators.
+ // `~` is the last printable ASCII character.
+ return ($str <= '~') && (!ctype_alnum($str)) && ($str !== '_');
+ }
+
+ /**
+ * Loads the specified context.
+ *
+ * Contexts may be used by accessing the context directly.
+ *
+ * @param string $context Name of the context or full class name that
+ * defines the context.
+ *
+ * @throws \Exception If the specified context doesn't exist.
+ *
+ * @return void
+ */
+ public static function load($context = '')
+ {
+ if (empty($context)) {
+ $context = self::$defaultContext;
+ }
+ if ($context[0] !== '\\') {
+ // Short context name (must be formatted into class name).
+ $context = self::$contextPrefix . $context;
+ }
+ if (!class_exists($context)) {
+ throw new \Exception(
+ 'Specified context ("' . $context . '") does not exist.'
+ );
+ }
+ self::$loadedContext = $context;
+ self::$KEYWORDS = $context::$KEYWORDS;
+ }
+
+ /**
+ * Loads the context with the closest version to the one specified.
+ *
+ * The closest context is found by replacing last digits with zero until one
+ * is loaded successfully.
+ *
+ * @see Context::load()
+ *
+ * @param string $context Name of the context or full class name that
+ * defines the context.
+ *
+ * @return string The loaded context. `null` if no context was loaded.
+ */
+ public static function loadClosest($context = '')
+ {
+ /**
+ * The number of replaces done by `preg_replace`.
+ * This actually represents whether a new context was generated or not.
+ *
+ * @var int $count
+ */
+ $count = 0;
+
+ // As long as a new context can be generated, we try to load it.
+ do {
+ try {
+ // Trying to load the new context.
+ static::load($context);
+ } catch (\Exception $e) {
+ // If it didn't work, we are looking for a new one and skipping
+ // over to the next generation that will try the new context.
+ $context = preg_replace(
+ '/[1-9](0*)$/', '0$1', $context, -1, $count
+ );
+ continue;
+ }
+
+ // Last generated context was valid (did not throw any exceptions).
+ // So we return it, to let the user know what context was loaded.
+ return $context;
+ } while ($count !== 0);
+
+ return null;
+ }
+
+ /**
+ * Sets the SQL mode.
+ *
+ * @param string $mode The list of modes. If empty, the mode is reset.
+ *
+ * @return void
+ */
+ public static function setMode($mode = '')
+ {
+ static::$MODE = 0;
+ if (empty($mode)) {
+ return;
+ }
+ $mode = explode(',', $mode);
+ foreach ($mode as $m) {
+ static::$MODE |= constant('static::' . $m);
+ }
+ }
+
+ /**
+ * Escapes the symbol by adding surrounding backticks.
+ *
+ * @param array|string $str The string to be escaped.
+ * @param string $quote Quote to be used when escaping.
+ *
+ * @return string
+ */
+ public static function escape($str, $quote = '`')
+ {
+ if (is_array($str)) {
+ foreach ($str as $key => $value) {
+ $str[$key] = static::escape($value);
+ }
+ return $str;
+ }
+
+ if (static::$MODE & Context::ANSI_QUOTES) {
+ $quote = '"';
+ }
+ return $quote . str_replace($quote, $quote . $quote, $str) . $quote;
+ }
+}
+
+// Initialing the default context.
+Context::load();
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php
new file mode 100644
index 0000000000..5cbb47cdea
--- /dev/null
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php
@@ -0,0 +1,281 @@
+<?php
+
+/**
+ * Context for MySQL 5.
+ *
+ * This file was auto-generated.
+ *
+ * @package SqlParser
+ * @subpackage Contexts
+ * @link https://dev.mysql.com/doc/refman/5.0/en/keywords.html
+ */
+namespace SqlParser\Contexts;
+
+use SqlParser\Context;
+
+/**
+ * Context for MySQL 5.
+ *
+ * @category Contexts
+ * @package SqlParser
+ * @subpackage Contexts
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ContextMySql50000 extends Context
+{
+
+ /**
+ * List of keywords.
+ *
+ * The value associated to each keyword represents its flags.
+ *
+ * @see Token::FLAG_KEYWORD_*
+ *
+ * @var array
+ */
+ public static $KEYWORDS = array(
+
+ 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1,
+ 'ANY' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1,
+ 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1,
+ 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'FAST' => 1,
+ 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, 'LAST' => 1, 'LOGS' => 1,
+ 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1,
+ 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, 'TYPE' => 1, 'VIEW' => 1,
+ 'WORK' => 1, 'X509' => 1,
+ 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1,
+ 'CHAIN' => 1, 'CLOSE' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1,
+ 'FOUND' => 1, 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1,
+ 'MERGE' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'PHASE' => 1,
+ 'QUERY' => 1, 'QUICK' => 1, 'RAID0' => 1, 'RESET' => 1, 'RTREE' => 1,
+ 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1,
+ 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1,
+ 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1,
+ 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1,
+ 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1,
+ 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1,
+ 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'RELOAD' => 1,
+ 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SIGNED' => 1, 'SIMPLE' => 1,
+ 'SOUNDS' => 1, 'SOURCE' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
+ 'AGAINST' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1,
+ 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1,
+ 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INVOKER' => 1,
+ 'MIGRATE' => 1, 'PARTIAL' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'RECOVER' => 1,
+ 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1,
+ 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1,
+ 'UPGRADE' => 1, 'USE_FRM' => 1, 'VIRTUAL' => 1,
+ 'CASCADED' => 1, 'CHECKSUM' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1,
+ 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1,
+ 'MAX_ROWS' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1,
+ 'ONE_SHOT' => 1, 'PROFILES' => 1, 'ROLLBACK' => 1, 'SECURITY' => 1,
+ 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, 'TRIGGERS' => 1,
+ 'WARNINGS' => 1,
+ 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1,
+ 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1,
+ 'PACK_KEYS' => 1, 'RAID_TYPE' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1,
+ 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1,
+ 'VARIABLES' => 1,
+ 'BERKELEYDB' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1,
+ 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1,
+ 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PRIVILEGES' => 1,
+ 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1,
+ 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1,
+ 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1,
+ 'TRANSACTION' => 1, 'UNCOMMITTED' => 1,
+ 'DES_KEY_FILE' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1,
+ 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1,
+ 'SQL_TSI_YEAR' => 1,
+ 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1,
+ 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1,
+ 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'MASTER_LOG_POS' => 1,
+ 'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1, 'RELAY_LOG_FILE' => 1,
+ 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'USER_RESOURCES' => 1,
+ 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1,
+ 'MASTER_SSL_CERT' => 1, 'SQL_TSI_QUARTER' => 1,
+ 'MASTER_SERVER_ID' => 1,
+ 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1,
+ 'SQL_TSI_FRAC_SECOND' => 1,
+ 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1,
+ 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1,
+ 'MAX_CONNECTIONS_PER_HOUR' => 1,
+
+ 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3,
+ 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3,
+ 'FOR' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, 'USE' => 3,
+ 'XOR' => 3,
+ 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3,
+ 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3,
+ 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3,
+ 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3,
+ 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3,
+ 'WHEN' => 3, 'WITH' => 3,
+ 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3,
+ 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3,
+ 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3,
+ 'OUTER' => 3, 'PURGE' => 3, 'READS' => 3, 'RLIKE' => 3, 'TABLE' => 3,
+ 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, 'WHILE' => 3,
+ 'WRITE' => 3,
+ 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3,
+ 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3,
+ 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'OPTION' => 3, 'REGEXP' => 3,
+ 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3, 'SONAME' => 3,
+ 'UNLOCK' => 3, 'UPDATE' => 3,
+ 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3,
+ 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3,
+ 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3,
+ 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3,
+ 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3,
+ 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, 'OPTIMIZE' => 3,
+ 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3,
+ 'TRAILING' => 3, 'UNSIGNED' => 3, 'ZEROFILL' => 3,
+ 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PRECISION' => 3,
+ 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3,
+ 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3,
+ 'OPTIONALLY' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3,
+ 'YEAR_MONTH' => 3,
+ 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3,
+ 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3,
+ 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3,
+ 'STRAIGHT_JOIN' => 3,
+ 'SQL_BIG_RESULT' => 3,
+ 'DAY_MICROSECOND' => 3,
+ 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3,
+ 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3,
+ 'SQL_CALC_FOUND_ROWS' => 3,
+
+ 'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
+ 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
+ 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
+ 'DATA DIRECTORY' => 7,
+ 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
+ 'GENERATED ALWAYS' => 7,
+ 'START TRANSACTION' => 7,
+ 'SELECT TRANSACTION' => 7,
+ 'DEFAULT CHARACTER SET' => 7,
+ 'WITH CONSISTENT SNAPSHOT' => 7,
+
+ 'XML' => 9,
+ 'ENUM' => 9, 'TEXT' => 9,
+ 'ARRAY' => 9,
+ 'SERIAL' => 9,
+ 'BOOLEAN' => 9,
+ 'DATETIME' => 9, 'MULTISET' => 9,
+
+ 'INT' => 11, 'SET' => 11,
+ 'BLOB' => 11, 'REAL' => 11,
+ 'FLOAT' => 11,
+ 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11,
+ 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11,
+ 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11,
+ 'TINYTEXT' => 11,
+ 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11,
+ 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11,
+
+ 'BINARY VARYING' => 15,
+
+ 'KEY' => 19,
+ 'INDEX' => 19,
+ 'UNIQUE' => 19,
+
+ 'INDEX KEY' => 23,
+ 'UNIQUE KEY' => 23,
+ 'FOREIGN KEY' => 23, 'PRIMARY KEY' => 23, 'SPATIAL KEY' => 23,
+ 'FULLTEXT KEY' => 23, 'UNIQUE INDEX' => 23,
+ 'SPATIAL INDEX' => 23,
+ 'FULLTEXT INDEX' => 23,
+
+ 'X' => 33, 'Y' => 33,
+ 'LN' => 33, 'PI' => 33,
+ 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33,
+ 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33,
+ 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33,
+ 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33,
+ 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33,
+ 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33,
+ 'SHA1' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'TRIM' => 33, 'USER' => 33,
+ 'UUID' => 33, 'WEEK' => 33,
+ 'ASCII' => 33, 'ATAN2' => 33, 'COUNT' => 33, 'CRC32' => 33, 'FIELD' => 33,
+ 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33, 'LEAST' => 33, 'LOG10' => 33,
+ 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33, 'POINT' => 33, 'POWER' => 33,
+ 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33, 'SLEEP' => 33, 'SPACE' => 33,
+ 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33,
+ 'ASTEXT' => 33, 'BIT_OR' => 33, 'CONCAT' => 33, 'DECODE' => 33, 'ENCODE' => 33,
+ 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, 'LENGTH' => 33,
+ 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, 'SECOND' => 33,
+ 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33,
+ 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33,
+ 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33,
+ 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33,
+ 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, 'REVERSE' => 33, 'SOUNDEX' => 33,
+ 'SUBDATE' => 33, 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33,
+ 'VAR_POP' => 33, 'VERSION' => 33, 'WEEKDAY' => 33,
+ 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33,
+ 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33,
+ 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33,
+ 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33,
+ 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33,
+ 'PASSWORD' => 33, 'POSITION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33,
+ 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33,
+ 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33,
+ 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33,
+ 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33,
+ 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33,
+ 'SUBSTRING' => 33,
+ 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33,
+ 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33,
+ 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33,
+ 'STARTPOINT' => 33, 'STDDEV_POP' => 33, 'UNCOMPRESS' => 33, 'WEEKOFYEAR' => 33,
+ 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33,
+ 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'GEOMFROMWKB' => 33,
+ 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33,
+ 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33,
+ 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33,
+ 'TIME_TO_SEC' => 33,
+ 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'GEOMETRYTYPE' => 33,
+ 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33, 'IS_FREE_LOCK' => 33,
+ 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33, 'MLINEFROMWKB' => 33,
+ 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33, 'OCTET_LENGTH' => 33,
+ 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33, 'POLYFROMTEXT' => 33,
+ 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33, 'TIMESTAMPADD' => 33,
+ 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'INTERIORRINGN' => 33,
+ 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33,
+ 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33,
+ 'TIMESTAMPDIFF' => 33,
+ 'LAST_INSERT_ID' => 33, 'MPOINTFROMTEXT' => 33, 'UNIX_TIMESTAMP' => 33,
+ 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33,
+ 'SUBSTRING_INDEX' => 33,
+ 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'NUMINTERIORRINGS' => 33,
+ 'GEOMETRYCOLLECTION' => 33,
+ 'UNCOMPRESSED_LENGTH' => 33,
+
+ 'IF' => 35, 'IN' => 35,
+ 'MOD' => 35,
+ 'LEFT' => 35,
+ 'RIGHT' => 35,
+ 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35,
+ 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35,
+ 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35,
+ 'LOCALTIME' => 35,
+ 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35,
+ 'UTC_TIMESTAMP' => 35,
+ 'LOCALTIMESTAMP' => 35,
+ 'CURRENT_TIMESTAMP' => 35,
+
+ 'NOT IN' => 39,
+
+ 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41,
+ 'TIMESTAMP' => 41,
+
+ 'CHAR' => 43,
+ 'INTERVAL' => 43,
+
+ );
+}
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php
new file mode 100644
index 0000000000..34192ba1bc
--- /dev/null
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php
@@ -0,0 +1,305 @@
+<?php
+
+/**
+ * Context for MySQL 5.1.
+ *
+ * This file was auto-generated.
+ *
+ * @package SqlParser
+ * @subpackage Contexts
+ * @link https://dev.mysql.com/doc/refman/5.1/en/keywords.html
+ */
+namespace SqlParser\Contexts;
+
+use SqlParser\Context;
+
+/**
+ * Context for MySQL 5.1.
+ *
+ * @category Contexts
+ * @package SqlParser
+ * @subpackage Contexts
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ContextMySql50100 extends Context
+{
+
+ /**
+ * List of keywords.
+ *
+ * The value associated to each keyword represents its flags.
+ *
+ * @see Token::FLAG_KEYWORD_*
+ *
+ * @var array
+ */
+ public static $KEYWORDS = array(
+
+ 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1,
+ 'ANY' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1,
+ 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1,
+ 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1,
+ 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'GOTO' => 1, 'HASH' => 1,
+ 'HELP' => 1, 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1,
+ 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1,
+ 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, 'THAN' => 1,
+ 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1,
+ 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1,
+ 'CHAIN' => 1, 'CLOSE' => 1, 'EVENT' => 1, 'EVERY' => 1, 'FIRST' => 1,
+ 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, 'LABEL' => 1,
+ 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1,
+ 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, 'PHASE' => 1, 'QUERY' => 1,
+ 'QUICK' => 1, 'RAID0' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1,
+ 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1,
+ 'UNTIL' => 1, 'VALUE' => 1,
+ 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1,
+ 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1,
+ 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1,
+ 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1,
+ 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'PARSER' => 1,
+ 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1,
+ 'ROLLUP' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1,
+ 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1,
+ 'STRING' => 1, 'TABLES' => 1,
+ 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1,
+ 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1,
+ 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1,
+ 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1,
+ 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1,
+ 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1,
+ 'SESSION' => 1, 'STORAGE' => 1, 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1,
+ 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'VIRTUAL' => 1,
+ 'WRAPPER' => 1,
+ 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1,
+ 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1,
+ 'LANGUAGE' => 1, 'MAXVALUE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1,
+ 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, 'ONE_SHOT' => 1,
+ 'PRESERVE' => 1, 'PROFILES' => 1, 'REDOFILE' => 1, 'ROLLBACK' => 1,
+ 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1,
+ 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1,
+ 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1,
+ 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1,
+ 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, 'RAID_TYPE' => 1,
+ 'READ_ONLY' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, 'SCHEDULER' => 1,
+ 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1,
+ 'UNINSTALL' => 1, 'VARIABLES' => 1,
+ 'BERKELEYDB' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1,
+ 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1,
+ 'MASTER_SSL' => 1, 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1,
+ 'PRIVILEGES' => 1, 'REORGANISE' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1,
+ 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1,
+ 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1,
+ 'MASTER_USER' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1,
+ 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1,
+ 'CONTRIBUTORS' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1,
+ 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1,
+ 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1,
+ 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1,
+ 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'PAGE_CHECKSUM' => 1,
+ 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1,
+ 'TRANSACTIONAL' => 1,
+ 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1,
+ 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1,
+ 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1,
+ 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1,
+ 'AUTOEXTEND_SIZE' => 1, 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1,
+ 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, 'SQL_TSI_QUARTER' => 1,
+ 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'UNDO_BUFFER_SIZE' => 1,
+ 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1,
+ 'SQL_TSI_FRAC_SECOND' => 1,
+ 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1,
+ 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1,
+ 'MAX_CONNECTIONS_PER_HOUR' => 1,
+
+ 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3,
+ 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3,
+ 'FOR' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, 'USE' => 3,
+ 'XOR' => 3,
+ 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3,
+ 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3,
+ 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3,
+ 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3,
+ 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3,
+ 'WHEN' => 3, 'WITH' => 3,
+ 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3,
+ 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3,
+ 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3,
+ 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3,
+ 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3,
+ 'WHILE' => 3, 'WRITE' => 3,
+ 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3,
+ 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3,
+ 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3,
+ 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3,
+ 'UNLOCK' => 3, 'UPDATE' => 3,
+ 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3,
+ 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3,
+ 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3,
+ 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3,
+ 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3,
+ 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, 'OPTIMIZE' => 3,
+ 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3,
+ 'TRAILING' => 3, 'UNSIGNED' => 3, 'ZEROFILL' => 3,
+ 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PRECISION' => 3,
+ 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3,
+ 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3,
+ 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3,
+ 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3,
+ 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3,
+ 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3,
+ 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3,
+ 'STRAIGHT_JOIN' => 3,
+ 'SQL_BIG_RESULT' => 3,
+ 'DAY_MICROSECOND' => 3,
+ 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3,
+ 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3,
+ 'SQL_CALC_FOUND_ROWS' => 3,
+ 'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
+
+ 'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
+ 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
+ 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
+ 'DATA DIRECTORY' => 7,
+ 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
+ 'GENERATED ALWAYS' => 7,
+ 'START TRANSACTION' => 7,
+ 'SELECT TRANSACTION' => 7,
+ 'DEFAULT CHARACTER SET' => 7,
+ 'WITH CONSISTENT SNAPSHOT' => 7,
+
+ 'XML' => 9,
+ 'ENUM' => 9, 'TEXT' => 9,
+ 'ARRAY' => 9,
+ 'SERIAL' => 9,
+ 'BOOLEAN' => 9,
+ 'DATETIME' => 9, 'MULTISET' => 9,
+
+ 'INT' => 11, 'SET' => 11,
+ 'BLOB' => 11, 'REAL' => 11,
+ 'FLOAT' => 11,
+ 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11,
+ 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11,
+ 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11,
+ 'TINYTEXT' => 11,
+ 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11,
+ 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11,
+
+ 'BINARY VARYING' => 15,
+
+ 'KEY' => 19,
+ 'INDEX' => 19,
+ 'UNIQUE' => 19,
+
+ 'INDEX KEY' => 23,
+ 'UNIQUE KEY' => 23,
+ 'FOREIGN KEY' => 23, 'PRIMARY KEY' => 23, 'SPATIAL KEY' => 23,
+ 'FULLTEXT KEY' => 23, 'UNIQUE INDEX' => 23,
+ 'SPATIAL INDEX' => 23,
+ 'FULLTEXT INDEX' => 23,
+
+ 'X' => 33, 'Y' => 33,
+ 'LN' => 33, 'PI' => 33,
+ 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33,
+ 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33,
+ 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33,
+ 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33,
+ 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33,
+ 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33,
+ 'SHA1' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'TRIM' => 33, 'USER' => 33,
+ 'UUID' => 33, 'WEEK' => 33,
+ 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33,
+ 'CRC32' => 33, 'DECOD' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33,
+ 'LCASE' => 33, 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33,
+ 'MONTH' => 33, 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33,
+ 'RTRIM' => 33, 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33,
+ 'UPPER' => 33,
+ 'ASTEXT' => 33, 'BIT_OR' => 33, 'CONCAT' => 33, 'ENCODE' => 33, 'EQUALS' => 33,
+ 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, 'LENGTH' => 33, 'LOCATE' => 33,
+ 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, 'SECOND' => 33, 'STDDEV' => 33,
+ 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33,
+ 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33,
+ 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33,
+ 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33,
+ 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, 'REVERSE' => 33, 'SOUNDEX' => 33,
+ 'SUBDATE' => 33, 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33,
+ 'VAR_POP' => 33, 'VERSION' => 33, 'WEEKDAY' => 33,
+ 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33,
+ 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33,
+ 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33,
+ 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33,
+ 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33,
+ 'PASSWORD' => 33, 'POSITION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33,
+ 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33,
+ 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33,
+ 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33,
+ 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33,
+ 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33,
+ 'SUBSTRING' => 33, 'UPDATEXML' => 33,
+ 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33,
+ 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33,
+ 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33,
+ 'STARTPOINT' => 33, 'STDDEV_POP' => 33, 'UNCOMPRESS' => 33, 'UUID_SHORT' => 33,
+ 'WEEKOFYEAR' => 33,
+ 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33,
+ 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'GEOMFROMWKB' => 33,
+ 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33,
+ 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33,
+ 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33,
+ 'TIME_TO_SEC' => 33,
+ 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33,
+ 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33,
+ 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33,
+ 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33,
+ 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33,
+ 'POLYFROMTEXT' => 33, 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33,
+ 'TIMESTAMPADD' => 33,
+ 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'INTERIORRINGN' => 33,
+ 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33,
+ 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33,
+ 'TIMESTAMPDIFF' => 33,
+ 'LAST_INSERT_ID' => 33, 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33,
+ 'UNIX_TIMESTAMP' => 33,
+ 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33,
+ 'POLYGONFROMTEXT' => 33, 'SUBSTRING_INDEX' => 33,
+ 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33,
+ 'NUMINTERIORRINGS' => 33,
+ 'LINESTRINGFROMWKB' => 33, 'MULTIPOINTFROMWKB' => 33,
+ 'GEOMETRYCOLLECTION' => 33, 'MULTIPOINTFROMTEXT' => 33,
+ 'MULTIPOLYGONFROMWKB' => 33, 'UNCOMPRESSED_LENGTH' => 33,
+ 'MULTIPOLYGONFROMTEXT' => 33,
+ 'MULTILINESTRINGFROMWKB' => 33,
+ 'MULTILINESTRINGFROMTEXT' => 33,
+ 'GEOMETRYCOLLECTIONFROMWKB' => 33,
+ 'GEOMETRYCOLLECTIONFROMTEXT' => 33,
+
+ 'IF' => 35, 'IN' => 35,
+ 'MOD' => 35,
+ 'LEFT' => 35,
+ 'RIGHT' => 35,
+ 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35,
+ 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35,
+ 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35,
+ 'LOCALTIME' => 35,
+ 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35,
+ 'UTC_TIMESTAMP' => 35,
+ 'LOCALTIMESTAMP' => 35,
+ 'CURRENT_TIMESTAMP' => 35,
+
+ 'NOT IN' => 39,
+
+ 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41,
+ 'TIMESTAMP' => 41,
+
+ 'CHAR' => 43,
+ 'INTERVAL' => 43,
+
+ );
+}
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php
new file mode 100644
index 0000000000..e8a32fe3a8
--- /dev/null
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php
@@ -0,0 +1,309 @@
+<?php
+
+/**
+ * Context for MySQL 5.5.
+ *
+ * This file was auto-generated.
+ *
+ * @package SqlParser
+ * @subpackage Contexts
+ * @link https://dev.mysql.com/doc/refman/5.5/en/keywords.html
+ */
+namespace SqlParser\Contexts;
+
+use SqlParser\Context;
+
+/**
+ * Context for MySQL 5.5.
+ *
+ * @category Contexts
+ * @package SqlParser
+ * @subpackage Contexts
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ContextMySql50500 extends Context
+{
+
+ /**
+ * List of keywords.
+ *
+ * The value associated to each keyword represents its flags.
+ *
+ * @see Token::FLAG_KEYWORD_*
+ *
+ * @var array
+ */
+ public static $KEYWORDS = array(
+
+ 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1,
+ 'ANY' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, 'NDB' => 1,
+ 'NEW' => 1, 'ONE' => 1, 'ROW' => 1,
+ 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1,
+ 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1,
+ 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, 'MODE' => 1,
+ 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1, 'PORT' => 1,
+ 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1, 'THAN' => 1,
+ 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1,
+ 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1,
+ 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, 'EVERY' => 1,
+ 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1,
+ 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1,
+ 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, 'PHASE' => 1, 'PROXY' => 1,
+ 'QUERY' => 1, 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1,
+ 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1,
+ 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1,
+ 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1,
+ 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1,
+ 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1,
+ 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1,
+ 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'PARSER' => 1,
+ 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1,
+ 'ROLLUP' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1,
+ 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1,
+ 'STRING' => 1, 'TABLES' => 1,
+ 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1,
+ 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1,
+ 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'GENERAL' => 1, 'HANDLER' => 1,
+ 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1,
+ 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1,
+ 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1,
+ 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1,
+ 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'VIRTUAL' => 1,
+ 'WRAPPER' => 1,
+ 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1,
+ 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1,
+ 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1,
+ 'NATIONAL' => 1, 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PRESERVE' => 1,
+ 'PROFILES' => 1, 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1,
+ 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1,
+ 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1,
+ 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1,
+ 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1,
+ 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, 'READ_ONLY' => 1,
+ 'REDUNDANT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1,
+ 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1,
+ 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1,
+ 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1,
+ 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PRIVILEGES' => 1,
+ 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1,
+ 'TABLESPACE' => 1, 'TABLE_NAME' => 1,
+ 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1,
+ 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1,
+ 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1,
+ 'TRANSACTION' => 1, 'UNCOMMITTED' => 1,
+ 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'CONTRIBUTORS' => 1,
+ 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, 'MESSAGE_TEXT' => 1,
+ 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1,
+ 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1,
+ 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1,
+ 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1,
+ 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1,
+ 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1,
+ 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RELAY_LOG_FILE' => 1,
+ 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'TABLE_CHECKSUM' => 1,
+ 'USER_RESOURCES' => 1,
+ 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1,
+ 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1,
+ 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1,
+ 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'UNDO_BUFFER_SIZE' => 1,
+ 'CONSTRAINT_SCHEMA' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1,
+ 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1,
+ 'CONSTRAINT_CATALOG' => 1,
+ 'SQL_TSI_FRAC_SECOND' => 1,
+ 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1,
+ 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1,
+ 'MASTER_HEARTBEAT_PERIOD' => 1,
+ 'MAX_CONNECTIONS_PER_HOUR' => 1,
+
+ 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3,
+ 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3,
+ 'FOR' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, 'USE' => 3,
+ 'XOR' => 3,
+ 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3,
+ 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3,
+ 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3,
+ 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3,
+ 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3,
+ 'WHEN' => 3, 'WITH' => 3,
+ 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3,
+ 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3,
+ 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3,
+ 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3,
+ 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3,
+ 'WHILE' => 3, 'WRITE' => 3,
+ 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3,
+ 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3,
+ 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3,
+ 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3,
+ 'SIGNAL' => 3, 'UNLOCK' => 3, 'UPDATE' => 3,
+ 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3,
+ 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3,
+ 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3,
+ 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3,
+ 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3,
+ 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, 'MODIFIES' => 3,
+ 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3,
+ 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3,
+ 'ZEROFILL' => 3,
+ 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PRECISION' => 3,
+ 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3,
+ 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3,
+ 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3,
+ 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3,
+ 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3,
+ 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3,
+ 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3,
+ 'STRAIGHT_JOIN' => 3,
+ 'SQL_BIG_RESULT' => 3,
+ 'DAY_MICROSECOND' => 3,
+ 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3,
+ 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3,
+ 'SQL_CALC_FOUND_ROWS' => 3,
+ 'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
+
+ 'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
+ 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
+ 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
+ 'DATA DIRECTORY' => 7,
+ 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
+ 'GENERATED ALWAYS' => 7,
+ 'START TRANSACTION' => 7,
+ 'SELECT TRANSACTION' => 7,
+ 'DEFAULT CHARACTER SET' => 7,
+ 'WITH CONSISTENT SNAPSHOT' => 7,
+
+ 'XML' => 9,
+ 'ENUM' => 9, 'TEXT' => 9,
+ 'ARRAY' => 9,
+ 'SERIAL' => 9,
+ 'BOOLEAN' => 9,
+ 'DATETIME' => 9, 'MULTISET' => 9,
+
+ 'INT' => 11, 'SET' => 11,
+ 'BLOB' => 11, 'REAL' => 11,
+ 'FLOAT' => 11,
+ 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11,
+ 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11,
+ 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11,
+ 'TINYTEXT' => 11,
+ 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11,
+ 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11,
+
+ 'BINARY VARYING' => 15,
+
+ 'KEY' => 19,
+ 'INDEX' => 19,
+ 'UNIQUE' => 19,
+
+ 'INDEX KEY' => 23,
+ 'UNIQUE KEY' => 23,
+ 'FOREIGN KEY' => 23, 'PRIMARY KEY' => 23, 'SPATIAL KEY' => 23,
+ 'FULLTEXT KEY' => 23, 'UNIQUE INDEX' => 23,
+ 'SPATIAL INDEX' => 23,
+ 'FULLTEXT INDEX' => 23,
+
+ 'X' => 33, 'Y' => 33,
+ 'LN' => 33, 'PI' => 33,
+ 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33,
+ 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33,
+ 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33,
+ 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33,
+ 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33,
+ 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33,
+ 'SHA1' => 33, 'SHA2' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'TRIM' => 33,
+ 'USER' => 33, 'UUID' => 33, 'WEEK' => 33,
+ 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33,
+ 'CRC32' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33,
+ 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33,
+ 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33,
+ 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33,
+ 'ASTEXT' => 33, 'BIT_OR' => 33, 'CONCAT' => 33, 'DECODE' => 33, 'ENCODE' => 33,
+ 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, 'LENGTH' => 33,
+ 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, 'SECOND' => 33,
+ 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33,
+ 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33,
+ 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33,
+ 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33,
+ 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, 'REVERSE' => 33, 'SOUNDEX' => 33,
+ 'SUBDATE' => 33, 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33,
+ 'VAR_POP' => 33, 'VERSION' => 33, 'WEEKDAY' => 33,
+ 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33,
+ 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33,
+ 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33,
+ 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33,
+ 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33,
+ 'PASSWORD' => 33, 'POSITION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33,
+ 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33,
+ 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33,
+ 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33,
+ 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33,
+ 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33,
+ 'SUBSTRING' => 33, 'UPDATEXML' => 33,
+ 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33,
+ 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33,
+ 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33,
+ 'STARTPOINT' => 33, 'STDDEV_POP' => 33, 'TO_SECONDS' => 33, 'UNCOMPRESS' => 33,
+ 'UUID_SHORT' => 33, 'WEEKOFYEAR' => 33,
+ 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33,
+ 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'GEOMFROMWKB' => 33,
+ 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33,
+ 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33,
+ 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33,
+ 'TIME_TO_SEC' => 33,
+ 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33,
+ 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33,
+ 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33,
+ 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33,
+ 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33,
+ 'POLYFROMTEXT' => 33, 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33,
+ 'TIMESTAMPADD' => 33,
+ 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'INTERIORRINGN' => 33,
+ 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33,
+ 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33,
+ 'TIMESTAMPDIFF' => 33,
+ 'LAST_INSERT_ID' => 33, 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33,
+ 'UNIX_TIMESTAMP' => 33,
+ 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33,
+ 'POLYGONFROMTEXT' => 33, 'SUBSTRING_INDEX' => 33,
+ 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33,
+ 'NUMINTERIORRINGS' => 33,
+ 'LINESTRINGFROMWKB' => 33, 'MULTIPOINTFROMWKB' => 33,
+ 'GEOMETRYCOLLECTION' => 33, 'MULTIPOINTFROMTEXT' => 33,
+ 'MULTIPOLYGONFROMWKB' => 33, 'UNCOMPRESSED_LENGTH' => 33,
+ 'MULTIPOLYGONFROMTEXT' => 33,
+ 'MULTILINESTRINGFROMWKB' => 33,
+ 'MULTILINESTRINGFROMTEXT' => 33,
+ 'GEOMETRYCOLLECTIONFROMWKB' => 33,
+ 'GEOMETRYCOLLECTIONFROMTEXT' => 33,
+
+ 'IF' => 35, 'IN' => 35,
+ 'MOD' => 35,
+ 'LEFT' => 35,
+ 'RIGHT' => 35,
+ 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35,
+ 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35,
+ 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35,
+ 'LOCALTIME' => 35,
+ 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35,
+ 'UTC_TIMESTAMP' => 35,
+ 'LOCALTIMESTAMP' => 35,
+ 'CURRENT_TIMESTAMP' => 35,
+
+ 'NOT IN' => 39,
+
+ 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41,
+ 'TIMESTAMP' => 41,
+
+ 'CHAR' => 43,
+ 'INTERVAL' => 43,
+
+ );
+}
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php
new file mode 100644
index 0000000000..c09425b0b9
--- /dev/null
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php
@@ -0,0 +1,339 @@
+<?php
+
+/**
+ * Context for MySQL 5.6.
+ *
+ * This file was auto-generated.
+ *
+ * @package SqlParser
+ * @subpackage Contexts
+ * @link https://dev.mysql.com/doc/refman/5.6/en/keywords.html
+ */
+namespace SqlParser\Contexts;
+
+use SqlParser\Context;
+
+/**
+ * Context for MySQL 5.6.
+ *
+ * @category Contexts
+ * @package SqlParser
+ * @subpackage Contexts
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ContextMySql50600 extends Context
+{
+
+ /**
+ * List of keywords.
+ *
+ * The value associated to each keyword represents its flags.
+ *
+ * @see Token::FLAG_KEYWORD_*
+ *
+ * @var array
+ */
+ public static $KEYWORDS = array(
+
+ 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1,
+ 'ANY' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, 'NDB' => 1,
+ 'NEW' => 1, 'ONE' => 1, 'ROW' => 1,
+ 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1,
+ 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1,
+ 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, 'MODE' => 1,
+ 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, 'PAGE' => 1,
+ 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1,
+ 'THAN' => 1, 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1,
+ 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1,
+ 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, 'EVERY' => 1,
+ 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1,
+ 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1,
+ 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, 'PHASE' => 1, 'PROXY' => 1,
+ 'QUERY' => 1, 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1,
+ 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1,
+ 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1,
+ 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1,
+ 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1,
+ 'EVENTS' => 1, 'EXPIRE' => 1, 'EXPORT' => 1, 'FAULTS' => 1, 'FIELDS' => 1,
+ 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'ISSUER' => 1, 'LEAVES' => 1,
+ 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'NUMBER' => 1,
+ 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1,
+ 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SERVER' => 1, 'SIGNED' => 1,
+ 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1,
+ 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
+ 'AGAINST' => 1, 'ANALYSE' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1,
+ 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1, 'DEFINER' => 1,
+ 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1,
+ 'GENERAL' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1,
+ 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1,
+ 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1,
+ 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1,
+ 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1,
+ 'USE_FRM' => 1, 'VIRTUAL' => 1, 'WRAPPER' => 1,
+ 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1,
+ 'EXCHANGE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1,
+ 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1,
+ 'NATIONAL' => 1, 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PRESERVE' => 1,
+ 'PROFILES' => 1, 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1,
+ 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1,
+ 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1,
+ 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1,
+ 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1,
+ 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, 'REDUNDANT' => 1,
+ 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1,
+ 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1,
+ 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1,
+ 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1,
+ 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PLUGIN_DIR' => 1,
+ 'PRIVILEGES' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1,
+ 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'TABLE_NAME' => 1,
+ 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, 'EXTENT_SIZE' => 1,
+ 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1,
+ 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1,
+ 'TRANSACTION' => 1, 'UNCOMMITTED' => 1,
+ 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'CONTRIBUTORS' => 1,
+ 'DEFAULT_AUTH' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1,
+ 'MASTER_DELAY' => 1, 'MESSAGE_TEXT' => 1, 'PARTITIONING' => 1,
+ 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1,
+ 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1,
+ 'SUBPARTITION' => 1,
+ 'COLUMN_FORMAT' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1,
+ 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1,
+ 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1,
+ 'MASTER_LOG_POS' => 1, 'MASTER_SSL_CRL' => 1, 'MASTER_SSL_KEY' => 1,
+ 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1,
+ 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1,
+ 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1,
+ 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1,
+ 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1,
+ 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'SQL_BEFORE_GTIDS' => 1,
+ 'STATS_PERSISTENT' => 1, 'UNDO_BUFFER_SIZE' => 1,
+ 'CONSTRAINT_SCHEMA' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1,
+ 'MASTER_SSL_CIPHER' => 1, 'RETURNED_SQLSTATE' => 1, 'SQL_BUFFER_RESULT' => 1,
+ 'STATS_AUTO_RECALC' => 1,
+ 'CONSTRAINT_CATALOG' => 1, 'MASTER_RETRY_COUNT' => 1, 'MASTER_SSL_CRLPATH' => 1,
+ 'SQL_AFTER_MTS_GAPS' => 1, 'STATS_SAMPLE_PAGES' => 1,
+ 'MASTER_AUTO_POSITION' => 1, 'MASTER_CONNECT_RETRY' => 1,
+ 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1,
+ 'MAX_USER_CONNECTIONS' => 1,
+ 'MASTER_HEARTBEAT_PERIOD' => 1,
+ 'MAX_CONNECTIONS_PER_HOUR' => 1,
+
+ 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3,
+ 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3,
+ 'FOR' => 3, 'GET' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3,
+ 'USE' => 3, 'XOR' => 3,
+ 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3,
+ 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3,
+ 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3,
+ 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3,
+ 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3,
+ 'WHEN' => 3, 'WITH' => 3,
+ 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3,
+ 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3,
+ 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3,
+ 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3,
+ 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3,
+ 'WHILE' => 3, 'WRITE' => 3,
+ 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3,
+ 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3,
+ 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3,
+ 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3,
+ 'SIGNAL' => 3, 'UNLOCK' => 3, 'UPDATE' => 3,
+ 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3,
+ 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3,
+ 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3,
+ 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3,
+ 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3,
+ 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, 'MODIFIES' => 3,
+ 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3,
+ 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3,
+ 'ZEROFILL' => 3,
+ 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PARTITION' => 3,
+ 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3,
+ 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3,
+ 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3,
+ 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3,
+ 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3,
+ 'MASTER_BIND' => 3,
+ 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3,
+ 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3,
+ 'STRAIGHT_JOIN' => 3,
+ 'IO_AFTER_GTIDS' => 3, 'SQL_BIG_RESULT' => 3,
+ 'DAY_MICROSECOND' => 3, 'IO_BEFORE_GTIDS' => 3,
+ 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3,
+ 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3,
+ 'SQL_CALC_FOUND_ROWS' => 3,
+ 'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
+
+ 'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
+ 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
+ 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
+ 'DATA DIRECTORY' => 7,
+ 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
+ 'GENERATED ALWAYS' => 7,
+ 'START TRANSACTION' => 7,
+ 'SELECT TRANSACTION' => 7,
+ 'DEFAULT CHARACTER SET' => 7,
+ 'WITH CONSISTENT SNAPSHOT' => 7,
+
+ 'XML' => 9,
+ 'ENUM' => 9, 'TEXT' => 9,
+ 'ARRAY' => 9,
+ 'SERIAL' => 9,
+ 'BOOLEAN' => 9,
+ 'DATETIME' => 9, 'MULTISET' => 9,
+
+ 'INT' => 11, 'SET' => 11,
+ 'BLOB' => 11, 'REAL' => 11,
+ 'FLOAT' => 11,
+ 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11,
+ 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11,
+ 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11,
+ 'TINYTEXT' => 11,
+ 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11,
+ 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11,
+
+ 'BINARY VARYING' => 15,
+
+ 'KEY' => 19,
+ 'INDEX' => 19,
+ 'UNIQUE' => 19,
+
+ 'INDEX KEY' => 23,
+ 'UNIQUE KEY' => 23,
+ 'FOREIGN KEY' => 23, 'PRIMARY KEY' => 23, 'SPATIAL KEY' => 23,
+ 'FULLTEXT KEY' => 23, 'UNIQUE INDEX' => 23,
+ 'SPATIAL INDEX' => 23,
+ 'FULLTEXT INDEX' => 23,
+
+ 'X' => 33, 'Y' => 33,
+ 'LN' => 33, 'PI' => 33,
+ 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33,
+ 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33,
+ 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33,
+ 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33,
+ 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33,
+ 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33,
+ 'SHA1' => 33, 'SHA2' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'ST_X' => 33,
+ 'ST_Y' => 33, 'TRIM' => 33, 'USER' => 33, 'UUID' => 33, 'WEEK' => 33,
+ 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33,
+ 'CRC32' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33,
+ 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33,
+ 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33,
+ 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33,
+ 'ASTEXT' => 33, 'BIT_OR' => 33, 'BUFFER' => 33, 'CONCAT' => 33, 'DECODE' => 33,
+ 'ENCODE' => 33, 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33,
+ 'LENGTH' => 33, 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33,
+ 'SECOND' => 33, 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33,
+ 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33,
+ 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33,
+ 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33,
+ 'IS_IPV4' => 33, 'IS_IPV6' => 33, 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33,
+ 'REVERSE' => 33, 'SOUNDEX' => 33, 'ST_AREA' => 33, 'ST_SRID' => 33, 'SUBDATE' => 33,
+ 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, 'VAR_POP' => 33,
+ 'VERSION' => 33, 'WEEKDAY' => 33,
+ 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33,
+ 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33,
+ 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33,
+ 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33,
+ 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33,
+ 'PASSWORD' => 33, 'POSITION' => 33, 'ST_ASWKB' => 33, 'ST_ASWKT' => 33,
+ 'ST_UNION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33, 'VARIANCE' => 33,
+ 'VAR_SAMP' => 33, 'YEARWEEK' => 33,
+ 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33,
+ 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33,
+ 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33,
+ 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33,
+ 'ST_ASTEXT' => 33, 'ST_BUFFER' => 33, 'ST_EQUALS' => 33, 'ST_POINTN' => 33,
+ 'ST_WITHIN' => 33, 'SUBSTRING' => 33, 'TO_BASE64' => 33, 'UPDATEXML' => 33,
+ 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33,
+ 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INET6_ATON' => 33, 'INET6_NTOA' => 33,
+ 'INTERSECTS' => 33, 'LINESTRING' => 33, 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33,
+ 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, 'STARTPOINT' => 33, 'STDDEV_POP' => 33,
+ 'ST_CROSSES' => 33, 'ST_ISEMPTY' => 33, 'ST_TOUCHES' => 33, 'TO_SECONDS' => 33,
+ 'UNCOMPRESS' => 33, 'UUID_SHORT' => 33, 'WEEKOFYEAR' => 33,
+ 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33,
+ 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'FROM_BASE64' => 33,
+ 'GEOMFROMWKB' => 33, 'GTID_SUBSET' => 33, 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33,
+ 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33,
+ 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33,
+ 'ST_ASBINARY' => 33, 'ST_CENTROID' => 33, 'ST_CONTAINS' => 33, 'ST_DISJOINT' => 33,
+ 'ST_DISTANCE' => 33, 'ST_ENDPOINT' => 33, 'ST_ENVELOPE' => 33, 'ST_ISCLOSED' => 33,
+ 'ST_ISSIMPLE' => 33, 'ST_OVERLAPS' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33,
+ 'TIME_TO_SEC' => 33,
+ 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33,
+ 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33,
+ 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33,
+ 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33,
+ 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33,
+ 'POLYFROMTEXT' => 33, 'RANDOM_BYTES' => 33, 'RELEASE_LOCK' => 33,
+ 'SESSION_USER' => 33, 'ST_DIMENSION' => 33, 'ST_GEOMETRYN' => 33,
+ 'ST_NUMPOINTS' => 33, 'TIMESTAMPADD' => 33,
+ 'CONNECTION_ID' => 33, 'CREATE_DIGEST' => 33, 'FROM_UNIXTIME' => 33,
+ 'GTID_SUBTRACT' => 33, 'INTERIORRINGN' => 33, 'MBRINTERSECTS' => 33,
+ 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33, 'MPOLYFROMTEXT' => 33,
+ 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33, 'ST_DIFFERENCE' => 33,
+ 'ST_INTERSECTS' => 33, 'ST_STARTPOINT' => 33, 'TIMESTAMPDIFF' => 33,
+ 'WEIGHT_STRING' => 33,
+ 'IS_IPV4_COMPAT' => 33, 'IS_IPV4_MAPPED' => 33, 'LAST_INSERT_ID' => 33,
+ 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33, 'ST_GEOMFROMWKB' => 33,
+ 'ST_LINEFROMWKB' => 33, 'ST_POLYFROMWKB' => 33, 'UNIX_TIMESTAMP' => 33,
+ 'ASYMMETRIC_SIGN' => 33, 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33,
+ 'MULTILINESTRING' => 33, 'POLYGONFROMTEXT' => 33, 'ST_EXTERIORRING' => 33,
+ 'ST_GEOMETRYTYPE' => 33, 'ST_GEOMFROMTEXT' => 33, 'ST_INTERSECTION' => 33,
+ 'ST_LINEFROMTEXT' => 33, 'ST_POINTFROMWKB' => 33, 'ST_POLYFROMTEXT' => 33,
+ 'SUBSTRING_INDEX' => 33,
+ 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33,
+ 'NUMINTERIORRINGS' => 33, 'ST_INTERIORRINGN' => 33, 'ST_NUMGEOMETRIES' => 33,
+ 'ST_POINTFROMTEXT' => 33, 'ST_SYMDIFFERENCE' => 33,
+ 'ASYMMETRIC_DERIVE' => 33, 'ASYMMETRIC_VERIFY' => 33, 'LINESTRINGFROMWKB' => 33,
+ 'MULTIPOINTFROMWKB' => 33, 'ST_POLYGONFROMWKB' => 33,
+ 'ASYMMETRIC_DECRYPT' => 33, 'ASYMMETRIC_ENCRYPT' => 33, 'GEOMETRYCOLLECTION' => 33,
+ 'MULTIPOINTFROMTEXT' => 33, 'ST_GEOMCOLLFROMTXT' => 33, 'ST_GEOMCOLLFROMWKB' => 33,
+ 'ST_POLYGONFROMTEXT' => 33,
+ 'MULTIPOLYGONFROMWKB' => 33, 'ST_GEOMCOLLFROMTEXT' => 33, 'ST_GEOMETRYFROMTEXT' => 33,
+ 'ST_NUMINTERIORRINGS' => 33, 'UNCOMPRESSED_LENGTH' => 33,
+ 'CREATE_DH_PARAMETERS' => 33, 'MULTIPOLYGONFROMTEXT' => 33,
+ 'ST_LINESTRINGFROMWKB' => 33,
+ 'MULTILINESTRINGFROMWKB' => 33,
+ 'MULTILINESTRINGFROMTEXT' => 33,
+ 'CREATE_ASYMMETRIC_PUB_KEY' => 33, 'GEOMETRYCOLLECTIONFROMWKB' => 33,
+ 'CREATE_ASYMMETRIC_PRIV_KEY' => 33, 'GEOMETRYCOLLECTIONFROMTEXT' => 33,
+ 'VALIDATE_PASSWORD_STRENGTH' => 33,
+ 'SQL_THREAD_WAIT_AFTER_GTIDS' => 33,
+ 'ST_GEOMETRYCOLLECTIONFROMWKB' => 33,
+ 'ST_GEOMETRYCOLLECTIONFROMTEXT' => 33,
+ 'WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS' => 33,
+
+ 'IF' => 35, 'IN' => 35,
+ 'MOD' => 35,
+ 'LEFT' => 35,
+ 'RIGHT' => 35,
+ 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35,
+ 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35,
+ 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35,
+ 'LOCALTIME' => 35,
+ 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35,
+ 'UTC_TIMESTAMP' => 35,
+ 'LOCALTIMESTAMP' => 35,
+ 'CURRENT_TIMESTAMP' => 35,
+
+ 'NOT IN' => 39,
+
+ 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41,
+ 'TIMESTAMP' => 41,
+
+ 'CHAR' => 43,
+ 'INTERVAL' => 43,
+
+ );
+}
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php
new file mode 100644
index 0000000000..7e7a29d876
--- /dev/null
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php
@@ -0,0 +1,351 @@
+<?php
+
+/**
+ * Context for MySQL 5.7.
+ *
+ * This file was auto-generated.
+ *
+ * @package SqlParser
+ * @subpackage Contexts
+ * @link https://dev.mysql.com/doc/refman/5.7/en/keywords.html
+ */
+namespace SqlParser\Contexts;
+
+use SqlParser\Context;
+
+/**
+ * Context for MySQL 5.7.
+ *
+ * @category Contexts
+ * @package SqlParser
+ * @subpackage Contexts
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ContextMySql50700 extends Context
+{
+
+ /**
+ * List of keywords.
+ *
+ * The value associated to each keyword represents its flags.
+ *
+ * @see Token::FLAG_KEYWORD_*
+ *
+ * @var array
+ */
+ public static $KEYWORDS = array(
+
+ 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1,
+ 'ANY' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, 'NDB' => 1,
+ 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'XID' => 1,
+ 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1,
+ 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1,
+ 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, 'MODE' => 1,
+ 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, 'PAGE' => 1,
+ 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1,
+ 'THAN' => 1, 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1,
+ 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1,
+ 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, 'EVERY' => 1,
+ 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1,
+ 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1,
+ 'NAMES' => 1, 'NCHAR' => 1, 'NEVER' => 1, 'OWNER' => 1, 'PHASE' => 1,
+ 'PROXY' => 1, 'QUERY' => 1, 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1,
+ 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1,
+ 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1,
+ 'ACTION' => 1, 'ALWAYS' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1,
+ 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1,
+ 'ESCAPE' => 1, 'EVENTS' => 1, 'EXPIRE' => 1, 'EXPORT' => 1, 'FAULTS' => 1,
+ 'FIELDS' => 1, 'FILTER' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1,
+ 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1,
+ 'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1,
+ 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1,
+ 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1,
+ 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1,
+ 'TABLES' => 1,
+ 'ACCOUNT' => 1, 'AGAINST' => 1, 'ANALYSE' => 1, 'CHANGED' => 1, 'CHANNEL' => 1,
+ 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1,
+ 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1,
+ 'EXECUTE' => 1, 'FOLLOWS' => 1, 'GENERAL' => 1, 'HANDLER' => 1, 'INDEXES' => 1,
+ 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1,
+ 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1,
+ 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1,
+ 'SESSION' => 1, 'STACKED' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1,
+ 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WITHOUT' => 1,
+ 'WRAPPER' => 1,
+ 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1,
+ 'EXCHANGE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1,
+ 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1,
+ 'NATIONAL' => 1, 'NVARCHAR' => 1, 'PRECEDES' => 1, 'PRESERVE' => 1,
+ 'PROFILES' => 1, 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1,
+ 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1,
+ 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1,
+ 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1,
+ 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1,
+ 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, 'REDUNDANT' => 1,
+ 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1,
+ 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1,
+ 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1,
+ 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1,
+ 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PLUGIN_DIR' => 1,
+ 'PRIVILEGES' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1,
+ 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'VALIDATION' => 1,
+ 'COLUMN_NAME' => 1, 'COMPRESSION' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1,
+ 'EXTENT_SIZE' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1,
+ 'MYSQL_ERRNO' => 1, 'NONBLOCKING' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1,
+ 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1,
+ 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'DEFAULT_AUTH' => 1,
+ 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, 'MASTER_DELAY' => 1,
+ 'MESSAGE_TEXT' => 1, 'PARTITIONING' => 1, 'RELAY_THREAD' => 1,
+ 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1,
+ 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1,
+ 'COLUMN_FORMAT' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1,
+ 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1,
+ 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1,
+ 'MASTER_LOG_POS' => 1, 'MASTER_SSL_CRL' => 1, 'MASTER_SSL_KEY' => 1,
+ 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1,
+ 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1,
+ 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1,
+ 'FILE_BLOCK_SIZE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1,
+ 'MASTER_SSL_CERT' => 1, 'PARSE_GCOL_EXPR' => 1, 'REPLICATE_DO_DB' => 1,
+ 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1,
+ 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'SQL_BEFORE_GTIDS' => 1,
+ 'STATS_PERSISTENT' => 1, 'UNDO_BUFFER_SIZE' => 1,
+ 'CONSTRAINT_SCHEMA' => 1, 'GROUP_REPLICATION' => 1, 'IGNORE_SERVER_IDS' => 1,
+ 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'RETURNED_SQLSTATE' => 1,
+ 'SQL_BUFFER_RESULT' => 1, 'STATS_AUTO_RECALC' => 1,
+ 'CONSTRAINT_CATALOG' => 1, 'MASTER_RETRY_COUNT' => 1, 'MASTER_SSL_CRLPATH' => 1,
+ 'MAX_STATEMENT_TIME' => 1, 'REPLICATE_DO_TABLE' => 1, 'SQL_AFTER_MTS_GAPS' => 1,
+ 'STATS_SAMPLE_PAGES' => 1,
+ 'REPLICATE_IGNORE_DB' => 1,
+ 'MASTER_AUTO_POSITION' => 1, 'MASTER_CONNECT_RETRY' => 1,
+ 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1,
+ 'MAX_USER_CONNECTIONS' => 1, 'REPLICATE_REWRITE_DB' => 1,
+ 'REPLICATE_IGNORE_TABLE' => 1,
+ 'MASTER_HEARTBEAT_PERIOD' => 1, 'REPLICATE_WILD_DO_TABLE' => 1,
+ 'MAX_CONNECTIONS_PER_HOUR' => 1,
+ 'REPLICATE_WILD_IGNORE_TABLE' => 1,
+
+ 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3,
+ 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3,
+ 'FOR' => 3, 'GET' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3,
+ 'USE' => 3, 'XOR' => 3,
+ 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3,
+ 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3,
+ 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3,
+ 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3,
+ 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3,
+ 'WHEN' => 3, 'WITH' => 3,
+ 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3,
+ 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3,
+ 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3,
+ 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3,
+ 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3,
+ 'WHILE' => 3, 'WRITE' => 3,
+ 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3,
+ 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3,
+ 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3,
+ 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3,
+ 'SIGNAL' => 3, 'STORED' => 3, 'UNLOCK' => 3, 'UPDATE' => 3,
+ 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3,
+ 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3,
+ 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3,
+ 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3,
+ 'VIRTUAL' => 3,
+ 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3,
+ 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, 'MODIFIES' => 3,
+ 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3,
+ 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3,
+ 'ZEROFILL' => 3,
+ 'CONDITION' => 3, 'DATABASES' => 3, 'GENERATED' => 3, 'MIDDLEINT' => 3,
+ 'PARTITION' => 3, 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3,
+ 'SEPARATOR' => 3,
+ 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3,
+ 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3,
+ 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3,
+ 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3,
+ 'MASTER_BIND' => 3,
+ 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3,
+ 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3,
+ 'STRAIGHT_JOIN' => 3,
+ 'IO_AFTER_GTIDS' => 3, 'SQL_BIG_RESULT' => 3,
+ 'DAY_MICROSECOND' => 3, 'IO_BEFORE_GTIDS' => 3, 'OPTIMIZER_COSTS' => 3,
+ 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3,
+ 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3,
+ 'SQL_CALC_FOUND_ROWS' => 3,
+ 'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
+
+ 'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
+ 'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
+ 'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
+ 'DATA DIRECTORY' => 7,
+ 'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
+ 'GENERATED ALWAYS' => 7,
+ 'START TRANSACTION' => 7,
+ 'SELECT TRANSACTION' => 7,
+ 'DEFAULT CHARACTER SET' => 7,
+ 'WITH CONSISTENT SNAPSHOT' => 7,
+
+ 'XML' => 9,
+ 'ENUM' => 9, 'TEXT' => 9,
+ 'ARRAY' => 9,
+ 'SERIAL' => 9,
+ 'BOOLEAN' => 9,
+ 'DATETIME' => 9, 'MULTISET' => 9,
+
+ 'INT' => 11, 'SET' => 11,
+ 'BLOB' => 11, 'REAL' => 11,
+ 'FLOAT' => 11,
+ 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11,
+ 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11,
+ 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11,
+ 'TINYTEXT' => 11,
+ 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11,
+ 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11,
+
+ 'BINARY VARYING' => 15,
+
+ 'KEY' => 19,
+ 'INDEX' => 19,
+ 'UNIQUE' => 19,
+
+ 'INDEX KEY' => 23,
+ 'UNIQUE KEY' => 23,
+ 'FOREIGN KEY' => 23, 'PRIMARY KEY' => 23, 'SPATIAL KEY' => 23,
+ 'FULLTEXT KEY' => 23, 'UNIQUE INDEX' => 23,
+ 'SPATIAL INDEX' => 23,
+ 'FULLTEXT INDEX' => 23,
+
+ 'X' => 33, 'Y' => 33,
+ 'LN' => 33, 'PI' => 33,
+ 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33,
+ 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33,
+ 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33,
+ 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33,
+ 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33,
+ 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33,
+ 'SHA1' => 33, 'SHA2' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'ST_X' => 33,
+ 'ST_Y' => 33, 'TRIM' => 33, 'USER' => 33, 'UUID' => 33, 'WEEK' => 33,
+ 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33,
+ 'CRC32' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33,
+ 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33,
+ 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33,
+ 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33,
+ 'ASTEXT' => 33, 'BIT_OR' => 33, 'BUFFER' => 33, 'CONCAT' => 33, 'DECODE' => 33,
+ 'ENCODE' => 33, 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33,
+ 'LENGTH' => 33, 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33,
+ 'SECOND' => 33, 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33,
+ 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33,
+ 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33,
+ 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33,
+ 'IS_IPV4' => 33, 'IS_IPV6' => 33, 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33,
+ 'REVERSE' => 33, 'SOUNDEX' => 33, 'ST_AREA' => 33, 'ST_SRID' => 33, 'SUBDATE' => 33,
+ 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, 'VAR_POP' => 33,
+ 'VERSION' => 33, 'WEEKDAY' => 33,
+ 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33,
+ 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33,
+ 'DISJOINT' => 33, 'DISTANCE' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33,
+ 'GET_LOCK' => 33, 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33,
+ 'MAKEDATE' => 33, 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33,
+ 'OVERLAPS' => 33, 'PASSWORD' => 33, 'POSITION' => 33, 'ST_ASWKB' => 33,
+ 'ST_ASWKT' => 33, 'ST_UNION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33,
+ 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33,
+ 'ANY_VALUE' => 33, 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33,
+ 'CONCAT_WS' => 33, 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33,
+ 'FROM_DAYS' => 33, 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33,
+ 'LOAD_FILE' => 33, 'MBRCOVERS' => 33, 'MBREQUALS' => 33, 'MBRWITHIN' => 33,
+ 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33, 'ST_ASTEXT' => 33,
+ 'ST_BUFFER' => 33, 'ST_EQUALS' => 33, 'ST_LENGTH' => 33, 'ST_POINTN' => 33,
+ 'ST_WITHIN' => 33, 'SUBSTRING' => 33, 'TO_BASE64' => 33, 'UPDATEXML' => 33,
+ 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'CONVEXHULL' => 33, 'DAYOFMONTH' => 33,
+ 'EXPORT_SET' => 33, 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INET6_ATON' => 33,
+ 'INET6_NTOA' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33, 'MBRTOUCHES' => 33,
+ 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, 'STARTPOINT' => 33,
+ 'STDDEV_POP' => 33, 'ST_CROSSES' => 33, 'ST_GEOHASH' => 33, 'ST_ISEMPTY' => 33,
+ 'ST_ISVALID' => 33, 'ST_TOUCHES' => 33, 'TO_SECONDS' => 33, 'UNCOMPRESS' => 33,
+ 'UUID_SHORT' => 33, 'WEEKOFYEAR' => 33,
+ 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33,
+ 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'FROM_BASE64' => 33,
+ 'GEOMFROMWKB' => 33, 'GTID_SUBSET' => 33, 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33,
+ 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33,
+ 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33,
+ 'ST_ASBINARY' => 33, 'ST_CENTROID' => 33, 'ST_CONTAINS' => 33, 'ST_DISJOINT' => 33,
+ 'ST_DISTANCE' => 33, 'ST_ENDPOINT' => 33, 'ST_ENVELOPE' => 33, 'ST_ISCLOSED' => 33,
+ 'ST_ISSIMPLE' => 33, 'ST_OVERLAPS' => 33, 'ST_SIMPLIFY' => 33, 'ST_VALIDATE' => 33,
+ 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33, 'TIME_TO_SEC' => 33,
+ 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33,
+ 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33,
+ 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33,
+ 'MBRCOVEREDBY' => 33, 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33,
+ 'MULTIPOLYGON' => 33, 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33,
+ 'POINTFROMWKB' => 33, 'POLYFROMTEXT' => 33, 'RANDOM_BYTES' => 33,
+ 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33, 'ST_ASGEOJSON' => 33,
+ 'ST_DIMENSION' => 33, 'ST_GEOMETRYN' => 33, 'ST_NUMPOINTS' => 33,
+ 'TIMESTAMPADD' => 33,
+ 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'GTID_SUBTRACT' => 33,
+ 'INTERIORRINGN' => 33, 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33,
+ 'MPOINTFROMWKB' => 33, 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33,
+ 'POINTFROMTEXT' => 33, 'ST_CONVEXHULL' => 33, 'ST_DIFFERENCE' => 33,
+ 'ST_INTERSECTS' => 33, 'ST_STARTPOINT' => 33, 'TIMESTAMPDIFF' => 33,
+ 'WEIGHT_STRING' => 33,
+ 'IS_IPV4_COMPAT' => 33, 'IS_IPV4_MAPPED' => 33, 'LAST_INSERT_ID' => 33,
+ 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33, 'ST_GEOMFROMWKB' => 33,
+ 'ST_LINEFROMWKB' => 33, 'ST_POLYFROMWKB' => 33, 'UNIX_TIMESTAMP' => 33,
+ 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33,
+ 'POLYGONFROMTEXT' => 33, 'ST_EXTERIORRING' => 33, 'ST_GEOMETRYTYPE' => 33,
+ 'ST_GEOMFROMTEXT' => 33, 'ST_INTERSECTION' => 33, 'ST_LINEFROMTEXT' => 33,
+ 'ST_MAKEENVELOPE' => 33, 'ST_MLINEFROMWKB' => 33, 'ST_MPOLYFROMWKB' => 33,
+ 'ST_POINTFROMWKB' => 33, 'ST_POLYFROMTEXT' => 33, 'SUBSTRING_INDEX' => 33,
+ 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33,
+ 'NUMINTERIORRINGS' => 33, 'ST_INTERIORRINGN' => 33, 'ST_MLINEFROMTEXT' => 33,
+ 'ST_MPOINTFROMWKB' => 33, 'ST_MPOLYFROMTEXT' => 33, 'ST_NUMGEOMETRIES' => 33,
+ 'ST_POINTFROMTEXT' => 33, 'ST_SYMDIFFERENCE' => 33,
+ 'LINESTRINGFROMWKB' => 33, 'MULTIPOINTFROMWKB' => 33, 'RELEASE_ALL_LOCKS' => 33,
+ 'ST_LATFROMGEOHASH' => 33, 'ST_MPOINTFROMTEXT' => 33, 'ST_POLYGONFROMWKB' => 33,
+ 'GEOMETRYCOLLECTION' => 33, 'MULTIPOINTFROMTEXT' => 33, 'ST_BUFFER_STRATEGY' => 33,
+ 'ST_DISTANCE_SPHERE' => 33, 'ST_GEOMCOLLFROMTXT' => 33, 'ST_GEOMCOLLFROMWKB' => 33,
+ 'ST_GEOMFROMGEOJSON' => 33, 'ST_LONGFROMGEOHASH' => 33, 'ST_POLYGONFROMTEXT' => 33,
+ 'MULTIPOLYGONFROMWKB' => 33, 'ST_GEOMCOLLFROMTEXT' => 33, 'ST_GEOMETRYFROMTEXT' => 33,
+ 'ST_NUMINTERIORRINGS' => 33, 'ST_POINTFROMGEOHASH' => 33, 'UNCOMPRESSED_LENGTH' => 33,
+ 'MULTIPOLYGONFROMTEXT' => 33, 'ST_LINESTRINGFROMWKB' => 33,
+ 'ST_MULTIPOINTFROMWKB' => 33,
+ 'ST_MULTIPOINTFROMTEXT' => 33,
+ 'MULTILINESTRINGFROMWKB' => 33, 'ST_MULTIPOLYGONFROMWKB' => 33,
+ 'MULTILINESTRINGFROMTEXT' => 33, 'ST_MULTIPOLYGONFROMTEXT' => 33,
+ 'GEOMETRYCOLLECTIONFROMWKB' => 33, 'ST_MULTILINESTRINGFROMWKB' => 33,
+ 'GEOMETRYCOLLECTIONFROMTEXT' => 33, 'ST_MULTILINESTRINGFROMTEXT' => 33,
+ 'VALIDATE_PASSWORD_STRENGTH' => 33, 'WAIT_FOR_EXECUTED_GTID_SET' => 33,
+ 'ST_GEOMETRYCOLLECTIONFROMWKB' => 33,
+ 'ST_GEOMETRYCOLLECTIONFROMTEXT' => 33,
+ 'WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS' => 33,
+
+ 'IF' => 35, 'IN' => 35,
+ 'MOD' => 35,
+ 'LEFT' => 35,
+ 'RIGHT' => 35,
+ 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35,
+ 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35,
+ 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35,
+ 'LOCALTIME' => 35,
+ 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35,
+ 'UTC_TIMESTAMP' => 35,
+ 'LOCALTIMESTAMP' => 35,
+ 'CURRENT_TIMESTAMP' => 35,
+
+ 'NOT IN' => 39,
+
+ 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41,
+ 'TIMESTAMP' => 41,
+
+ 'CHAR' => 43,
+ 'INTERVAL' => 43,
+
+ );
+}
diff --git a/libraries/sql-parser/src/Exceptions/LexerException.php b/libraries/sql-parser/src/Exceptions/LexerException.php
new file mode 100644
index 0000000000..3bbc0c72cd
--- /dev/null
+++ b/libraries/sql-parser/src/Exceptions/LexerException.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * Exception thrown by the lexer.
+ *
+ * @package SqlParser
+ * @subpackage Exceptions
+ */
+namespace SqlParser\Exceptions;
+
+/**
+ * Exception thrown by the lexer.
+ *
+ * @category Exceptions
+ * @package SqlParser
+ * @subpackage Exceptions
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class LexerException extends \Exception
+{
+
+ /**
+ * The character that produced this error.
+ *
+ * @var string
+ */
+ public $ch;
+
+ /**
+ * The index of the character that produced this error.
+ *
+ * @var int
+ */
+ public $pos;
+
+ /**
+ * Constructor.
+ *
+ * @param string $msg The message of this exception.
+ * @param string $ch The character that produced this exception.
+ * @param int $pos The position of the character.
+ * @param int $code The code of this error.
+ */
+ public function __construct($msg = '', $ch = '', $pos = 0, $code = 0)
+ {
+ parent::__construct($msg, $code);
+ $this->ch = $ch;
+ $this->pos = $pos;
+ }
+}
diff --git a/libraries/sql-parser/src/Exceptions/ParserException.php b/libraries/sql-parser/src/Exceptions/ParserException.php
new file mode 100644
index 0000000000..5a9fac0442
--- /dev/null
+++ b/libraries/sql-parser/src/Exceptions/ParserException.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * Exception thrown by the parser.
+ *
+ * @package SqlParser
+ * @subpackage Exceptions
+ */
+namespace SqlParser\Exceptions;
+
+use SqlParser\Token;
+
+/**
+ * Exception thrown by the parser.
+ *
+ * @category Exceptions
+ * @package SqlParser
+ * @subpackage Exceptions
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ParserException extends \Exception
+{
+
+ /**
+ * The token that produced this error.
+ *
+ * @var Token
+ */
+ public $token;
+
+ /**
+ * Constructor.
+ *
+ * @param string $msg The message of this exception.
+ * @param Token $token The token that produced this exception.
+ * @param int $code The code of this error.
+ */
+ public function __construct($msg = '', Token $token = null, $code = 0)
+ {
+ parent::__construct($msg, $code);
+ $this->token = $token;
+ }
+}
diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php
new file mode 100644
index 0000000000..e4561de9ff
--- /dev/null
+++ b/libraries/sql-parser/src/Lexer.php
@@ -0,0 +1,881 @@
+<?php
+
+/**
+ * Defines the lexer of the library.
+ *
+ * This is one of the most important components, along with the parser.
+ *
+ * Depends on context to extract lexemes.
+ *
+ * @package SqlParser
+ */
+
+namespace {
+
+ if (!function_exists('__')) {
+
+ /**
+ * Translates the given string.
+ *
+ * @param string $str String to be translated.
+ *
+ * @return string
+ */
+ function __($str)
+ {
+ return $str;
+ }
+ }
+}
+
+namespace SqlParser {
+
+ use SqlParser\Exceptions\LexerException;
+
+ if (!defined('USE_UTF_STRINGS')) {
+
+ // NOTE: In previous versions of PHP (5.5 and older) the default
+ // internal encoding is "ISO-8859-1".
+ // All `mb_` functions must specify the correct encoding, which is
+ // 'UTF-8' in order to work properly.
+
+ /**
+ * Forces usage of `UtfString` if the string is multibyte.
+ * `UtfString` may be slower, but it gives better results.
+ *
+ * @var bool
+ */
+ define('USE_UTF_STRINGS', true);
+ }
+
+ /**
+ * Performs lexical analysis over a SQL statement and splits it in multiple
+ * tokens.
+ *
+ * The output of the lexer is affected by the context of the SQL statement.
+ *
+ * @category Lexer
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ * @see Context
+ */
+ class Lexer
+ {
+
+ /**
+ * A list of methods that are used in lexing the SQL query.
+ *
+ * @var array
+ */
+ public static $PARSER_METHODS = array(
+
+ // It is best to put the parsers in order of their complexity
+ // (ascending) and their occurrence rate (descending).
+ //
+ // Conflicts:
+ //
+ // 1. `parseDelimiter`, `parseUnknown`, `parseKeyword`, `parseNumber`
+ // They fight over delimiter. The delimiter may be a keyword, a
+ // number or almost any character which makes the delimiter one of
+ // the first tokens that must be parsed.
+ //
+ // 1. `parseNumber` and `parseOperator`
+ // They fight over `+` and `-`.
+ //
+ // 2. `parseComment` and `parseOperator`
+ // They fight over `/` (as in ```/*comment*/``` or ```a / b```)
+ //
+ // 3. `parseBool` and `parseKeyword`
+ // They fight over `TRUE` and `FALSE`.
+ //
+ // 4. `parseKeyword` and `parseUnknown`
+ // They fight over words. `parseUnknown` does not know about
+ // keywords.
+
+ 'parseDelimiter', 'parseWhitespace', 'parseNumber',
+ 'parseComment', 'parseOperator', 'parseBool', 'parseString',
+ 'parseSymbol', 'parseKeyword', 'parseUnknown'
+ );
+
+ /**
+ * Whether errors should throw exceptions or just be stored.
+ *
+ * @var bool
+ *
+ * @see static::$errors
+ */
+ public $strict = false;
+
+ /**
+ * The string to be parsed.
+ *
+ * @var string|UtfString
+ */
+ public $str = '';
+
+ /**
+ * The length of `$str`.
+ *
+ * By storing its length, a lot of time is saved, because parsing methods
+ * would call `strlen` everytime.
+ *
+ * @var int
+ */
+ public $len = 0;
+
+ /**
+ * The index of the last parsed character.
+ *
+ * @var int
+ */
+ public $last = 0;
+
+ /**
+ * Tokens extracted from given strings.
+ *
+ * @var TokensList
+ */
+ public $list;
+
+ /**
+ * The default delimiter. This is used, by default, in all new instances.
+ *
+ * @var string
+ */
+ public static $DEFAULT_DELIMITER = ';';
+
+ /**
+ * Statements delimiter.
+ * This may change during lexing.
+ *
+ * @var string
+ */
+ public $delimiter;
+
+ /**
+ * The length of the delimiter.
+ *
+ * Because `parseDelimiter` can be called a lot, it would perform a lot of
+ * calls to `strlen`, which might affect performance when the delimiter is
+ * big.
+ *
+ * @var int
+ */
+ public $delimiterLen;
+
+ /**
+ * List of errors that occurred during lexing.
+ *
+ * Usually, the lexing does not stop once an error occurred because that
+ * error might be false positive or a partial result (even a bad one)
+ * might be needed.
+ *
+ * @var LexerException[]
+ *
+ * @see Lexer::error()
+ */
+ public $errors = array();
+
+ /**
+ * Constructor.
+ *
+ * @param string|UtfString $str The query to be lexed.
+ * @param bool $strict Whether strict mode should be
+ * enabled or not.
+ * @param string $delimiter The delimiter to be used.
+ */
+ public function __construct($str, $strict = false, $delimiter = null)
+ {
+ // `strlen` is used instead of `mb_strlen` because the lexer needs to
+ // parse each byte of the input.
+ $len = ($str instanceof UtfString) ? $str->length() : strlen($str);
+
+ // For multi-byte strings, a new instance of `UtfString` is
+ // initialized (only if `UtfString` usage is forced.
+ if (!($str instanceof UtfString)) {
+ if ((USE_UTF_STRINGS) && ($len !== mb_strlen($str, 'UTF-8'))) {
+ $str = new UtfString($str);
+ }
+ }
+
+ $this->str = $str;
+ $this->len = ($str instanceof UtfString) ? $str->length() : $len;
+
+ $this->strict = $strict;
+
+ // Setting the delimiter.
+ $this->setDelimiter(
+ !empty($delimiter) ? $delimiter : static::$DEFAULT_DELIMITER
+ );
+
+ $this->lex();
+ }
+
+ /**
+ * Sets the delimiter.
+ *
+ * @param string $delimiter The new delimiter.
+ */
+ public function setDelimiter($delimiter)
+ {
+ $this->delimiter = $delimiter;
+ $this->delimiterLen = strlen($delimiter);
+ }
+
+ /**
+ * Parses the string and extracts lexemes.
+ *
+ * @return void
+ */
+ public function lex()
+ {
+ // TODO: Sometimes, static::parse* functions make unnecessary calls to
+ // is* functions. For a better performance, some rules can be deduced
+ // from context.
+ // For example, in `parseBool` there is no need to compare the token
+ // every time with `true` and `false`. The first step would be to
+ // compare with 'true' only and just after that add another letter from
+ // context and compare again with `false`.
+ // Another example is `parseComment`.
+
+ $list = new TokensList();
+
+ /**
+ * Last processed token.
+ *
+ * @var Token $lastToken
+ */
+ $lastToken = null;
+
+ for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) {
+
+ /**
+ * The new token.
+ *
+ * @var Token $token
+ */
+ $token = null;
+
+ foreach (static::$PARSER_METHODS as $method) {
+ if (($token = $this->$method())) {
+ break;
+ }
+ }
+
+ if ($token === null) {
+ // @assert($this->last === $lastIdx);
+ $token = new Token($this->str[$this->last]);
+ $this->error(
+ __('Unexpected character.'),
+ $this->str[$this->last],
+ $this->last
+ );
+ } elseif (($lastToken !== null)
+ && ($token->type === Token::TYPE_SYMBOL)
+ && ($token->flags & Token::FLAG_SYMBOL_VARIABLE)
+ && (($lastToken->type === Token::TYPE_STRING)
+ || (($lastToken->type === Token::TYPE_SYMBOL)
+ && ($lastToken->flags & Token::FLAG_SYMBOL_BACKTICK)))
+ ) {
+ // Handles ```... FROM 'user'@'%' ...```.
+ $lastToken->token .= $token->token;
+ $lastToken->type = Token::TYPE_SYMBOL;
+ $lastToken->flags = Token::FLAG_SYMBOL_USER;
+ $lastToken->value .= '@' . $token->value;
+ continue;
+ } elseif (($lastToken !== null)
+ && ($token->type === Token::TYPE_KEYWORD)
+ && ($lastToken->type === Token::TYPE_OPERATOR)
+ && ($lastToken->value === '.')
+ ) {
+ // Handles ```... tbl.FROM ...```. In this case, FROM is not
+ // a reserved word.
+ $token->type = Token::TYPE_NONE;
+ $token->flags = 0;
+ $token->value = $token->token;
+ }
+
+ $token->position = $lastIdx;
+
+ $list->tokens[$list->count++] = $token;
+
+ // Handling delimiters.
+ if (($token->type === Token::TYPE_NONE) && ($token->value === 'DELIMITER')) {
+ if ($this->last + 1 >= $this->len) {
+ $this->error(
+ __('Expected whitespace(s) before delimiter.'),
+ '',
+ $this->last + 1
+ );
+ continue;
+ }
+
+ // Skipping last R (from `delimiteR`) and whitespaces between
+ // the keyword `DELIMITER` and the actual delimiter.
+ $pos = ++$this->last;
+ if (($token = $this->parseWhitespace()) !== null) {
+ $token->position = $pos;
+ $list->tokens[$list->count++] = $token;
+ }
+
+ // Preparing the token that holds the new delimiter.
+ if ($this->last + 1 >= $this->len) {
+ $this->error(
+ __('Expected delimiter.'),
+ '',
+ $this->last + 1
+ );
+ continue;
+ }
+ $pos = $this->last + 1;
+
+ // Parsing the delimiter.
+ $this->delimiter = null;
+ while ((++$this->last < $this->len) && (!Context::isWhitespace($this->str[$this->last]))) {
+ $this->delimiter .= $this->str[$this->last];
+ }
+
+ if (empty($this->delimiter)) {
+ $this->error(
+ __('Expected delimiter.'),
+ '',
+ $this->last
+ );
+ $this->delimiter = ';';
+ }
+
+ --$this->last;
+
+ // Saving the delimiter and its token.
+ $this->delimiterLen = strlen($this->delimiter);
+ $token = new Token($this->delimiter, Token::TYPE_DELIMITER);
+ $token->position = $pos;
+ $list->tokens[$list->count++] = $token;
+ }
+
+ $lastToken = $token;
+ }
+
+ // Adding a final delimiter to mark the ending.
+ $list->tokens[$list->count++] = new Token(null, Token::TYPE_DELIMITER);
+
+ // Saving the tokens list.
+ $this->list = $list;
+ }
+
+ /**
+ * Creates a new error log.
+ *
+ * @param string $msg The error message.
+ * @param string $str The character that produced the error.
+ * @param int $pos The position of the character.
+ * @param int $code The code of the error.
+ *
+ * @throws LexerException Throws the exception, if strict mode is enabled.
+ *
+ * @return void
+ */
+ public function error($msg = '', $str = '', $pos = 0, $code = 0)
+ {
+ $error = new LexerException($msg, $str, $pos, $code);
+ if ($this->strict) {
+ throw $error;
+ }
+ $this->errors[] = $error;
+ }
+
+ /**
+ * Parses a keyword.
+ *
+ * @return Token
+ */
+ public function parseKeyword()
+ {
+ $token = '';
+
+ /**
+ * Value to be returned.
+ *
+ * @var Token $ret
+ */
+ $ret = null;
+
+ /**
+ * The value of `$this->last` where `$token` ends in `$this->str`.
+ *
+ * @var int $iEnd
+ */
+ $iEnd = $this->last;
+
+ /**
+ * Whether last parsed character is a whitespace.
+ *
+ * @var bool $lastSpace
+ */
+ $lastSpace = false;
+
+ for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
+
+ // Composed keywords shouldn't have more than one whitespace between
+ // keywords.
+ if (Context::isWhitespace($this->str[$this->last])) {
+ if ($lastSpace) {
+ --$j; // The size of the keyword didn't increase.
+ continue;
+ } else {
+ $lastSpace = true;
+ }
+ } else {
+ $lastSpace = false;
+ }
+ $token .= $this->str[$this->last];
+ if (($this->last + 1 === $this->len) || (Context::isSeparator($this->str[$this->last + 1]))) {
+ if (($flags = Context::isKeyword($token))) {
+ $ret = new Token($token, Token::TYPE_KEYWORD, $flags);
+ $iEnd = $this->last;
+
+ // We don't break so we find longest keyword.
+ // For example, `OR` and `ORDER` have a common prefix `OR`.
+ // If we stopped at `OR`, the parsing would be invalid.
+ }
+ }
+ }
+
+ $this->last = $iEnd;
+ return $ret;
+ }
+
+ /**
+ * Parses an operator.
+ *
+ * @return Token
+ */
+ public function parseOperator()
+ {
+ $token = '';
+
+ /**
+ * Value to be returned.
+ *
+ * @var Token $ret
+ */
+ $ret = null;
+
+ /**
+ * The value of `$this->last` where `$token` ends in `$this->str`.
+ *
+ * @var int $iEnd
+ */
+ $iEnd = $this->last;
+
+ for ($j = 1; $j < Context::OPERATOR_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
+ $token .= $this->str[$this->last];
+ if ($flags = Context::isOperator($token)) {
+ $ret = new Token($token, Token::TYPE_OPERATOR, $flags);
+ $iEnd = $this->last;
+ }
+ }
+
+ $this->last = $iEnd;
+ return $ret;
+ }
+
+ /**
+ * Parses a whitespace.
+ *
+ * @return Token
+ */
+ public function parseWhitespace()
+ {
+ $token = $this->str[$this->last];
+
+ if (!Context::isWhitespace($token)) {
+ return null;
+ }
+
+ while ((++$this->last < $this->len) && (Context::isWhitespace($this->str[$this->last]))) {
+ $token .= $this->str[$this->last];
+ }
+
+ --$this->last;
+ return new Token($token, Token::TYPE_WHITESPACE);
+ }
+
+ /**
+ * Parses a comment.
+ *
+ * @return Token
+ */
+ public function parseComment()
+ {
+ $iBak = $this->last;
+ $token = $this->str[$this->last];
+
+ // Bash style comments. (#comment\n)
+ if (Context::isComment($token)) {
+ while ((++$this->last < $this->len) && ($this->str[$this->last] !== "\n")) {
+ $token .= $this->str[$this->last];
+ }
+ $token .= "\n"; // Adding the line ending.
+ return new Token($token, Token::TYPE_COMMENT, Token::FLAG_COMMENT_BASH);
+ }
+
+ // C style comments. (/*comment*\/)
+ if (++$this->last < $this->len) {
+ $token .= $this->str[$this->last];
+ if (Context::isComment($token)) {
+ $flags = Token::FLAG_COMMENT_C;
+
+ // This comment already ended. It may be a part of a
+ // previous MySQL specific command.
+ if ($token === '*/') {
+ return new Token($token, Token::TYPE_COMMENT, $flags);
+ }
+
+ // Checking if this is a MySQL-specific command.
+ if (($this->last + 1 < $this->len) && ($this->str[$this->last + 1] === '!')) {
+ $flags |= Token::FLAG_COMMENT_MYSQL_CMD;
+ $token .= $this->str[++$this->last];
+
+ while ((++$this->last < $this->len)
+ && ('0' <= $this->str[$this->last])
+ && ($this->str[$this->last] <= '9')
+ ) {
+ $token .= $this->str[$this->last];
+ }
+ --$this->last;
+
+ // We split this comment and parse only its beginning
+ // here.
+ return new Token($token, Token::TYPE_COMMENT, $flags);
+ }
+
+ // Parsing the comment.
+ while ((++$this->last < $this->len)
+ && (($this->str[$this->last - 1] !== '*') || ($this->str[$this->last] !== '/'))
+ ) {
+ $token .= $this->str[$this->last];
+ }
+
+ // Adding the ending.
+ if ($this->last < $this->len) {
+ $token .= $this->str[$this->last];
+ }
+ return new Token($token, Token::TYPE_COMMENT, $flags);
+ }
+ }
+
+ // SQL style comments. (-- comment\n)
+ if (++$this->last < $this->len) {
+ $token .= $this->str[$this->last];
+ if (Context::isComment($token)) {
+ // Checking if this comment did not end already (```--\n```).
+ if ($this->str[$this->last] !== "\n") {
+ while ((++$this->last < $this->len) && ($this->str[$this->last] !== "\n")) {
+ $token .= $this->str[$this->last];
+ }
+ $token .= "\n"; // Adding the line ending.
+ }
+ return new Token($token, Token::TYPE_COMMENT, Token::FLAG_COMMENT_SQL);
+ }
+ }
+
+ $this->last = $iBak;
+ return null;
+ }
+
+ /**
+ * Parses a boolean.
+ *
+ * @return Token
+ */
+ public function parseBool()
+ {
+ if ($this->last + 3 >= $this->len) {
+ // At least `min(strlen('TRUE'), strlen('FALSE'))` characters are
+ // required.
+ return null;
+ }
+
+ $iBak = $this->last;
+ $token = $this->str[$this->last] . $this->str[++$this->last]
+ . $this->str[++$this->last] . $this->str[++$this->last]; // _TRUE_ or _FALS_e
+
+ if (Context::isBool($token)) {
+ return new Token($token, Token::TYPE_BOOL);
+ } elseif (++$this->last < $this->len) {
+ $token .= $this->str[$this->last]; // fals_E_
+ if (Context::isBool($token)) {
+ return new Token($token, Token::TYPE_BOOL, 1);
+ }
+ }
+
+ $this->last = $iBak;
+ return null;
+ }
+
+ /**
+ * Parses a number.
+ *
+ * @return Token
+ */
+ public function parseNumber()
+ {
+ // A rudimentary state machine is being used to parse numbers due to
+ // the various forms of their notation.
+ //
+ // Below are the states of the machines and the conditions to change
+ // the state.
+ //
+ // 1 --------------------[ + or - ]-------------------> 1
+ // 1 -------------------[ 0x or 0X ]------------------> 2
+ // 1 --------------------[ 0 to 9 ]-------------------> 3
+ // 1 -----------------------[ . ]---------------------> 4
+ // 1 -----------------------[ b ]---------------------> 7
+ //
+ // 2 --------------------[ 0 to F ]-------------------> 2
+ //
+ // 3 --------------------[ 0 to 9 ]-------------------> 3
+ // 3 -----------------------[ . ]---------------------> 4
+ // 3 --------------------[ e or E ]-------------------> 5
+ //
+ // 4 --------------------[ 0 to 9 ]-------------------> 4
+ // 4 --------------------[ e or E ]-------------------> 5
+ //
+ // 5 ---------------[ + or - or 0 to 9 ]--------------> 6
+ //
+ // 7 -----------------------[ ' ]---------------------> 8
+ //
+ // 8 --------------------[ 0 or 1 ]-------------------> 8
+ // 8 -----------------------[ ' ]---------------------> 9
+ //
+ // State 1 may be reached by negative numbers.
+ // State 2 is reached only by hex numbers.
+ // State 4 is reached only by float numbers.
+ // State 5 is reached only by numbers in approximate form.
+ // State 7 is reached only by numbers in bit representation.
+ //
+ // Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a
+ // state other than these is invalid.
+ $iBak = $this->last;
+ $token = '';
+ $flags = 0;
+ $state = 1;
+ for (; $this->last < $this->len; ++$this->last) {
+ if ($state === 1) {
+ if ($this->str[$this->last] === '-') {
+ $flags |= Token::FLAG_NUMBER_NEGATIVE;
+ } elseif (($this->last + 1 < $this->len)
+ && ($this->str[$this->last] === '0')
+ && (($this->str[$this->last + 1] === 'x')
+ || ($this->str[$this->last + 1] === 'X'))
+ ) {
+ $token .= $this->str[$this->last++];
+ $state = 2;
+ } elseif (($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) {
+ $state = 3;
+ } elseif ($this->str[$this->last] === '.') {
+ $state = 4;
+ } elseif ($this->str[$this->last] === 'b') {
+ $state = 7;
+ } elseif ($this->str[$this->last] !== '+') {
+ // `+` is a valid character in a number.
+ break;
+ }
+ } elseif ($state === 2) {
+ $flags |= Token::FLAG_NUMBER_HEX;
+ if (!((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9'))
+ || (($this->str[$this->last] >= 'A') && ($this->str[$this->last] <= 'F'))
+ || (($this->str[$this->last] >= 'a') && ($this->str[$this->last] <= 'f')))
+ ) {
+ break;
+ }
+ } elseif ($state === 3) {
+ if ($this->str[$this->last] === '.') {
+ $state = 4;
+ } elseif (($this->str[$this->last] === 'e') || ($this->str[$this->last] === 'E')) {
+ $state = 5;
+ } elseif (($this->str[$this->last] < '0') || ($this->str[$this->last] > '9')) {
+ // Just digits and `.`, `e` and `E` are valid characters.
+ break;
+ }
+ } elseif ($state === 4) {
+ $flags |= Token::FLAG_NUMBER_FLOAT;
+ if (($this->str[$this->last] === 'e') || ($this->str[$this->last] === 'E')) {
+ $state = 5;
+ } elseif (($this->str[$this->last] < '0') || ($this->str[$this->last] > '9')) {
+ // Just digits, `e` and `E` are valid characters.
+ break;
+ }
+ } elseif ($state === 5) {
+ $flags |= Token::FLAG_NUMBER_APPROXIMATE;
+ if (($this->str[$this->last] === '+') || ($this->str[$this->last] === '-')
+ || ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')))
+ ) {
+ $state = 6;
+ } else {
+ break;
+ }
+ } elseif ($state === 6) {
+ if (($this->str[$this->last] < '0') || ($this->str[$this->last] > '9')) {
+ // Just digits are valid characters.
+ break;
+ }
+ } elseif ($state === 7) {
+ $flags |= Token::FLAG_NUMBER_BINARY;
+ if ($this->str[$this->last] === '\'') {
+ $state = 8;
+ } else {
+ break;
+ }
+ } elseif ($state === 8) {
+ if ($this->str[$this->last] === '\'') {
+ $state = 9;
+ } elseif (($this->str[$this->last] !== '0')
+ && ($this->str[$this->last] !== '1')
+ ) {
+ break;
+ }
+ } elseif ($state === 9) {
+ break;
+ }
+ $token .= $this->str[$this->last];
+ }
+ if (($state === 2) || ($state === 3)
+ || (($token !== '.') && ($state === 4))
+ || ($state === 6) || ($state === 9)
+ ) {
+ --$this->last;
+ return new Token($token, Token::TYPE_NUMBER, $flags);
+ }
+ $this->last = $iBak;
+ return null;
+ }
+
+ /**
+ * Parses a string.
+ *
+ * @param string $quote Additional starting symbol.
+ *
+ * @return Token
+ */
+ public function parseString($quote = '')
+ {
+ $token = $this->str[$this->last];
+ if ((!($flags = Context::isString($token))) && ($token !== $quote)) {
+ return null;
+ }
+ $quote = $token;
+
+ while (++$this->last < $this->len) {
+ if (($this->last + 1 < $this->len)
+ && ((($this->str[$this->last] === $quote) && ($this->str[$this->last + 1] === $quote))
+ || (($this->str[$this->last] === '\\') && ($quote !== '`')))
+ ) {
+ $token .= $this->str[$this->last] . $this->str[++$this->last];
+ } else {
+ if ($this->str[$this->last] === $quote) {
+ break;
+ }
+ $token .= $this->str[$this->last];
+ }
+ }
+
+ if (($this->last >= $this->len) || ($this->str[$this->last] !== $quote)) {
+ $this->error(
+ sprintf(
+ __('Ending quote %1$s was expected.'),
+ $quote
+ ),
+ '',
+ $this->last
+ );
+ } else {
+ $token .= $this->str[$this->last];
+ }
+ return new Token($token, Token::TYPE_STRING, $flags);
+ }
+
+ /**
+ * Parses a symbol.
+ *
+ * @return Token
+ */
+ public function parseSymbol()
+ {
+ $token = $this->str[$this->last];
+ if (!($flags = Context::isSymbol($token))) {
+ return null;
+ }
+
+ if ($flags & Token::FLAG_SYMBOL_VARIABLE) {
+ if ($this->str[++$this->last] === '@') {
+ // This is a system variable (e.g. `@@hostname`).
+ $token .= $this->str[$this->last++];
+ $flags |= Token::FLAG_SYMBOL_SYSTEM;
+ }
+ } else {
+ $token = '';
+ }
+
+ $str = null;
+
+ if ($this->last < $this->len) {
+ if (($str = $this->parseString('`')) === null) {
+ if (($str = static::parseUnknown()) === null) {
+ $this->error(
+ __('Variable name was expected.'),
+ $this->str[$this->last],
+ $this->last
+ );
+ }
+ }
+ }
+
+ if ($str !== null) {
+ $token .= $str->token;
+ }
+
+ return new Token($token, Token::TYPE_SYMBOL, $flags);
+ }
+
+ /**
+ * Parses unknown parts of the query.
+ *
+ * @return Token
+ */
+ public function parseUnknown()
+ {
+ $token = $this->str[$this->last];
+ if (Context::isSeparator($token)) {
+ return null;
+ }
+ while ((++$this->last < $this->len) && (!Context::isSeparator($this->str[$this->last]))) {
+ $token .= $this->str[$this->last];
+ }
+ --$this->last;
+ return new Token($token);
+ }
+
+ /**
+ * Parses the delimiter of the query.
+ *
+ * @return Token
+ */
+ public function parseDelimiter()
+ {
+ $idx = 0;
+
+ while (($idx < $this->delimiterLen) && ($this->last + $idx < $this->len)) {
+ if ($this->delimiter[$idx] !== $this->str[$this->last + $idx]) {
+ return null;
+ }
+ ++$idx;
+ }
+
+ $this->last += $this->delimiterLen - 1;
+ return new Token($this->delimiter, Token::TYPE_DELIMITER);
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php
new file mode 100644
index 0000000000..5b74f33982
--- /dev/null
+++ b/libraries/sql-parser/src/Parser.php
@@ -0,0 +1,547 @@
+<?php
+
+/**
+ * Defines the parser of the library.
+ *
+ * This is one of the most important components, along with the lexer.
+ *
+ * @package SqlParser
+ */
+
+namespace {
+
+ if (!function_exists('__')) {
+
+ /**
+ * Translates the given string.
+ *
+ * @param string $str String to be translated.
+ *
+ * @return string
+ */
+ function __($str)
+ {
+ return $str;
+ }
+ }
+}
+
+namespace SqlParser {
+
+ use SqlParser\Exceptions\ParserException;
+ use SqlParser\Statements\SelectStatement;
+ use SqlParser\Statements\TransactionStatement;
+
+ /**
+ * Takes multiple tokens (contained in a Lexer instance) as input and builds a
+ * parse tree.
+ *
+ * @category Parser
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+ class Parser
+ {
+
+ /**
+ * Array of classes that are used in parsing the SQL statements.
+ *
+ * @var array
+ */
+ public static $STATEMENT_PARSERS = array(
+
+ // MySQL Utility Statements
+ 'EXPLAIN' => 'SqlParser\\Statements\\ExplainStatement',
+ 'DESCRIBE' => 'SqlParser\\Statements\\ExplainStatement',
+ 'HELP' => '',
+ 'USE' => '',
+ 'STATUS' => '',
+
+ // Table Maintenance Statements
+ // https://dev.mysql.com/doc/refman/5.7/en/table-maintenance-sql.html
+ 'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement',
+ 'BACKUP' => 'SqlParser\\Statements\\BackupStatement',
+ 'CHECK' => 'SqlParser\\Statements\\CheckStatement',
+ 'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement',
+ 'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement',
+ 'REPAIR' => 'SqlParser\\Statements\\RepairStatement',
+ 'RESTORE' => 'SqlParser\\Statements\\RestoreStatement',
+
+ // Database Administration Statements
+ // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-server-administration.html
+ 'SET' => 'SqlParser\\Statements\\SetStatement',
+ 'SHOW' => 'SqlParser\\Statements\\ShowStatement',
+
+ // Data Definition Statements.
+ // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-definition.html
+ 'ALTER' => 'SqlParser\\Statements\\AlterStatement',
+ 'CREATE' => 'SqlParser\\Statements\\CreateStatement',
+ 'DROP' => 'SqlParser\\Statements\\DropStatement',
+ 'RENAME' => 'SqlParser\\Statements\\RenameStatement',
+ 'TRUNCATE' => 'SqlParser\\Statements\\TruncateStatement',
+
+ // Data Manipulation Statements.
+ // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-manipulation.html
+ 'CALL' => 'SqlParser\\Statements\\CallStatement',
+ 'DELETE' => 'SqlParser\\Statements\\DeleteStatement',
+ 'DO' => '',
+ 'HANDLER' => '',
+ 'INSERT' => 'SqlParser\\Statements\\InsertStatement',
+ 'LOAD' => '',
+ 'REPLACE' => 'SqlParser\\Statements\\ReplaceStatement',
+ 'SELECT' => 'SqlParser\\Statements\\SelectStatement',
+ 'UPDATE' => 'SqlParser\\Statements\\UpdateStatement',
+
+ // Prepared Statements.
+ // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
+ 'PREPARE' => '',
+ 'EXECUTE' => '',
+
+ // Transactional and Locking Statements
+ // https://dev.mysql.com/doc/refman/5.7/en/commit.html
+ 'START TRANSACTION' => 'SqlParser\\Statements\\TransactionStatement',
+ 'BEGIN' => 'SqlParser\\Statements\\TransactionStatement',
+ 'COMMIT' => 'SqlParser\\Statements\\TransactionStatement',
+ 'ROLLBACK' => 'SqlParser\\Statements\\TransactionStatement',
+ );
+
+ /**
+ * Array of classes that are used in parsing SQL components.
+ *
+ * @var array
+ */
+ public static $KEYWORD_PARSERS = array(
+
+ // This is not a proper keyword and was added here to help the
+ // formatter.
+ 'PARTITION BY' => array(),
+ 'SUBPARTITION BY' => array(),
+
+ // This is not a proper keyword and was added here to help the
+ // builder.
+ '_OPTIONS' => array(
+ 'class' => 'SqlParser\\Components\\OptionsArray',
+ 'field' => 'options',
+ ),
+ 'UNION' => array(
+ 'class' => 'SqlParser\\Components\\UnionKeyword',
+ 'field' => 'union',
+ ),
+
+ // Actual clause parsers.
+ 'ALTER' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'ANALYZE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'BACKUP' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'CALL' => array(
+ 'class' => 'SqlParser\\Components\\FunctionCall',
+ 'field' => 'call',
+ ),
+ 'CHECK' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'CHECKSUM' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'DROP' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'fields',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'FROM' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'from',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'GROUP BY' => array(
+ 'class' => 'SqlParser\\Components\\OrderKeyword',
+ 'field' => 'group',
+ ),
+ 'HAVING' => array(
+ 'class' => 'SqlParser\\Components\\Condition',
+ 'field' => 'having',
+ ),
+ 'INTO' => array(
+ 'class' => 'SqlParser\\Components\\IntoKeyword',
+ 'field' => 'into',
+ ),
+ 'JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'LEFT JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'RIGHT JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'INNER JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'FULL JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
+ ),
+ 'LIMIT' => array(
+ 'class' => 'SqlParser\\Components\\Limit',
+ 'field' => 'limit',
+ ),
+ 'OPTIMIZE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'ORDER BY' => array(
+ 'class' => 'SqlParser\\Components\\OrderKeyword',
+ 'field' => 'order',
+ ),
+ 'PARTITION' => array(
+ 'class' => 'SqlParser\\Components\\ArrayObj',
+ 'field' => 'partition',
+ ),
+ 'PROCEDURE' => array(
+ 'class' => 'SqlParser\\Components\\FunctionCall',
+ 'field' => 'procedure',
+ ),
+ 'RENAME' => array(
+ 'class' => 'SqlParser\\Components\\RenameOperation',
+ 'field' => 'renames',
+ ),
+ 'REPAIR' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'RESTORE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'SET' => array(
+ 'class' => 'SqlParser\\Components\\SetOperation',
+ 'field' => 'set',
+ ),
+ 'SELECT' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'expr',
+ ),
+ 'TRUNCATE' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'UPDATE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
+ ),
+ 'VALUE' => array(
+ 'class' => 'SqlParser\\Components\\Array2d',
+ 'field' => 'values',
+ ),
+ 'VALUES' => array(
+ 'class' => 'SqlParser\\Components\\Array2d',
+ 'field' => 'values',
+ ),
+ 'WHERE' => array(
+ 'class' => 'SqlParser\\Components\\Condition',
+ 'field' => 'where',
+ ),
+
+ );
+
+ /**
+ * The list of tokens that are parsed.
+ *
+ * @var TokensList
+ */
+ public $list;
+
+ /**
+ * Whether errors should throw exceptions or just be stored.
+ *
+ * @var bool
+ *
+ * @see static::$errors
+ */
+ public $strict = false;
+
+ /**
+ * List of errors that occurred during parsing.
+ *
+ * Usually, the parsing does not stop once an error occurred because that
+ * error might be a false positive or a partial result (even a bad one)
+ * might be needed.
+ *
+ * @var ParserException[]
+ *
+ * @see Parser::error()
+ */
+ public $errors = array();
+
+ /**
+ * List of statements parsed.
+ *
+ * @var Statement[]
+ */
+ public $statements = array();
+
+ /**
+ * Constructor.
+ *
+ * @param string|UtfString|TokensList $list The list of tokens to be parsed.
+ * @param bool $strict Whether strict mode should be enabled or not.
+ */
+ public function __construct($list = null, $strict = false)
+ {
+ if ((is_string($list)) || ($list instanceof UtfString)) {
+ $lexer = new Lexer($list, $strict);
+ $this->list = $lexer->list;
+ } elseif ($list instanceof TokensList) {
+ $this->list = $list;
+ }
+
+ $this->strict = $strict;
+
+ if ($list !== null) {
+ $this->parse();
+ }
+ }
+
+ /**
+ * Builds the parse trees.
+ *
+ * @return void
+ */
+ public function parse()
+ {
+
+ /**
+ * Last transaction.
+ *
+ * @var TransactionStatement $lastTransaction
+ */
+ $lastTransaction = null;
+
+ /**
+ * Last parsed statement.
+ *
+ * @var Statement $lastStatement
+ */
+ $lastStatement = null;
+
+ /**
+ * Whether a union is parsed or not.
+ *
+ * @var bool $inUnion
+ */
+ $inUnion = false;
+
+ /**
+ * The index of the last token from the last statement.
+ *
+ * @var int $prevLastIdx
+ */
+ $prevLastIdx = -1;
+
+ /**
+ * The list of tokens.
+ *
+ * @var TokensList $list
+ */
+ $list = &$this->list;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // `DELIMITER` is not an actual statement and it requires
+ // special handling.
+ if (($token->type === Token::TYPE_NONE)
+ && (strtoupper($token->token) === 'DELIMITER')
+ ) {
+ // Skipping to the end of this statement.
+ $list->getNextOfType(Token::TYPE_DELIMITER);
+ $prevLastIdx = $list->idx;
+ continue;
+ }
+
+ // Statements can start with keywords only.
+ // Comments, whitespaces, etc. are ignored.
+ if ($token->type !== Token::TYPE_KEYWORD) {
+ if (($token->type !== TOKEN::TYPE_COMMENT)
+ && ($token->type !== Token::TYPE_WHITESPACE)
+ && ($token->type !== Token::TYPE_OPERATOR) // `(` and `)`
+ && ($token->type !== Token::TYPE_DELIMITER)
+ ) {
+ $this->error(
+ __('Unexpected beginning of statement.'),
+ $token
+ );
+ }
+ continue;
+ }
+
+ if ($token->value === 'UNION') {
+ $inUnion = true;
+ continue;
+ }
+
+ // Checking if it is a known statement that can be parsed.
+ if (empty(static::$STATEMENT_PARSERS[$token->value])) {
+ if (!isset(static::$STATEMENT_PARSERS[$token->value])) {
+ // A statement is considered recognized if the parser
+ // is aware that it is a statement, but it does not have
+ // a parser for it yet.
+ $this->error(
+ __('Unrecognized statement type.'),
+ $token
+ );
+ }
+ // Skipping to the end of this statement.
+ $list->getNextOfType(Token::TYPE_DELIMITER);
+ $prevLastIdx = $list->idx;
+ continue;
+ }
+
+ /**
+ * The name of the class that is used for parsing.
+ *
+ * @var string $class
+ */
+ $class = static::$STATEMENT_PARSERS[$token->value];
+
+ /**
+ * Processed statement.
+ *
+ * @var Statement $statement
+ */
+ $statement = new $class($this, $this->list);
+
+ // The first token that is a part of this token is the next token
+ // unprocessed by the previous statement.
+ // There might be brackets around statements and this shouldn't
+ // affect the parser
+ $statement->first = $prevLastIdx + 1;
+
+ // Storing the index of the last token parsed and updating the old
+ // index.
+ $statement->last = $list->idx;
+ $prevLastIdx = $list->idx;
+
+ // Handles unions.
+ if (($inUnion)
+ && ($lastStatement instanceof SelectStatement)
+ && ($statement instanceof SelectStatement)
+ ) {
+
+ /**
+ * This SELECT statement.
+ *
+ * @var SelectStatement $statement
+ */
+
+ /**
+ * Last SELECT statement.
+ *
+ * @var SelectStatement $lastStatement
+ */
+ $lastStatement->union[] = $statement;
+
+ // if there are no no delimiting brackets, the `ORDER` and
+ // `LIMIT` keywords actually belong to the first statement.
+ $lastStatement->order = $statement->order;
+ $lastStatement->limit = $statement->limit;
+ $statement->order = array();
+ $statement->limit = null;
+
+ // The statement actually ends where the last statement in
+ // union ends.
+ $lastStatement->last = $statement->last;
+
+ $inUnion = false;
+ continue;
+ }
+
+ // Handles transactions.
+ if ($statement instanceof TransactionStatement) {
+
+ /**
+ * @var TransactionStatement $statement
+ */
+ if ($statement->type === TransactionStatement::TYPE_BEGIN) {
+ $lastTransaction = $statement;
+ $this->statements[] = $statement;
+ } elseif ($statement->type === TransactionStatement::TYPE_END) {
+ if ($lastTransaction === null) {
+ // Even though an error occurred, the query is being
+ // saved.
+ $this->statements[] = $statement;
+ $this->error(
+ __('No transaction was previously started.'),
+ $token
+ );
+ } else {
+ $lastTransaction->end = $statement;
+ }
+ $lastTransaction = null;
+ }
+ continue;
+ }
+
+ // Finally, storing the statement.
+ if ($lastTransaction !== null) {
+ $lastTransaction->statements[] = $statement;
+ } else {
+ $this->statements[] = $statement;
+ }
+ $lastStatement = $statement;
+
+ }
+ }
+
+ /**
+ * Creates a new error log.
+ *
+ * @param string $msg The error message.
+ * @param Token $token The token that produced the error.
+ * @param int $code The code of the error.
+ *
+ * @throws ParserException Throws the exception, if strict mode is enabled.
+ *
+ * @return void
+ */
+ public function error($msg = '', Token $token = null, $code = 0)
+ {
+ $error = new ParserException($msg, $token, $code);
+ if ($this->strict) {
+ throw $error;
+ }
+ $this->errors[] = $error;
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php
new file mode 100644
index 0000000000..0568d93773
--- /dev/null
+++ b/libraries/sql-parser/src/Statement.php
@@ -0,0 +1,355 @@
+<?php
+
+/**
+ * The result of the parser is an array of statements are extensions of the
+ * class defined here.
+ *
+ * A statement represents the result of parsing the lexemes.
+ *
+ * @package SqlParser
+ */
+namespace SqlParser;
+
+use SqlParser\Components\OptionsArray;
+
+/**
+ * Abstract statement definition.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+abstract class Statement
+{
+
+ /**
+ * Options for this statement.
+ *
+ * The option would be the key and the value can be an integer or an array.
+ *
+ * The integer represents only the index used.
+ *
+ * The array may have two keys: `0` is used to represent the index used and
+ * `1` is the type of the option (which may be 'var' or 'var='). Both
+ * options mean they expect a value after the option (e.g. `A = B` or `A B`,
+ * in which case `A` is the key and `B` is the value). The only difference
+ * is in the building process. `var` options are built as `A B` and `var=`
+ * options are built as `A = B`
+ *
+ * Two options that can be used together must have different values for
+ * indexes, else, when they will be used together, an error will occur.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array();
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * The value attributed to each clause is used by the builder and it may
+ * have one of the following values:
+ *
+ * - 1 = 01 - add the clause only
+ * - 2 = 10 - add the keyword
+ * - 3 = 11 - add both the keyword and the clause
+ *
+ * @var array
+ */
+ public static $CLAUSES = array();
+
+ /**
+ * The options of this query.
+ *
+ * @var OptionsArray
+ *
+ * @see static::$OPTIONS
+ */
+ public $options;
+
+ /**
+ * The index of the first token used in this statement.
+ *
+ * @var int
+ */
+ public $first;
+
+ /**
+ * The index of the last token used in this statement.
+ *
+ * @var int
+ */
+ public $last;
+
+ /**
+ * Constructor.
+ *
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ */
+ public function __construct(Parser $parser = null, TokensList $list = null)
+ {
+ if (($parser !== null) && ($list !== null)) {
+ $this->parse($parser, $list);
+ }
+ }
+
+ /**
+ * Builds the string representation of this statement.
+ *
+ * @return string
+ */
+ public function build()
+ {
+ /**
+ * Query to be returned.
+ *
+ * @var string $query
+ */
+ $query = '';
+
+ foreach (static::$CLAUSES as $clause) {
+
+ /**
+ * The name of the clause.
+ *
+ * @var string $name
+ */
+ $name = $clause[0];
+
+ /**
+ * The type of the clause.
+ *
+ * @see self::$CLAUSES
+ * @var int $type
+ */
+ $type = $clause[1];
+
+ /**
+ * The builder (parser) of this clause.
+ *
+ * @var Component $class
+ */
+ $class = Parser::$KEYWORD_PARSERS[$name]['class'];
+
+ /**
+ * The name of the field that is used as source for the builder.
+ * Same field is used to store the result of parsing.
+ *
+ * @var string $field
+ */
+ $field = Parser::$KEYWORD_PARSERS[$name]['field'];
+
+ // The field is empty, there is nothing to be built.
+ if (empty($this->$field)) {
+ continue;
+ }
+
+ // Checking if the name of the clause should be added.
+ if ($type & 2) {
+ $query .= $name . ' ';
+ }
+
+ // Checking if the result of the builder should be added.
+ if ($type & 1) {
+ $query .= $class::build($this->$field) . ' ';
+ }
+ }
+
+ return $query;
+ }
+
+ /**
+ * Parses the statements defined by the tokens list.
+ *
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ *
+ * @return void
+ */
+ public function parse(Parser $parser, TokensList $list)
+ {
+ /**
+ * Array containing all list of clauses parsed.
+ * This is used to check for duplicates.
+ *
+ * @var array $parsedClauses
+ */
+ $parsedClauses = array();
+
+ // This may be corrected by the parser.
+ $this->first = $list->idx;
+
+ /**
+ * Whether options were parsed or not.
+ * For statements that do not have any options this is set to `true` by
+ * default.
+ *
+ * @var bool $parsedOptions
+ */
+ $parsedOptions = empty(static::$OPTIONS);
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Only keywords are relevant here. Other parts of the query are
+ // processed in the functions below.
+ if ($token->type !== Token::TYPE_KEYWORD) {
+ if (($token->type !== TOKEN::TYPE_COMMENT)
+ && ($token->type !== Token::TYPE_WHITESPACE)
+ ) {
+ $parser->error(__('Unexpected token.'), $token);
+ }
+ continue;
+ }
+
+ // Unions are parsed by the parser because they represent more than
+ // one statement.
+ if ($token->value === 'UNION') {
+ break;
+ }
+
+ /**
+ * The name of the class that is used for parsing.
+ *
+ * @var Component $class
+ */
+ $class = null;
+
+ /**
+ * The name of the field where the result of the parsing is stored.
+ *
+ * @var string $field
+ */
+ $field = null;
+
+ /**
+ * Parser's options.
+ *
+ * @var array $options
+ */
+ $options = array();
+
+ // Looking for duplicated clauses.
+ if ((!empty(Parser::$KEYWORD_PARSERS[$token->value]))
+ || (!empty(Parser::$STATEMENT_PARSERS[$token->value]))
+ ) {
+ if (!empty($parsedClauses[$token->value])) {
+ $parser->error(
+ __('This type of clause was previously parsed.'), $token
+ );
+ break;
+ }
+ $parsedClauses[$token->value] = true;
+ }
+
+ // Checking if this is the beginning of a clause.
+ if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) {
+ $class = Parser::$KEYWORD_PARSERS[$token->value]['class'];
+ $field = Parser::$KEYWORD_PARSERS[$token->value]['field'];
+ if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) {
+ $options = Parser::$KEYWORD_PARSERS[$token->value]['options'];
+ }
+ }
+
+ // Checking if this is the beginning of the statement.
+ if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
+ if ((!empty(static::$CLAUSES)) // Undefined for some statements.
+ && (empty(static::$CLAUSES[$token->value]))
+ ) {
+ // Some keywords (e.g. `SET`) may be the beginning of a
+ // statement and a clause.
+ // If such keyword was found and it cannot be a clause of
+ // this statement it means it is a new statement, but no
+ // delimiter was found between them.
+ $parser->error(
+ __('A new statement was found, but no delimiter between it and the previous one.'),
+ $token
+ );
+ break;
+ }
+ if (!$parsedOptions) {
+ if (empty(static::$OPTIONS[$token->value])) {
+ // Skipping keyword because if it is not a option.
+ ++$list->idx;
+ }
+ $this->options = OptionsArray::parse(
+ $parser,
+ $list,
+ static::$OPTIONS
+ );
+ $parsedOptions = true;
+ }
+ } elseif ($class === null) {
+ // There is no parser for this keyword and isn't the beginning
+ // of a statement (so no options) either.
+ $parser->error(__('Unrecognized keyword.'), $token);
+ continue;
+ }
+
+ $this->before($parser, $list, $token);
+
+ // Parsing this keyword.
+ if ($class !== null) {
+ ++$list->idx; // Skipping keyword or last option.
+ $this->$field = $class::parse($parser, $list, $options);
+ }
+
+ $this->after($parser, $list, $token);
+ }
+
+ // This may be corrected by the parser.
+ $this->last = --$list->idx; // Go back to last used token.
+ }
+
+ /**
+ * Function called before the token is processed.
+ *
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ * @param Token $token The token that is being parsed.
+ *
+ * @return void
+ */
+ public function before(Parser $parser, TokensList $list, Token $token)
+ {
+
+ }
+
+ /**
+ * Function called after the token was processed.
+ *
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ * @param Token $token The token that is being parsed.
+ *
+ * @return void
+ */
+ public function after(Parser $parser, TokensList $list, Token $token)
+ {
+
+ }
+
+ /**
+ * Builds the string representation of this statement.
+ *
+ * @see static::build
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->build();
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/AlterStatement.php b/libraries/sql-parser/src/Statements/AlterStatement.php
new file mode 100644
index 0000000000..31bbcb4540
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/AlterStatement.php
@@ -0,0 +1,140 @@
+<?php
+
+/**
+ * `ALTER` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+use SqlParser\Components\AlterOperation;
+use SqlParser\Components\Expression;
+use SqlParser\Components\OptionsArray;
+
+/**
+ * `ALTER` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class AlterStatement extends Statement
+{
+
+ /**
+ * Table affected.
+ *
+ * @var Expression
+ */
+ public $table;
+
+ /**
+ * Column affected by this statement.
+ *
+ * @var AlterOperation[]
+ */
+ public $altered = array();
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'ONLINE' => 1,
+ 'OFFLINE' => 1,
+ 'IGNORE' => 2,
+ );
+
+ /**
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ *
+ * @return void
+ */
+ public function parse(Parser $parser, TokensList $list)
+ {
+ ++$list->idx; // Skipping `ALTER`.
+ $this->options = OptionsArray::parse(
+ $parser,
+ $list,
+ static::$OPTIONS
+ );
+
+ // Skipping `TABLE`.
+ $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE');
+
+ // Parsing affected table.
+ $this->table = Expression::parse(
+ $parser, $list, array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ )
+ );
+ ++$list->idx; // Skipping field.
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -----------------[ alter operation ]-----------------> 1
+ *
+ * 1 -------------------------[ , ]-----------------------> 0
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $this->altered[] = AlterOperation::parse($parser, $list);
+ $state = 1;
+ } else if ($state === 1) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
+ $state = 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function build()
+ {
+ $tmp = array();
+ foreach ($this->altered as $altered) {
+ $tmp[] = $altered::build($altered);
+ }
+
+ return 'ALTER ' . OptionsArray::build($this->options)
+ . ' TABLE ' . Expression::build($this->table)
+ . ' ' . implode(', ', $tmp);
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/AnalyzeStatement.php b/libraries/sql-parser/src/Statements/AnalyzeStatement.php
new file mode 100644
index 0000000000..b6ae99e8c0
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/AnalyzeStatement.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * `ANALYZE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\Expression;
+
+/**
+ * `ANALYZE` statement.
+ *
+ * ANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE
+ * tbl_name [, tbl_name] ...
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class AnalyzeStatement extends Statement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'NO_WRITE_TO_BINLOG' => 2,
+ 'LOCAL' => 3,
+ );
+
+ /**
+ * Analyzed tables.
+ *
+ * @var Expression[]
+ */
+ public $tables;
+}
diff --git a/libraries/sql-parser/src/Statements/BackupStatement.php b/libraries/sql-parser/src/Statements/BackupStatement.php
new file mode 100644
index 0000000000..5a58a2acb4
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/BackupStatement.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * `BACKUP` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `BACKUP` statement.
+ *
+ * BACKUP TABLE tbl_name [, tbl_name] ... TO '/path/to/backup/directory'
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class BackupStatement extends MaintenanceStatement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'NO_WRITE_TO_BINLOG' => 2,
+ 'LOCAL' => 3,
+
+ 'TO' => array(4, 'var'),
+ );
+}
diff --git a/libraries/sql-parser/src/Statements/CallStatement.php b/libraries/sql-parser/src/Statements/CallStatement.php
new file mode 100644
index 0000000000..bac73ee530
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/CallStatement.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * `CALL` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\FunctionCall;
+
+/**
+ * `CALL` statement.
+ *
+ * CALL sp_name([parameter[,...]])
+ *
+ * or
+ *
+ * CALL sp_name[()]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class CallStatement extends Statement
+{
+
+ /**
+ * The name of the function and its parameters.
+ *
+ * @var FunctionCall
+ */
+ public $call;
+}
diff --git a/libraries/sql-parser/src/Statements/CheckStatement.php b/libraries/sql-parser/src/Statements/CheckStatement.php
new file mode 100644
index 0000000000..8ffa9460f5
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/CheckStatement.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * `CHECK` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `CHECK` statement.
+ *
+ * CHECK TABLE tbl_name [, tbl_name] ... [option] ...
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class CheckStatement extends MaintenanceStatement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'FOR UPGRADE' => 2,
+ 'QUICK' => 3,
+ 'FAST' => 4,
+ 'MEDIUM' => 5,
+ 'EXTENDED' => 6,
+ 'CHANGED' => 7,
+ );
+}
diff --git a/libraries/sql-parser/src/Statements/ChecksumStatement.php b/libraries/sql-parser/src/Statements/ChecksumStatement.php
new file mode 100644
index 0000000000..7c66bed786
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/ChecksumStatement.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * `CHECKSUM` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `CHECKSUM` statement.
+ *
+ * CHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ChecksumStatement extends MaintenanceStatement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'QUICK' => 2,
+ 'EXTENDED' => 3,
+ );
+}
diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php
new file mode 100644
index 0000000000..9b07737d7f
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/CreateStatement.php
@@ -0,0 +1,554 @@
+<?php
+
+/**
+ * `CREATE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+use SqlParser\Components\ArrayObj;
+use SqlParser\Components\DataType;
+use SqlParser\Components\CreateDefinition;
+use SqlParser\Components\PartitionDefinition;
+use SqlParser\Components\Expression;
+use SqlParser\Components\OptionsArray;
+use SqlParser\Components\ParameterDefinition;
+
+/**
+ * `CREATE` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class CreateStatement extends Statement
+{
+
+ /**
+ * Options for `CREATE` statements.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ // CREATE TABLE
+ 'TEMPORARY' => 1,
+
+ // CREATE VIEW
+ 'OR REPLACE' => array(2, 'var='),
+ 'ALGORITHM' => array(3, 'var='),
+ // `DEFINER` is also used for `CREATE FUNCTION / PROCEDURE`
+ 'DEFINER' => array(4, 'var='),
+ 'SQL SECURITY' => array(5, 'var'),
+
+ 'DATABASE' => 6,
+ 'EVENT' => 6,
+ 'FUNCTION' => 6,
+ 'INDEX' => 6,
+ 'PROCEDURE' => 6,
+ 'SERVER' => 6,
+ 'TABLE' => 6,
+ 'TABLESPACE' => 6,
+ 'TRIGGER' => 6,
+ 'USER' => 6,
+ 'VIEW' => 6,
+
+ // CREATE TABLE
+ 'IF NOT EXISTS' => 7,
+ );
+
+ /**
+ * All database options.
+ *
+ * @var array
+ */
+ public static $DB_OPTIONS = array(
+ 'CHARACTER SET' => array(1, 'var='),
+ 'CHARSET' => array(1, 'var='),
+ 'DEFAULT CHARACTER SET' => array(1, 'var='),
+ 'DEFAULT CHARSET' => array(1, 'var='),
+ 'DEFAULT COLLATE' => array(2, 'var='),
+ 'COLLATE' => array(2, 'var='),
+ );
+
+ /**
+ * All table options.
+ *
+ * @var array
+ */
+ public static $TABLE_OPTIONS = array(
+ 'ENGINE' => array(1, 'var='),
+ 'AUTO_INCREMENT' => array(2, 'var='),
+ 'AVG_ROW_LENGTH' => array(3, 'var'),
+ 'CHARACTER SET' => array(4, 'var='),
+ 'CHARSET' => array(4, 'var='),
+ 'DEFAULT CHARACTER SET' => array(4, 'var='),
+ 'DEFAULT CHARSET' => array(4, 'var='),
+ 'CHECKSUM' => array(5, 'var'),
+ 'DEFAULT COLLATE' => array(6, 'var='),
+ 'COLLATE' => array(6, 'var='),
+ 'COMMENT' => array(7, 'var='),
+ 'CONNECTION' => array(8, 'var'),
+ 'DATA DIRECTORY' => array(9, 'var'),
+ 'DELAY_KEY_WRITE' => array(10, 'var'),
+ 'INDEX DIRECTORY' => array(11, 'var'),
+ 'INSERT_METHOD' => array(12, 'var'),
+ 'KEY_BLOCK_SIZE' => array(13, 'var'),
+ 'MAX_ROWS' => array(14, 'var'),
+ 'MIN_ROWS' => array(15, 'var'),
+ 'PACK_KEYS' => array(16, 'var'),
+ 'PASSWORD' => array(17, 'var'),
+ 'ROW_FORMAT' => array(18, 'var'),
+ 'TABLESPACE' => array(19, 'var'),
+ 'STORAGE' => array(20, 'var'),
+ 'UNION' => array(21, 'var'),
+ );
+
+ /**
+ * All function options.
+ *
+ * @var array
+ */
+ public static $FUNC_OPTIONS = array(
+ 'COMMENT' => array(1, 'var='),
+ 'LANGUAGE SQL' => 2,
+ 'DETERMINISTIC' => 3,
+ 'NOT DETERMINISTIC' => 3,
+ 'CONTAINS SQL' => 4,
+ 'NO SQL' => 4,
+ 'READS SQL DATA' => 4,
+ 'MODIFIES SQL DATA' => 4,
+ 'SQL SECURITY DEFINER' => array(5, 'var'),
+ );
+
+ /**
+ * All trigger options.
+ *
+ * @var array
+ */
+ public static $TRIGGER_OPTIONS = array(
+ 'BEFORE' => 1,
+ 'AFTER' => 1,
+ 'INSERT' => 2,
+ 'UPDATE' => 2,
+ 'DELETE' => 2,
+ );
+
+ /**
+ * The name of the entity that is created.
+ *
+ * Used by all `CREATE` statements.
+ *
+ * @var Expression
+ */
+ public $name;
+
+ /**
+ * The options of the entity (table, procedure, function, etc.).
+ *
+ * Used by `CREATE TABLE`, `CREATE FUNCTION` and `CREATE PROCEDURE`.
+ *
+ * @var OptionsArray
+ *
+ * @see static::$TABLE_OPTIONS
+ * @see static::$FUNC_OPTIONS
+ * @see static::$TRIGGER_OPTIONS
+ */
+ public $entityOptions;
+
+ /**
+ * If `CREATE TABLE`, a list of columns and keys.
+ * If `CREATE VIEW`, a list of columns.
+ *
+ * Used by `CREATE TABLE` and `CREATE VIEW`.
+ *
+ * @var CreateDefinition[]|ArrayObj
+ */
+ public $fields;
+
+ /**
+ * Expression used for partitioning.
+ *
+ * @var string
+ */
+ public $partitionBy;
+
+ /**
+ * The number of partitions.
+ *
+ * @var int
+ */
+ public $partitionsNum;
+
+ /**
+ * Expression used for subpartitioning.
+ *
+ * @var string
+ */
+ public $subpartitionBy;
+
+ /**
+ * The number of subpartitions.
+ *
+ * @var int
+ */
+ public $subpartitionsNum;
+
+ /**
+ * The partition of the new table.
+ *
+ * @var PartitionDefinition[]
+ */
+ public $partitions;
+
+ /**
+ * If `CREATE TRIGGER` the name of the table.
+ *
+ * Used by `CREATE TRIGGER`.
+ *
+ * @var Expression
+ */
+ public $table;
+
+ /**
+ * The return data type of this routine.
+ *
+ * Used by `CREATE FUNCTION`.
+ *
+ * @var DataType
+ */
+ public $return;
+
+ /**
+ * The parameters of this routine.
+ *
+ * Used by `CREATE FUNCTION` and `CREATE PROCEDURE`.
+ *
+ * @var ParameterDefinition[]
+ */
+ public $parameters;
+
+ /**
+ * The body of this function or procedure. For views, it is the select
+ * statement that gets the
+ *
+ * Used by `CREATE FUNCTION`, `CREATE PROCEDURE` and `CREATE VIEW`.
+ *
+ * @var Token[]|string
+ */
+ public $body = array();
+
+ /**
+ * @return string
+ */
+ public function build()
+ {
+ $fields = '';
+ if (!empty($this->fields)) {
+ if (is_array($this->fields)) {
+ $fields = CreateDefinition::build($this->fields) . ' ';
+ } elseif ($this->fields instanceof ArrayObj) {
+ $fields = ArrayObj::build($this->fields);
+ }
+ }
+ if ($this->options->has('DATABASE')) {
+ return 'CREATE '
+ . OptionsArray::build($this->options) . ' '
+ . Expression::build($this->name) . ' '
+ . OptionsArray::build($this->entityOptions);
+ } elseif ($this->options->has('TABLE')) {
+ $partition = '';
+
+ if (!empty($this->partitionBy)) {
+ $partition .= "\nPARTITION BY " . $this->partitionBy;
+ }
+ if (!empty($this->partitionsNum)) {
+ $partition .= "\nPARTITIONS " . $this->partitionsNum;
+ }
+ if (!empty($this->subpartitionBy)) {
+ $partition .= "\nSUBPARTITION BY " . $this->subpartitionBy;
+ }
+ if (!empty($this->subpartitionsNum)) {
+ $partition .= "\nSUBPARTITIONS " . $this->subpartitionsNum;
+ }
+ if (!empty($this->partitions)) {
+ $partition .= "\n" . PartitionDefinition::build($this->partitions);
+ }
+
+ return 'CREATE '
+ . OptionsArray::build($this->options) . ' '
+ . Expression::build($this->name) . ' '
+ . $fields
+ . OptionsArray::build($this->entityOptions)
+ . $partition;
+ } elseif ($this->options->has('VIEW')) {
+ return 'CREATE '
+ . OptionsArray::build($this->options) . ' '
+ . Expression::build($this->name) . ' '
+ . $fields . ' AS ' . TokensList::build($this->body) . ' '
+ . OptionsArray::build($this->entityOptions);
+ } elseif ($this->options->has('TRIGGER')) {
+ return 'CREATE '
+ . OptionsArray::build($this->options) . ' '
+ . Expression::build($this->name) . ' '
+ . OptionsArray::build($this->entityOptions) . ' '
+ . 'ON ' . Expression::build($this->table) . ' '
+ . 'FOR EACH ROW ' . TokensList::build($this->body);
+ } elseif (($this->options->has('PROCEDURE'))
+ || ($this->options->has('FUNCTION'))
+ ) {
+ $tmp = '';
+ if ($this->options->has('FUNCTION')) {
+ $tmp = 'RETURNS ' . DataType::build($this->return);
+ }
+ return 'CREATE '
+ . OptionsArray::build($this->options) . ' '
+ . Expression::build($this->name) . ' '
+ . ParameterDefinition::build($this->parameters) . ' '
+ . $tmp . ' ' . TokensList::build($this->body);
+ }
+ return '';
+ }
+
+ /**
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ *
+ * @return void
+ */
+ public function parse(Parser $parser, TokensList $list)
+ {
+ ++$list->idx; // Skipping `CREATE`.
+
+ // Parsing options.
+ $this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
+ ++$list->idx; // Skipping last option.
+
+ // Parsing the field name.
+ $this->name = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ )
+ );
+
+ if ((!isset($this->name)) || ($this->name === '')) {
+ $parser->error(
+ __('The name of the entity was expected.'),
+ $list->tokens[$list->idx]
+ );
+ } else {
+ ++$list->idx; // Skipping field.
+ }
+
+ if ($this->options->has('DATABASE')) {
+ $this->entityOptions = OptionsArray::parse(
+ $parser,
+ $list,
+ static::$DB_OPTIONS
+ );
+ } elseif ($this->options->has('TABLE')) {
+ $this->fields = CreateDefinition::parse($parser, $list);
+ if (empty($this->fields)) {
+ $parser->error(
+ __('At least one column definition was expected.'),
+ $list->tokens[$list->idx]
+ );
+ }
+ ++$list->idx;
+
+ $this->entityOptions = OptionsArray::parse(
+ $parser,
+ $list,
+ static::$TABLE_OPTIONS
+ );
+
+ /**
+ * The field that is being filled (`partitionBy` or
+ * `subpartitionBy`).
+ *
+ * @var string $field
+ */
+ $field = null;
+
+ /**
+ * The number of brackets. `false` means no bracket was found
+ * previously. At least one bracket is required to validate the
+ * expression.
+ *
+ * @var int|bool $brackets
+ */
+ $brackets = false;
+
+ /*
+ * Handles partitions.
+ */
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping comments.
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'PARTITION BY')) {
+ $field = 'partitionBy';
+ $brackets = false;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'SUBPARTITION BY')) {
+ $field = 'subpartitionBy';
+ $brackets = false;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'PARTITIONS')) {
+ $token = $list->getNextOfType(Token::TYPE_NUMBER);
+ --$list->idx; // `getNextOfType` also advances one position.
+ $this->partitionsNum = $token->value;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'SUBPARTITIONS')) {
+ $token = $list->getNextOfType(Token::TYPE_NUMBER);
+ --$list->idx; // `getNextOfType` also advances one position.
+ $this->subpartitionsNum = $token->value;
+ } elseif (!empty($field)) {
+
+ /*
+ * Handling the content of `PARTITION BY` and `SUBPARTITION BY`.
+ */
+
+ // Counting brackets.
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ // This is used instead of `++$brackets` because,
+ // initially, `$brackets` is `false` cannot be
+ // incremented.
+ $brackets = $brackets + 1;
+ } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ')')) {
+ --$brackets;
+ }
+
+ // Building the expression used for partitioning.
+ $this->$field .= ($token->type === Token::TYPE_WHITESPACE) ? ' ' : $token->token;
+
+ // Last bracket was read, the expression ended.
+ // Comparing with `0` and not `false`, because `false` means
+ // that no bracket was found and at least one must is
+ // required.
+ if ($brackets === 0) {
+ $this->$field = trim($this->$field);
+ $field = null;
+ }
+ } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ if (!empty($this->partitionBy)) {
+ $this->partitions = ArrayObj::parse(
+ $parser,
+ $list,
+ array(
+ 'type' => 'SqlParser\\Components\\PartitionDefinition'
+ )
+ );
+ }
+ break;
+ }
+ }
+ } elseif (($this->options->has('PROCEDURE'))
+ || ($this->options->has('FUNCTION'))
+ ) {
+ $this->parameters = ParameterDefinition::parse($parser, $list);
+ if ($this->options->has('FUNCTION')) {
+ $token = $list->getNextOfType(Token::TYPE_KEYWORD);
+ if ($token->value !== 'RETURNS') {
+ $parser->error(
+ __('A "RETURNS" keyword was expected.'),
+ $token
+ );
+ } else {
+ ++$list->idx;
+ $this->return = DataType::parse(
+ $parser,
+ $list
+ );
+ }
+ }
+ ++$list->idx;
+
+ $this->entityOptions = OptionsArray::parse(
+ $parser,
+ $list,
+ static::$FUNC_OPTIONS
+ );
+ ++$list->idx;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+ $token = $list->tokens[$list->idx];
+ $this->body[] = $token;
+ }
+ } else if ($this->options->has('VIEW')) {
+ $token = $list->getNext(); // Skipping whitespaces and comments.
+
+ // Parsing columns list.
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ --$list->idx; // getNext() also goes forward one field.
+ $this->fields = ArrayObj::parse($parser, $list);
+ ++$list->idx; // Skipping last token from the array.
+ $list->getNext();
+ }
+
+ // Parsing the `AS` keyword.
+ for (; $list->idx < $list->count; ++$list->idx) {
+ $token = $list->tokens[$list->idx];
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+ $this->body[] = $token;
+ }
+ } else if ($this->options->has('TRIGGER')) {
+ // Parsing the time and the event.
+ $this->entityOptions = OptionsArray::parse(
+ $parser,
+ $list,
+ static::$TRIGGER_OPTIONS
+ );
+ ++$list->idx;
+
+ $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'ON');
+ ++$list->idx; // Skipping `ON`.
+
+ // Parsing the name of the table.
+ $this->table = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ )
+ );
+ ++$list->idx;
+
+ $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'FOR EACH ROW');
+ ++$list->idx; // Skipping `FOR EACH ROW`.
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+ $token = $list->tokens[$list->idx];
+ $this->body[] = $token;
+ }
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/DeleteStatement.php b/libraries/sql-parser/src/Statements/DeleteStatement.php
new file mode 100644
index 0000000000..0e13881926
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/DeleteStatement.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * `DELETE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\ArrayObj;
+use SqlParser\Components\Expression;
+use SqlParser\Components\Limit;
+use SqlParser\Components\OrderKeyword;
+use SqlParser\Components\Condition;
+
+/**
+ * `DELETE` statement.
+ *
+ * DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
+ * [PARTITION (partition_name,...)]
+ * [WHERE where_condition]
+ * [ORDER BY ...]
+ * [LIMIT row_count]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class DeleteStatement extends Statement
+{
+
+ /**
+ * Options for `DELETE` statements.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'LOW_PRIORITY' => 1,
+ 'QUICK' => 2,
+ 'IGNORE' => 3,
+ );
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'DELETE' => array('DELETE', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ 'FROM' => array('FROM', 3),
+ 'PARTITION' => array('PARTITION', 3),
+ 'WHERE' => array('WHERE', 3),
+ 'ORDER BY' => array('ORDER BY', 3),
+ 'LIMIT' => array('LIMIT', 3),
+ );
+
+ /**
+ * Tables used as sources for this statement.
+ *
+ * @var Expression[]
+ */
+ public $from;
+
+ /**
+ * Partitions used as source for this statement.
+ *
+ * @var ArrayObj
+ */
+ public $partition;
+
+ /**
+ * Conditions used for filtering each row of the result set.
+ *
+ * @var Condition[]
+ */
+ public $where;
+
+ /**
+ * Specifies the order of the rows in the result set.
+ *
+ * @var OrderKeyword[]
+ */
+ public $order;
+
+ /**
+ * Conditions used for limiting the size of the result set.
+ *
+ * @var Limit
+ */
+ public $limit;
+}
diff --git a/libraries/sql-parser/src/Statements/DropStatement.php b/libraries/sql-parser/src/Statements/DropStatement.php
new file mode 100644
index 0000000000..70583ed83b
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/DropStatement.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * `DROP` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\Expression;
+
+/**
+ * `DROP` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class DropStatement extends Statement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'DATABASE' => 1,
+ 'EVENT' => 1,
+ 'FUNCTION' => 1,
+ 'INDEX' => 1,
+ 'LOGFILE' => 1,
+ 'PROCEDURE' => 1,
+ 'SCHEMA' => 1,
+ 'SERVER' => 1,
+ 'TABLE' => 1,
+ 'TABLESPACE' => 1,
+ 'TRIGGER' => 1,
+
+ 'TEMPORARY' => 2,
+ 'IF EXISTS' => 3,
+ );
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'DROP' => array('DROP', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ // Used for select expressions.
+ 'DROP_' => array('DROP', 1),
+ );
+
+ /**
+ * Dropped elements.
+ *
+ * @var Expression[]
+ */
+ public $fields;
+}
diff --git a/libraries/sql-parser/src/Statements/ExplainStatement.php b/libraries/sql-parser/src/Statements/ExplainStatement.php
new file mode 100644
index 0000000000..eb869643cb
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/ExplainStatement.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * `EXPLAIN` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `EXPLAIN` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ExplainStatement extends NotImplementedStatement
+{
+
+}
diff --git a/libraries/sql-parser/src/Statements/InsertStatement.php b/libraries/sql-parser/src/Statements/InsertStatement.php
new file mode 100644
index 0000000000..303de259b6
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/InsertStatement.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * `INSERT` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\IntoKeyword;
+use SqlParser\Components\Array2d;
+
+/**
+ * `INSERT` statement.
+ *
+ * INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
+ * [INTO] tbl_name
+ * [PARTITION (partition_name,...)]
+ * [(col_name,...)]
+ * {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
+ * [ ON DUPLICATE KEY UPDATE
+ * col_name=expr
+ * [, col_name=expr] ... ]
+ *
+ * or
+ *
+ * INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
+ * [INTO] tbl_name
+ * [PARTITION (partition_name,...)]
+ * SET col_name={expr | DEFAULT}, ...
+ * [ ON DUPLICATE KEY UPDATE
+ * col_name=expr
+ * [, col_name=expr] ... ]
+ *
+ * or
+ *
+ * INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
+ * [INTO] tbl_name
+ * [PARTITION (partition_name,...)]
+ * [(col_name,...)]
+ * SELECT ...
+ * [ ON DUPLICATE KEY UPDATE
+ * col_name=expr
+ * [, col_name=expr] ... ]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class InsertStatement extends Statement
+{
+
+ /**
+ * Options for `INSERT` statements.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'LOW_PRIORITY' => 1,
+ 'DELAYED' => 2,
+ 'HIGH_PRIORITY' => 3,
+ 'IGNORE' => 4,
+ );
+
+ /**
+ * Tables used as target for this statement.
+ *
+ * @var IntoKeyword
+ */
+ public $into;
+
+ /**
+ * Values to be inserted.
+ *
+ * @var Array2d
+ */
+ public $values;
+}
diff --git a/libraries/sql-parser/src/Statements/MaintenanceStatement.php b/libraries/sql-parser/src/Statements/MaintenanceStatement.php
new file mode 100644
index 0000000000..952314e8f2
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/MaintenanceStatement.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * Maintenance statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+use SqlParser\Components\Expression;
+use SqlParser\Components\OptionsArray;
+
+/**
+ * Maintenance statement.
+ *
+ * They follow the syntax:
+ * STMT [some options] tbl_name [, tbl_name] ... [some more options]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class MaintenanceStatement extends Statement
+{
+
+ /**
+ * Tables maintained.
+ *
+ * @var Expression[]
+ */
+ public $tables;
+
+ /**
+ * Function called after the token was processed.
+ *
+ * Parses the additional options from the end.
+ *
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ * @param Token $token The token that is being parsed.
+ *
+ * @return void
+ */
+ public function after(Parser $parser, TokensList $list, Token $token)
+ {
+ // [some options] is going to be parsed first.
+ //
+ // There is a parser specified in `Parser::$KEYWORD_PARSERS`
+ // which parses the name of the tables.
+ //
+ // Finally, we parse here [some more options] and that's all.
+ ++$list->idx;
+ $this->options->merge(
+ OptionsArray::parse(
+ $parser,
+ $list,
+ static::$OPTIONS
+ )
+ );
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/NotImplementedStatement.php b/libraries/sql-parser/src/Statements/NotImplementedStatement.php
new file mode 100644
index 0000000000..0a1dc338eb
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/NotImplementedStatement.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * Not implemented (yet) statements.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Not implemented (yet) statements.
+ *
+ * The `after` function makes the parser jump straight to the first delimiter.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class NotImplementedStatement extends Statement
+{
+
+ /**
+ * The part of the statement that can't be parsed.
+ *
+ * @var Token[]
+ */
+ public $unknown = array();
+
+ /**
+ * @return string
+ */
+ public function build()
+ {
+ // Building the parsed part of the query (if any).
+ $query = parent::build() . ' ';
+
+ // Rebuilding the unknown part from tokens.
+ foreach ($this->unknown as $token) {
+ $query .= $token->token;
+ }
+
+ return $query;
+ }
+
+ /**
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ *
+ * @return void
+ */
+ public function parse(Parser $parser, TokensList $list)
+ {
+ for (; $list->idx < $list->count; ++$list->idx) {
+ if ($list->tokens[$list->idx]->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+ $this->unknown[] = $list->tokens[$list->idx];
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/OptimizeStatement.php b/libraries/sql-parser/src/Statements/OptimizeStatement.php
new file mode 100644
index 0000000000..07150150da
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/OptimizeStatement.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * `OPTIMIZE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\Expression;
+
+/**
+ * `OPTIMIZE` statement.
+ *
+ * OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE
+ * tbl_name [, tbl_name] ...
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class OptimizeStatement extends Statement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'NO_WRITE_TO_BINLOG' => 2,
+ 'LOCAL' => 3,
+ );
+
+ /**
+ * Optimized tables.
+ *
+ * @var Expression[]
+ */
+ public $tables;
+}
diff --git a/libraries/sql-parser/src/Statements/RenameStatement.php b/libraries/sql-parser/src/Statements/RenameStatement.php
new file mode 100644
index 0000000000..6b4f1888e0
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/RenameStatement.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * `RENAME` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+use SqlParser\Components\RenameOperation;
+
+/**
+ * `RENAME` statement.
+ *
+ * RENAME TABLE tbl_name TO new_tbl_name
+ * [, tbl_name2 TO new_tbl_name2] ...
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class RenameStatement extends Statement
+{
+
+ /**
+ * The old and new names of the tables.
+ *
+ * @var RenameOperation[]
+ */
+ public $renames;
+
+ /**
+ * Function called before the token is processed.
+ *
+ * Skips the `TABLE` keyword after `RENAME`.
+ *
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ * @param Token $token The token that is being parsed.
+ *
+ * @return void
+ */
+ public function before(Parser $parser, TokensList $list, Token $token)
+ {
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'RENAME')) {
+ // Checking if it is the beginning of the query.
+ $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE');
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/RepairStatement.php b/libraries/sql-parser/src/Statements/RepairStatement.php
new file mode 100644
index 0000000000..b1d840b624
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/RepairStatement.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * `REPAIR` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `REPAIR` statement.
+ *
+ * REPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE
+ * tbl_name [, tbl_name] ...
+ * [QUICK] [EXTENDED] [USE_FRM]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class RepairStatement extends MaintenanceStatement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'NO_WRITE_TO_BINLOG' => 2,
+ 'LOCAL' => 3,
+
+ 'QUICK' => 4,
+ 'EXTENDED' => 5,
+ 'USE_FRM' => 6,
+ );
+}
diff --git a/libraries/sql-parser/src/Statements/ReplaceStatement.php b/libraries/sql-parser/src/Statements/ReplaceStatement.php
new file mode 100644
index 0000000000..10c5e6312a
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/ReplaceStatement.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * `REPLACE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\IntoKeyword;
+use SqlParser\Components\SetOperation;
+use SqlParser\Components\Array2d;
+
+/**
+ * `REPLACE` statement.
+ *
+ * REPLACE [LOW_PRIORITY | DELAYED]
+ * [INTO] tbl_name [(col_name,...)]
+ * {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
+ *
+ * or
+ *
+ * REPLACE [LOW_PRIORITY | DELAYED]
+ * [INTO] tbl_name
+ * SET col_name={expr | DEFAULT}, ...
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ReplaceStatement extends Statement
+{
+
+ /**
+ * Options for `REPLACE` statements and their slot ID.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'LOW_PRIORITY' => 1,
+ 'DELAYED' => 1,
+ );
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'REPLACE' => array('REPLACE', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ 'INTO' => array('FROM', 3),
+ 'VALUES' => array('VALUES', 1),
+ 'SET' => array('PARTITION', 3),
+ );
+
+ /**
+ * Tables used as target for this statement.
+ *
+ * @var IntoKeyword
+ */
+ public $into;
+
+ /**
+ * Values to be replaced.
+ *
+ * @var Array2d
+ */
+ public $values;
+
+ /**
+ * The replaced values.
+ *
+ * @var SetOperation[]
+ */
+ public $set;
+}
diff --git a/libraries/sql-parser/src/Statements/RestoreStatement.php b/libraries/sql-parser/src/Statements/RestoreStatement.php
new file mode 100644
index 0000000000..be83dd64e1
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/RestoreStatement.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * `RESTORE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `RESTORE` statement.
+ *
+ * RESTORE TABLE tbl_name [, tbl_name] ... FROM '/path/to/backup/directory'
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class RestoreStatement extends MaintenanceStatement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+
+ 'TABLE' => 1,
+
+ 'FROM' => array(2, 'var'),
+ );
+}
diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php
new file mode 100644
index 0000000000..a19bd8e143
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/SelectStatement.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * `SELECT` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\ArrayObj;
+use SqlParser\Components\FunctionCall;
+use SqlParser\Components\Expression;
+use SqlParser\Components\IntoKeyword;
+use SqlParser\Components\JoinKeyword;
+use SqlParser\Components\Limit;
+use SqlParser\Components\OrderKeyword;
+use SqlParser\Components\Condition;
+
+/**
+ * `SELECT` statement.
+ *
+ * SELECT
+ * [ALL | DISTINCT | DISTINCTROW ]
+ * [HIGH_PRIORITY]
+ * [MAX_STATEMENT_TIME = N]
+ * [STRAIGHT_JOIN]
+ * [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
+ * [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
+ * select_expr [, select_expr ...]
+ * [FROM table_references
+ * [PARTITION partition_list]
+ * [WHERE where_condition]
+ * [GROUP BY {col_name | expr | position}
+ * [ASC | DESC], ... [WITH ROLLUP]]
+ * [HAVING where_condition]
+ * [ORDER BY {col_name | expr | position}
+ * [ASC | DESC], ...]
+ * [LIMIT {[offset,] row_count | row_count OFFSET offset}]
+ * [PROCEDURE procedure_name(argument_list)]
+ * [INTO OUTFILE 'file_name'
+ * [CHARACTER SET charset_name]
+ * export_options
+ * | INTO DUMPFILE 'file_name'
+ * | INTO var_name [, var_name]]
+ * [FOR UPDATE | LOCK IN SHARE MODE]]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class SelectStatement extends Statement
+{
+
+ /**
+ * Options for `SELECT` statements and their slot ID.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'ALL' => 1,
+ 'DISTINCT' => 1,
+ 'DISTINCTROW' => 1,
+ 'HIGH_PRIORITY' => 2,
+ 'MAX_STATEMENT_TIME' => array(3, 'var='),
+ 'STRAIGHT_JOIN' => 4,
+ 'SQL_SMALL_RESULT' => 5,
+ 'SQL_BIG_RESULT' => 6,
+ 'SQL_BUFFER_RESULT' => 7,
+ 'SQL_CACHE' => 8,
+ 'SQL_NO_CACHE' => 8,
+ 'SQL_CALC_FOUND_ROWS' => 9,
+ );
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'SELECT' => array('SELECT', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ // Used for selected expressions.
+ '_SELECT' => array('SELECT', 1),
+ 'FROM' => array('FROM', 3),
+ 'PARTITION' => array('PARTITION', 3),
+ 'JOIN' => array('JOIN', 1),
+ 'WHERE' => array('WHERE', 3),
+ 'GROUP BY' => array('GROUP BY', 3),
+ 'HAVING' => array('HAVING', 3),
+ 'ORDER BY' => array('ORDER BY', 3),
+ 'LIMIT' => array('LIMIT', 3),
+ 'PROCEDURE' => array('PROCEDURE', 3),
+ 'INTO' => array('INTO', 3),
+ 'UNION' => array('UNION', 3),
+ // These are available only when `UNION` is present.
+ // 'ORDER BY' => array('ORDER BY', 3),
+ // 'LIMIT' => array('LIMIT', 3),
+ );
+
+ /**
+ * Expressions that are being selected by this statement.
+ *
+ * @var Expression[]
+ */
+ public $expr = array();
+
+ /**
+ * Tables used as sources for this statement.
+ *
+ * @var Expression[]
+ */
+ public $from = array();
+
+ /**
+ * Partitions used as source for this statement.
+ *
+ * @var ArrayObj
+ */
+ public $partition;
+
+ /**
+ * Conditions used for filtering each row of the result set.
+ *
+ * @var Condition[]
+ */
+ public $where;
+
+ /**
+ * Conditions used for grouping the result set.
+ *
+ * @var OrderKeyword[]
+ */
+ public $group;
+
+ /**
+ * Conditions used for filtering the result set.
+ *
+ * @var Condition[]
+ */
+ public $having;
+
+ /**
+ * Specifies the order of the rows in the result set.
+ *
+ * @var OrderKeyword[]
+ */
+ public $order;
+
+ /**
+ * Conditions used for limiting the size of the result set.
+ *
+ * @var Limit
+ */
+ public $limit;
+
+ /**
+ * Procedure that should process the data in the result set.
+ *
+ * @var FunctionCall
+ */
+ public $procedure;
+
+ /**
+ * Destination of this result set.
+ *
+ * @var IntoKeyword
+ */
+ public $into;
+
+ /**
+ * Joins.
+ *
+ * @var JoinKeyword[]
+ */
+ public $join;
+
+ /**
+ * Unions.
+ *
+ * @var SelectStatement[]
+ */
+ public $union = array();
+}
diff --git a/libraries/sql-parser/src/Statements/SetStatement.php b/libraries/sql-parser/src/Statements/SetStatement.php
new file mode 100644
index 0000000000..d4128533a8
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/SetStatement.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * `SET` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\SetOperation;
+
+/**
+ * `SET` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class SetStatement extends Statement
+{
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'SET' => array('SET', 3),
+ );
+
+ /**
+ * The updated values.
+ *
+ * @var SetOperation[]
+ */
+ public $set;
+}
diff --git a/libraries/sql-parser/src/Statements/ShowStatement.php b/libraries/sql-parser/src/Statements/ShowStatement.php
new file mode 100644
index 0000000000..ae8cb3f55c
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/ShowStatement.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * `SHOW` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+/**
+ * `SHOW` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class ShowStatement extends NotImplementedStatement
+{
+
+ /**
+ * Options of this statement.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'CREATE' => 1,
+ 'AUTHORS' => 2,
+ 'BINARY' => 2,
+ 'BINLOG' => 2,
+ 'CHARACTER' => 2,
+ 'CODE' => 2,
+ 'COLLATION' => 2,
+ 'COLUMNS' => 2,
+ 'CONTRIBUTORS' => 2,
+ 'DATABASE' => 2,
+ 'DATABASES' => 2,
+ 'ENGINE' => 2,
+ 'ENGINES' => 2,
+ 'ERRORS' => 2,
+ 'EVENT' => 2,
+ 'EVENTS' => 2,
+ 'FUNCTION' => 2,
+ 'GRANTS' => 2,
+ 'HOSTS' => 2,
+ 'INDEX' => 2,
+ 'INNODB' => 2,
+ 'LOGS' => 2,
+ 'MASTER' => 2,
+ 'OPEN' => 2,
+ 'PLUGINS' => 2,
+ 'PRIVILEGES' => 2,
+ 'PROCEDURE' => 2,
+ 'PROCESSLIST' => 2,
+ 'PROFILE' => 2,
+ 'PROFILES' => 2,
+ 'SCHEDULER' => 2,
+ 'SET' => 2,
+ 'SLAVE' => 2,
+ 'STATUS' => 2,
+ 'TABLE' => 2,
+ 'TABLES' => 2,
+ 'TRIGGER' => 2,
+ 'TRIGGERS' => 2,
+ 'VARIABLES' => 2,
+ 'VIEW' => 2,
+ 'WARNINGS' => 2,
+ );
+}
diff --git a/libraries/sql-parser/src/Statements/TransactionStatement.php b/libraries/sql-parser/src/Statements/TransactionStatement.php
new file mode 100644
index 0000000000..0ae83fec3f
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/TransactionStatement.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * Transaction statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\TokensList;
+use SqlParser\Components\OptionsArray;
+
+/**
+ * Transaction statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class TransactionStatement extends Statement
+{
+
+ /**
+ * START TRANSACTION and BEGIN
+ *
+ * @var int
+ */
+ const TYPE_BEGIN = 1;
+
+ /**
+ * COMMIT and ROLLBACK
+ *
+ * @var int
+ */
+ const TYPE_END = 2;
+
+ /**
+ * The type of this query.
+ *
+ * @var int
+ */
+ public $type;
+
+ /**
+ * The list of statements in this transaction.
+ *
+ * @var Statement[]
+ */
+ public $statements;
+
+ /**
+ * The ending transaction statement which may be a `COMMIT` or a `ROLLBACK`.
+ *
+ * @var TransactionStatement
+ */
+ public $end;
+
+ /**
+ * Options for this query.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'START TRANSACTION' => 1,
+ 'BEGIN' => 1,
+ 'COMMIT' => 1,
+ 'ROLLBACK' => 1,
+ 'WITH CONSISTENT SNAPSHOT' => 2,
+ 'WORK' => 2,
+ 'AND NO CHAIN' => 3,
+ 'AND CHAIN' => 3,
+ 'RELEASE' => 4,
+ 'NO RELEASE' => 4,
+ );
+
+ /**
+ * @param Parser $parser The instance that requests parsing.
+ * @param TokensList $list The list of tokens to be parsed.
+ *
+ * @return void
+ */
+ public function parse(Parser $parser, TokensList $list)
+ {
+ parent::parse($parser, $list);
+
+ // Checks the type of this query.
+ if (($this->options->has('START TRANSACTION'))
+ || ($this->options->has('BEGIN'))
+ ) {
+ $this->type = TransactionStatement::TYPE_BEGIN;
+ } elseif (($this->options->has('COMMIT'))
+ || ($this->options->has('ROLLBACK'))
+ ) {
+ $this->type = TransactionStatement::TYPE_END;
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function build()
+ {
+ $ret = OptionsArray::build($this->options);
+ if ($this->type === TransactionStatement::TYPE_BEGIN) {
+ foreach ($this->statements as $statement) {
+ /**
+ * @var SelectStatement $statement
+ */
+ $ret .= ';' . $statement->build();
+ }
+ $ret .= ';' . $this->end->build();
+ }
+ return $ret;
+ }
+}
diff --git a/libraries/sql-parser/src/Statements/TruncateStatement.php b/libraries/sql-parser/src/Statements/TruncateStatement.php
new file mode 100644
index 0000000000..c0cb5fd2c1
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/TruncateStatement.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * `TRUNCATE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\Expression;
+
+/**
+ * `TRUNCATE` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class TruncateStatement extends Statement
+{
+
+ /**
+ * Options for `TRUNCATE` statements.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'TABLE' => 1,
+ );
+
+ /**
+ * The name of the truncated table.
+ *
+ * @var Expression
+ */
+ public $table;
+}
diff --git a/libraries/sql-parser/src/Statements/UpdateStatement.php b/libraries/sql-parser/src/Statements/UpdateStatement.php
new file mode 100644
index 0000000000..59b2ff72a3
--- /dev/null
+++ b/libraries/sql-parser/src/Statements/UpdateStatement.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * `UPDATE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Statement;
+use SqlParser\Components\Expression;
+use SqlParser\Components\Limit;
+use SqlParser\Components\OrderKeyword;
+use SqlParser\Components\SetOperation;
+use SqlParser\Components\Condition;
+
+/**
+ * `UPDATE` statement.
+ *
+ * UPDATE [LOW_PRIORITY] [IGNORE] table_reference
+ * SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
+ * [WHERE where_condition]
+ * [ORDER BY ...]
+ * [LIMIT row_count]
+ *
+ * or
+ *
+ * UPDATE [LOW_PRIORITY] [IGNORE] table_references
+ * SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
+ * [WHERE where_condition]
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class UpdateStatement extends Statement
+{
+
+ /**
+ * Options for `UPDATE` statements and their slot ID.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'LOW_PRIORITY' => 1,
+ 'IGNORE' => 2,
+ );
+
+ /**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'UPDATE' => array('UPDATE', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ // Used for updated tables.
+ '_UPDATE' => array('UPDATE', 1),
+ 'SET' => array('SET', 3),
+ 'WHERE' => array('WHERE', 3),
+ 'ORDER BY' => array('ORDER BY', 3),
+ 'LIMIT' => array('LIMIT', 3),
+ );
+
+ /**
+ * Tables used as sources for this statement.
+ *
+ * @var Expression[]
+ */
+ public $tables;
+
+ /**
+ * The updated values.
+ *
+ * @var SetOperation[]
+ */
+ public $set;
+
+ /**
+ * Conditions used for filtering each row of the result set.
+ *
+ * @var Condition[]
+ */
+ public $where;
+
+ /**
+ * Specifies the order of the rows in the result set.
+ *
+ * @var OrderKeyword[]
+ */
+ public $order;
+
+ /**
+ * Conditions used for limiting the size of the result set.
+ *
+ * @var Limit
+ */
+ public $limit;
+}
diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php
new file mode 100644
index 0000000000..d5343212cb
--- /dev/null
+++ b/libraries/sql-parser/src/Token.php
@@ -0,0 +1,292 @@
+<?php
+
+/**
+ * Defines a token along with a set of types and flags and utility functions.
+ *
+ * An array of tokens will result after parsing the query.
+ *
+ * @package SqlParser
+ */
+namespace SqlParser;
+
+/**
+ * A structure representing a lexeme that explicitly indicates its
+ * categorization for the purpose of parsing.
+ *
+ * @category Tokens
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Token
+{
+
+ // Types of tokens (a vague description of a token's purpose).
+
+ /**
+ * This type is used when the token is invalid or its type cannot be
+ * determined because of the ambiguous context. Further analysis might be
+ * required to detect its type.
+ *
+ * @var int
+ */
+ const TYPE_NONE = 0;
+
+ /**
+ * SQL specific keywords: SELECT, UPDATE, INSERT, etc.
+ *
+ * @var int
+ */
+ const TYPE_KEYWORD = 1;
+
+ /**
+ * Any type of legal operator.
+ *
+ * Arithmetic operators: +, -, *, /, etc.
+ * Logical operators: ===, <>, !==, etc.
+ * Bitwise operators: &, |, ^, etc.
+ * Assignment operators: =, +=, -=, etc.
+ * SQL specific operators: . (e.g. .. WHERE database.table ..),
+ * * (e.g. SELECT * FROM ..)
+ *
+ * @var int
+ */
+ const TYPE_OPERATOR = 2;
+
+ /**
+ * Spaces, tabs, new lines, etc.
+ *
+ * @var int
+ */
+ const TYPE_WHITESPACE = 3;
+
+ /**
+ * Any type of legal comment.
+ *
+ * Bash (#), C (/* *\/) or SQL (--) comments:
+ *
+ * -- SQL-comment
+ *
+ * #Bash-like comment
+ *
+ * /*C-like comment*\/
+ *
+ * or:
+ *
+ * /*C-like
+ * comment*\/
+ *
+ * Backslashes were added to respect PHP's comments syntax.
+ *
+ * @var int
+ */
+ const TYPE_COMMENT = 4;
+
+ /**
+ * Boolean values: true or false.
+ *
+ * @var int
+ */
+ const TYPE_BOOL = 5;
+
+ /**
+ * Numbers: 4, 0x8, 15.16, 23e42, etc.
+ *
+ * @var int
+ */
+ const TYPE_NUMBER = 6;
+
+ /**
+ * Literal strings: 'string', "test".
+ * Some of these strings are actually symbols.
+ *
+ * @var int
+ */
+ const TYPE_STRING = 7;
+
+ /**
+ * Database, table names, variables, etc.
+ * For example: ```SELECT `foo`, `bar` FROM `database`.`table`;```
+ *
+ * @var int
+ */
+ const TYPE_SYMBOL = 8;
+
+ /**
+ * Delimits an unknown string.
+ * For example: ```SELECT * FROM test;```, `test` is a delimiter.
+ *
+ * @var int
+ */
+ const TYPE_DELIMITER = 9;
+
+ // Flags that describe the tokens in more detail.
+ // All keywords must have flag 1 so `Context::isKeyword` method doesn't
+ // require strict comparison.
+ const FLAG_KEYWORD_RESERVED = 2;
+ const FLAG_KEYWORD_COMPOSED = 4;
+ const FLAG_KEYWORD_DATA_TYPE = 8;
+ const FLAG_KEYWORD_KEY = 16;
+ const FLAG_KEYWORD_FUNCTION = 32;
+
+ // Numbers related flags.
+ const FLAG_NUMBER_HEX = 1;
+ const FLAG_NUMBER_FLOAT = 2;
+ const FLAG_NUMBER_APPROXIMATE = 4;
+ const FLAG_NUMBER_NEGATIVE = 8;
+ const FLAG_NUMBER_BINARY = 16;
+
+ // Strings related flags.
+ const FLAG_STRING_SINGLE_QUOTES = 1;
+ const FLAG_STRING_DOUBLE_QUOTES = 2;
+
+ // Comments related flags.
+ const FLAG_COMMENT_BASH = 1;
+ const FLAG_COMMENT_C = 2;
+ const FLAG_COMMENT_SQL = 4;
+ const FLAG_COMMENT_MYSQL_CMD = 8;
+
+ // Operators related flags.
+ const FLAG_OPERATOR_ARITHMETIC = 1;
+ const FLAG_OPERATOR_LOGICAL = 2;
+ const FLAG_OPERATOR_BITWISE = 4;
+ const FLAG_OPERATOR_ASSIGNMENT = 8;
+ const FLAG_OPERATOR_SQL = 16;
+
+ // Symbols related flags.
+ const FLAG_SYMBOL_VARIABLE = 1;
+ const FLAG_SYMBOL_BACKTICK = 2;
+ const FLAG_SYMBOL_USER = 4;
+ const FLAG_SYMBOL_SYSTEM = 8;
+
+ /**
+ * The token it its raw string representation.
+ *
+ * @var string
+ */
+ public $token;
+
+ /**
+ * The value this token contains (i.e. token after some evaluation)
+ *
+ * @var mixed
+ */
+ public $value;
+
+ /**
+ * The type of this token.
+ *
+ * @var int
+ */
+ public $type;
+
+ /**
+ * The flags of this token.
+ *
+ * @var int
+ */
+ public $flags;
+
+ /**
+ * The position in the initial string where this token started.
+ *
+ * @var int
+ */
+ public $position;
+
+ /**
+ * Constructor.
+ *
+ * @param string $token The value of the token.
+ * @param int $type The type of the token.
+ * @param int $flags The flags of the token.
+ */
+ public function __construct($token, $type = 0, $flags = 0)
+ {
+ $this->token = $token;
+ $this->type = $type;
+ $this->flags = $flags;
+ $this->value = $this->extract();
+ }
+
+ /**
+ * Does little processing to the token to extract a value.
+ *
+ * If no processing can be done it will return the initial string.
+ *
+ * @return mixed
+ */
+ public function extract()
+ {
+ switch ($this->type) {
+ case Token::TYPE_KEYWORD:
+ if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ // Unreserved keywords should stay the way they are because they
+ // might represent field names.
+ return $this->token;
+ }
+ return strtoupper($this->token);
+ case Token::TYPE_WHITESPACE:
+ return ' ';
+ case Token::TYPE_BOOL:
+ return strtoupper($this->token) === 'TRUE';
+ case Token::TYPE_NUMBER:
+ $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42
+ if ($this->flags & Token::FLAG_NUMBER_HEX) {
+ if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) {
+ $ret = str_replace('-', '', $this->token);
+ sscanf($ret, "%x", $ret);
+ $ret = -$ret;
+ } else {
+ sscanf($ret, "%x", $ret);
+ }
+ } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE)
+ || ($this->flags & Token::FLAG_NUMBER_FLOAT)
+ ) {
+ sscanf($ret, "%f", $ret);
+ } else {
+ sscanf($ret, "%d", $ret);
+ }
+ return $ret;
+ case Token::TYPE_STRING:
+ $quote = $this->token[0];
+ $str = str_replace($quote . $quote, $quote, $this->token);
+ return mb_substr($str, 1, -1, 'UTF-8'); // trims quotes
+ case Token::TYPE_SYMBOL:
+ $str = $this->token;
+ if ((isset($str[0])) && ($str[0] === '@')) {
+ // `mb_strlen($str)` must be used instead of `null` because
+ // in PHP 5.3- the `null` parameter isn't handled correctly.
+ $str = mb_substr(
+ $str,
+ ((!empty($str[1])) && ($str[1] === '@')) ? 2 : 1,
+ mb_strlen($str),
+ 'UTF-8'
+ );
+ }
+ if ((isset($str[0])) && (($str[0] === '`')
+ || ($str[0] === '"') || ($str[0] === '\''))
+ ) {
+ $quote = $str[0];
+ $str = str_replace($quote . $quote, $quote, $str);
+ $str = mb_substr($str, 1, -1, 'UTF-8');
+ }
+ return $str;
+ }
+ return $this->token;
+ }
+
+ /**
+ * Converts the token into an inline token by replacing tabs and new lines.
+ *
+ * @return string
+ */
+ public function getInlineToken()
+ {
+ return str_replace(
+ array("\r", "\n", "\t"),
+ array('\r', '\n', '\t'),
+ $this->token
+ );
+ }
+}
diff --git a/libraries/sql-parser/src/TokensList.php b/libraries/sql-parser/src/TokensList.php
new file mode 100644
index 0000000000..10ff56e717
--- /dev/null
+++ b/libraries/sql-parser/src/TokensList.php
@@ -0,0 +1,208 @@
+<?php
+
+/**
+ * Defines an array of tokens and utility functions to iterate through it.
+ *
+ * @package SqlParser
+ */
+namespace SqlParser;
+
+/**
+ * A structure representing a list of tokens.
+ *
+ * @category Tokens
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class TokensList implements \ArrayAccess
+{
+
+ /**
+ * The array of tokens.
+ *
+ * @var array
+ */
+ public $tokens = array();
+
+ /**
+ * The count of tokens.
+ *
+ * @var int
+ */
+ public $count = 0;
+
+ /**
+ * The index of the next token to be returned.
+ *
+ * @var int
+ */
+ public $idx = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param array $tokens The initial array of tokens.
+ * @param int $count The count of tokens in the initial array.
+ */
+ public function __construct(array $tokens = array(), $count = -1)
+ {
+ if (!empty($tokens)) {
+ $this->tokens = $tokens;
+ if ($count === -1) {
+ $this->count = count($tokens);
+ }
+ }
+ }
+
+ /**
+ * Builds an array of tokens by merging their raw value.
+ *
+ * @param string|Token[]|TokensList $list The tokens to be built.
+ *
+ * @return string
+ */
+ public static function build($list)
+ {
+ if (is_string($list)) {
+ return $list;
+ }
+
+ if ($list instanceof TokensList) {
+ $list = $list->tokens;
+ }
+
+ $ret = '';
+ if (is_array($list)) {
+ foreach ($list as $tok) {
+ $ret .= $tok->token;
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Adds a new token.
+ *
+ * @param Token $token Token to be added in list.
+ *
+ * @return void
+ */
+ public function add(Token $token)
+ {
+ $this->tokens[$this->count++] = $token;
+ }
+
+ /**
+ * Gets the next token. Skips any irrelevant token (whitespaces and
+ * comments).
+ *
+ * @return Token
+ */
+ public function getNext()
+ {
+ for (; $this->idx < $this->count; ++$this->idx) {
+ if (($this->tokens[$this->idx]->type !== Token::TYPE_WHITESPACE)
+ && ($this->tokens[$this->idx]->type !== Token::TYPE_COMMENT)
+ ) {
+ return $this->tokens[$this->idx++];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the next token.
+ *
+ * @param int $type The type.
+ *
+ * @return Token
+ */
+ public function getNextOfType($type)
+ {
+ for (; $this->idx < $this->count; ++$this->idx) {
+ if ($this->tokens[$this->idx]->type === $type) {
+ return $this->tokens[$this->idx++];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the next token.
+ *
+ * @param int $type The type of the token.
+ * @param string $value The value of the token.
+ *
+ * @return Token
+ */
+ public function getNextOfTypeAndValue($type, $value)
+ {
+ for (; $this->idx < $this->count; ++$this->idx) {
+ if (($this->tokens[$this->idx]->type === $type)
+ && ($this->tokens[$this->idx]->value === $value)
+ ) {
+ return $this->tokens[$this->idx++];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Sets an value inside the container.
+ *
+ * @param int $offset The offset to be set.
+ * @param Token $value The token to be saved.
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ if ($offset === null) {
+ $this->tokens[$this->count++] = $value;
+ } else {
+ $this->tokens[$offset] = $value;
+ }
+ }
+
+ /**
+ * Gets a value from the container.
+ *
+ * @param int $offset The offset to be returned.
+ *
+ * @return Token
+ */
+ public function offsetGet($offset)
+ {
+ return $offset < $this->count ? $this->tokens[$offset] : null;
+ }
+
+ /**
+ * Checks if an offset was previously set.
+ *
+ * @param int $offset The offset to be checked.
+ *
+ * @return bool
+ */
+ public function offsetExists($offset)
+ {
+ return $offset < $this->count;
+ }
+
+ /**
+ * Unsets the value of an offset.
+ *
+ * @param int $offset The offset to be unset.
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->tokens[$offset]);
+ --$this->count;
+ for ($i = $offset; $i < $this->count; ++$i) {
+ $this->tokens[$i] = $this->tokens[$i + 1];
+ }
+ unset($this->tokens[$this->count]);
+ }
+}
diff --git a/libraries/sql-parser/src/UtfString.php b/libraries/sql-parser/src/UtfString.php
new file mode 100644
index 0000000000..5f4ba12f9d
--- /dev/null
+++ b/libraries/sql-parser/src/UtfString.php
@@ -0,0 +1,218 @@
+<?php
+
+/**
+ * Implementation for UTF-8 strings.
+ *
+ * The subscript operator in PHP, when used with string will return a byte
+ * and not a character. Because in UTF-8 strings a character may occupy more
+ * than one byte, the subscript operator may return an invalid character.
+ *
+ * Because the lexer relies on the subscript operator this class had to be
+ * implemented.
+ *
+ * @package SqlParser
+ */
+namespace SqlParser;
+
+/**
+ * Implements array-like access for UTF-8 strings.
+ *
+ * In this library, this class should be used to parse UTF-8 queries.
+ *
+ * @category Misc
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class UtfString implements \ArrayAccess
+{
+
+ /**
+ * The raw, multi-byte string.
+ *
+ * @var string
+ */
+ public $str = '';
+
+ /**
+ * The index of current byte.
+ *
+ * For ASCII strings, the byte index is equal to the character index.
+ *
+ * @var int
+ */
+ public $byteIdx = 0;
+
+ /**
+ * The index of current character.
+ *
+ * For non-ASCII strings, some characters occupy more than one byte and
+ * the character index will have a lower value than the byte index.
+ *
+ * @var int
+ */
+ public $charIdx = 0;
+
+ /**
+ * The length of the string (in bytes).
+ *
+ * @var int
+ */
+ public $byteLen = 0;
+
+ /**
+ * The length of the string (in characters).
+ *
+ * @var int
+ */
+ public $charLen = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param string $str The string.
+ */
+ public function __construct($str)
+ {
+ $this->str = $str;
+ $this->byteIdx = 0;
+ $this->charIdx = 0;
+ // TODO: `strlen($str)` might return a wrong length when function
+ // overloading is enabled.
+ // https://php.net/manual/ro/mbstring.overload.php
+ $this->byteLen = strlen($str);
+ $this->charLen = mb_strlen($str, 'UTF-8');
+ }
+
+ /**
+ * Checks if the given offset exists.
+ *
+ * @param int $offset The offset to be checked.
+ *
+ * @return bool
+ */
+ public function offsetExists($offset)
+ {
+ return ($offset >= 0) && ($offset < $this->charLen);
+ }
+
+ /**
+ * Gets the character at given offset.
+ *
+ * @param int $offset The offset to be returned.
+ *
+ * @return string
+ */
+ public function offsetGet($offset)
+ {
+ if (($offset < 0) || ($offset >= $this->charLen)) {
+ return null;
+ }
+
+ $delta = $offset - $this->charIdx;
+
+ if ($delta > 0) {
+ // Fast forwarding.
+ while ($delta-- > 0) {
+ $this->byteIdx += static::getCharLength($this->str[$this->byteIdx]);
+ ++$this->charIdx;
+ }
+ } elseif ($delta < 0) {
+ // Rewinding.
+ while ($delta++ < 0) {
+ do {
+ $byte = ord($this->str[--$this->byteIdx]);
+ } while ((128 <= $byte) && ($byte < 192));
+ --$this->charIdx;
+ }
+ }
+
+ $bytesCount = static::getCharLength($this->str[$this->byteIdx]);
+
+ $ret = '';
+ for ($i = 0; $bytesCount-- > 0; ++$i) {
+ $ret .= $this->str[$this->byteIdx + $i];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Sets the value of a character.
+ *
+ * @param int $offset The offset to be set.
+ * @param string $value The value to be set.
+ *
+ * @throws \Exception Not implemented.
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ throw new \Exception('Not implemented.');
+ }
+
+ /**
+ * Unsets an index.
+ *
+ * @param int $offset The value to be unset.
+ *
+ * @throws \Exception Not implemented.
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ throw new \Exception('Not implemented.');
+ }
+
+ /**
+ * Gets the length of an UTF-8 character.
+ *
+ * According to RFC 3629, a UTF-8 character can have at most 4 bytes.
+ * However, this implementation supports UTF-8 characters containing up to 6
+ * bytes.
+ *
+ * @param string $byte The byte to be analyzed.
+ *
+ * @see http://tools.ietf.org/html/rfc3629
+ *
+ * @return int
+ */
+ public static function getCharLength($byte)
+ {
+ $byte = ord($byte);
+ if ($byte < 128) {
+ return 1;
+ } elseif ($byte < 224) {
+ return 2;
+ } elseif ($byte < 240) {
+ return 3;
+ } elseif ($byte < 248) {
+ return 4;
+ } elseif ($byte < 252) {
+ return 5; // unofficial
+ }
+ return 6; // unofficial
+ }
+
+ /**
+ * Returns the length in characters of the string.
+ *
+ * @return int
+ */
+ public function length()
+ {
+ return $this->charLen;
+ }
+
+ /**
+ * Returns the contained string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->str;
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/BufferedQuery.php b/libraries/sql-parser/src/Utils/BufferedQuery.php
new file mode 100644
index 0000000000..e58165ab27
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/BufferedQuery.php
@@ -0,0 +1,399 @@
+<?php
+
+/**
+ * Buffered query utilities.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Context;
+
+/**
+ * Buffer query utilities.
+ *
+ * Implements a specialized lexer used to extract statements from large inputs
+ * that are being buffered. After each statement has been extracted, a lexer or
+ * a parser may be used.
+ *
+ * All comments are skipped, with one exception: MySQL commands inside `/*!`.
+ *
+ * @category Lexer
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class BufferedQuery
+{
+
+ // Constants that describe the current status of the parser.
+ const STATUS_STRING_SINGLE_QUOTES = 1;
+ const STATUS_STRING_DOUBLE_QUOTES = 2;
+ const STATUS_STRING_BACKTICK = 3;
+ const STATUS_COMMENT_BASH = 4;
+ const STATUS_COMMENT_C = 5;
+ const STATUS_COMMENT_SQL = 6;
+
+ /**
+ * The query that is being processed.
+ *
+ * This field can be modified just by appending to it!
+ *
+ * @var string
+ */
+ public $query = '';
+
+ /**
+ * The options of this parser.
+ *
+ * @var array
+ */
+ public $options = array();
+
+ /**
+ * The last delimiter used.
+ *
+ * @var string
+ */
+ public $delimiter;
+
+ /**
+ * The length of the delimiter.
+ *
+ * @var int
+ */
+ public $delimiterLen;
+
+ /**
+ * The current status of the parser.
+ *
+ * @var int
+ */
+ public $status;
+
+ /**
+ * The last incomplete query that was extracted.
+ *
+ * @var string
+ */
+ public $current = '';
+
+ /**
+ * Constructor.
+ *
+ * @param string $query The query to be parsed.
+ * @param array $options The options of this parser.
+ */
+ public function __construct($query = '', array $options = array())
+ {
+ // Merges specified options with defaults.
+ $this->options = array_merge(
+ array(
+
+ /**
+ * The starting delimiter.
+ *
+ * @var string
+ */
+ 'delimiter' => ';',
+
+ /**
+ * Whether `DELIMITER` statements should be parsed.
+ *
+ * @var bool
+ */
+ 'parse_delimiter' => false,
+
+ /**
+ * Whether a delimiter should be added at the end of the
+ * statement.
+ *
+ * @var bool
+ */
+ 'add_delimiter' => false,
+ ),
+ $options
+ );
+
+ $this->query = $query;
+ $this->setDelimiter($this->options['delimiter']);
+ }
+
+ /**
+ * Sets the delimiter.
+ *
+ * Used to update the length of it too.
+ *
+ * @param string $delimiter
+ */
+ public function setDelimiter($delimiter)
+ {
+ $this->delimiter = $delimiter;
+ $this->delimiterLen = strlen($delimiter);
+ }
+
+ /**
+ * Extracts a statement from the buffer.
+ *
+ * @param bool $end Whether the end of the buffer was reached.
+ *
+ * @return string
+ */
+ public function extract($end = false)
+ {
+ /**
+ * The last parsed position.
+ *
+ * This is statically defined because it is not used outside anywhere
+ * outside this method and there is probably a (minor) performance
+ * improvement to it.
+ *
+ * @var int
+ */
+ static $i = 0;
+
+ if (empty($this->query)) {
+ return false;
+ }
+
+ /**
+ * The length of the buffer.
+ *
+ * @var int $len
+ */
+ $len = strlen($this->query);
+
+ /**
+ * The last index of the string that is going to be parsed.
+ *
+ * There must be a few characters left in the buffer so the parser can
+ * avoid confusing some symbols that may have multiple meanings.
+ *
+ * For example, if the buffer ends in `-` that may be an operator or the
+ * beginning of a comment.
+ *
+ * Another example if the buffer ends in `DELIMITE`. The parser is going
+ * to require a few more characters because that may be a part of the
+ * `DELIMITER` keyword or just a column named `DELIMITE`.
+ *
+ * Those extra characters are required only if there is more data
+ * expected (the end of the buffer was not reached).
+ *
+ * @var int $loopLen
+ */
+ $loopLen = $end ? $len : $len - 16;
+
+ for (; $i < $loopLen; ++$i) {
+
+ /*
+ * Handling special parses statuses.
+ */
+ if ($this->status === static::STATUS_STRING_SINGLE_QUOTES) {
+ // Single-quoted strings like 'foo'.
+ if (($this->query[$i - 1] != '\\') && ($this->query[$i] === '\'')) {
+ $this->status = 0;
+ }
+ $this->current .= $this->query[$i];
+ continue;
+ } elseif ($this->status === static::STATUS_STRING_DOUBLE_QUOTES) {
+ // Double-quoted strings like "bar".
+ if (($this->query[$i - 1] != '\\') && ($this->query[$i] === '"')) {
+ $this->status = 0;
+ }
+ $this->current .= $this->query[$i];
+ continue;
+ } elseif ($this->status === static::STATUS_STRING_BACKTICK) {
+ if ($this->query[$i] === '`') {
+ $this->status = 0;
+ }
+ $this->current .= $this->query[$i];
+ continue;
+ } elseif (($this->status === static::STATUS_COMMENT_BASH)
+ || ($this->status === static::STATUS_COMMENT_SQL)
+ ) {
+ // Bash-like (#) or SQL-like (-- ) comments end in new line.
+ if ($this->query[$i] === "\n") {
+ $this->status = 0;
+ }
+ continue;
+ } elseif ($this->status === static::STATUS_COMMENT_C) {
+ // C-like comments end in */.
+ if (($this->query[$i - 1] === '*') && ($this->query[$i] === '/')) {
+ $this->status = 0;
+ }
+ continue;
+ }
+
+ /*
+ * Checking if a string started.
+ */
+ if ($this->query[$i] === '\'') {
+ $this->status = static::STATUS_STRING_SINGLE_QUOTES;
+ $this->current .= $this->query[$i];
+ continue;
+ } elseif ($this->query[$i] === '"') {
+ $this->status = static::STATUS_STRING_DOUBLE_QUOTES;
+ $this->current .= $this->query[$i];
+ continue;
+ } elseif ($this->query[$i] === '`') {
+ $this->status = static::STATUS_STRING_BACKTICK;
+ $this->current .= $this->query[$i];
+ continue;
+ }
+
+ /*
+ * Checking if a comment started.
+ */
+ if ($this->query[$i] === '#') {
+ $this->status = static::STATUS_COMMENT_BASH;
+ continue;
+ } elseif (($i + 2 < $len)
+ && ($this->query[$i] === '-')
+ && ($this->query[$i + 1] === '-')
+ && (Context::isWhitespace($this->query[$i + 2]))
+ ) {
+ $this->status = static::STATUS_COMMENT_SQL;
+ continue;
+ } elseif (($i + 2 < $len)
+ && ($this->query[$i] === '/')
+ && ($this->query[$i + 1] === '*')
+ && ($this->query[$i + 2] !== '!')
+ ) {
+ $this->status = static::STATUS_COMMENT_C;
+ continue;
+ }
+
+ /*
+ * Handling `DELIMITER` statement.
+ *
+ * The code below basically checks for
+ * `strtoupper(substr($this->query, $i, 9)) === 'DELIMITER'`
+ *
+ * This optimization makes the code about 3 times faster.
+ */
+ if (($i + 9 < $len)
+ && (($this->query[$i ] === 'D') || ($this->query[$i ] === 'd'))
+ && (($this->query[$i + 1] === 'E') || ($this->query[$i + 1] === 'e'))
+ && (($this->query[$i + 2] === 'L') || ($this->query[$i + 2] === 'l'))
+ && (($this->query[$i + 3] === 'I') || ($this->query[$i + 3] === 'i'))
+ && (($this->query[$i + 4] === 'M') || ($this->query[$i + 4] === 'm'))
+ && (($this->query[$i + 5] === 'I') || ($this->query[$i + 5] === 'i'))
+ && (($this->query[$i + 6] === 'T') || ($this->query[$i + 6] === 't'))
+ && (($this->query[$i + 7] === 'E') || ($this->query[$i + 7] === 'e'))
+ && (($this->query[$i + 8] === 'R') || ($this->query[$i + 8] === 'r'))
+ && (Context::isWhitespace($this->query[$i + 9]))
+ ) {
+
+ // Saving the current index to be able to revert any parsing
+ // done in this block.
+ $iBak = $i;
+ $i += 9; // Skipping `DELIMITER`.
+
+ // Skipping whitespaces.
+ while (($i < $len) && (Context::isWhitespace($this->query[$i]))) {
+ ++$i;
+ }
+
+ // Parsing the delimiter.
+ $delimiter = '';
+ while (($i < $len) && (!Context::isWhitespace($this->query[$i]))) {
+ $delimiter .= $this->query[$i++];
+ }
+
+ // Checking if the delimiter definition ended.
+ if (($delimiter != '')
+ && ((($i < $len) && (Context::isWhitespace($this->query[$i])))
+ || (($i === $len) && ($end)))
+ ) {
+
+ // Saving the delimiter.
+ $this->setDelimiter($delimiter);
+
+ // Whether this statement should be returned or not.
+ $ret = '';
+ if (!empty($this->options['parse_delimiter'])) {
+
+ // Appending the `DELIMITER` statement that was just
+ // found to the current statement.
+ $ret = trim(
+ $this->current . ' ' . substr($this->query, $iBak, $i - $iBak)
+ );
+ }
+
+ // Removing the statement that was just extracted from the
+ // query.
+ $this->query = substr($this->query, $i);
+ $i = 0;
+
+ // Resetting the current statement.
+ $this->current = '';
+
+ return $ret;
+ }
+
+ // Incomplete statement. Reverting
+ $i = $iBak;
+ return false;
+ }
+
+ /*
+ * Checking if the current statement finished.
+ *
+ * The first letter of the delimiter is being checked as an
+ * optimization. This code is almost as fast as the one above.
+ *
+ * There is no point in checking if two strings match if not even
+ * the first letter matches.
+ */
+ if (($this->query[$i] === $this->delimiter[0])
+ && (($this->delimiterLen === 1)
+ || (substr($this->query, $i, $this->delimiterLen) === $this->delimiter))
+ ) {
+
+ // Saving the statement that just ended.
+ $ret = $this->current;
+
+ // If needed, adds a delimiter at the end of the statement.
+ if (!empty($this->options['add_delimiter'])) {
+ $ret .= $this->delimiter;
+ }
+
+ // Removing the statement that was just extracted from the
+ // query.
+ $this->query = substr($this->query, $i + $this->delimiterLen);
+ $i = 0;
+
+ // Resetting the current statement.
+ $this->current = '';
+
+ // Returning the statement.
+ return trim($ret);
+ }
+
+ /*
+ * Appending current character to current statement.
+ */
+ $this->current .= $this->query[$i];
+ }
+
+ if (($end) && ($i === $len)) {
+ // If the end of the buffer was reached, the buffer is emptied and
+ // the current statement that was extracted is returned.
+ $ret = $this->current;
+
+ // Emptying the buffer.
+ $this->query = '';
+ $i = 0;
+
+ // Resetting the current statement.
+ $this->current = '';
+
+ // Returning the statement.
+ return trim($ret);
+ }
+
+ return '';
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/Error.php b/libraries/sql-parser/src/Utils/Error.php
new file mode 100644
index 0000000000..df6d5133ce
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/Error.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * Error related utilities.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Lexer;
+use SqlParser\Parser;
+
+/**
+ * Error related utilities.
+ *
+ * @category Exceptions
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Error
+{
+
+ /**
+ * Gets the errors of a lexer and a parser.
+ *
+ * @param array $objs Objects from where the errors will be extracted.
+ *
+ * @return array Each element of the array represents an error.
+ * `$err[0]` holds the error message.
+ * `$err[1]` holds the error code.
+ * `$err[2]` holds the string that caused the issue.
+ * `$err[3]` holds the position of the string.
+ * (i.e. `array($msg, $code, $str, $pos)`)
+ */
+ public static function get($objs)
+ {
+ $ret = array();
+
+ foreach ($objs as $obj) {
+ if ($obj instanceof Lexer) {
+ foreach ($obj->errors as $err) {
+ $ret[] = array(
+ $err->getMessage(),
+ $err->getCode(),
+ $err->ch,
+ $err->pos
+ );
+ }
+ } elseif ($obj instanceof Parser) {
+ foreach ($obj->errors as $err) {
+ $ret[] = array(
+ $err->getMessage(),
+ $err->getCode(),
+ $err->token->token,
+ $err->token->position
+ );
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Formats the specified errors
+ *
+ * @param array $errors The errors to be formatted.
+ * @param string $format The format of an error.
+ * '$1$d' is replaced by the position of this error.
+ * '$2$s' is replaced by the error message.
+ * '$3$d' is replaced by the error code.
+ * '$4$s' is replaced by the string that caused the
+ * issue.
+ * '$5$d' is replaced by the position of the string.
+ * @return array
+ */
+ public static function format(
+ $errors, $format = '#%1$d: %2$s (near "%4$s" at position %5$d)'
+ ) {
+ $ret = array();
+
+ $i = 0;
+ foreach ($errors as $key => $err) {
+ $ret[$key] = sprintf(
+ $format, ++$i, $err[0], $err[1], $err[2], $err[3]
+ );
+ }
+
+ return $ret;
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/Formatter.php b/libraries/sql-parser/src/Utils/Formatter.php
new file mode 100644
index 0000000000..ebdea42ece
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/Formatter.php
@@ -0,0 +1,536 @@
+<?php
+
+/**
+ * Utilities that are used for formatting queries.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Lexer;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
+
+/**
+ * Utilities that are used for formatting queries.
+ *
+ * @category Misc
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Formatter
+{
+
+ /**
+ * The formatting options.
+ *
+ * @var array
+ */
+ public $options;
+
+ /**
+ * Clauses that must be inlined.
+ *
+ * These clauses usually are short and it's nicer to have them inline.
+ *
+ * @var array
+ */
+ public static $INLINE_CLAUSES = array(
+ 'CREATE' => true,
+ 'LIMIT' => true,
+ 'PARTITION BY' => true,
+ 'PARTITION' => true,
+ 'PROCEDURE' => true,
+ 'SUBPARTITION BY' => true,
+ 'VALUES' => true,
+ );
+
+ /**
+ * Constructor.
+ *
+ * @param array $options The formatting options.
+ */
+ public function __construct(array $options = array())
+ {
+ // The specified formatting options are merged with the default values.
+ $this->options = array_merge(
+ array(
+
+ /**
+ * The format of the result.
+ *
+ * @var string The type ('text', 'cli' or 'html')
+ */
+ 'type' => php_sapi_name() == 'cli' ? 'cli' : 'text',
+
+ /**
+ * The line ending used.
+ * By default, for text this is "\n" and for HTML this is "<br/>".
+ *
+ * @var string
+ */
+ 'line_ending' => $this->options['type'] == 'html' ? '<br/>' : "\n",
+
+ /**
+ * The string used for indentation.
+ *
+ * @var string
+ */
+ 'indentation' => " ",
+
+ /**
+ * Whether comments should be removed or not.
+ *
+ * @var bool
+ */
+ 'remove_comments' => false,
+
+ /**
+ * Whether each clause should be on a new line.
+ *
+ * @var bool
+ */
+ 'clause_newline' => true,
+
+ /**
+ * Whether each part should be on a new line.
+ * Parts are delimited by brackets and commas.
+ *
+ * @var bool
+ */
+ 'parts_newline' => true,
+
+ /**
+ * Whether each part of each clause should be indented.
+ *
+ * @var bool
+ */
+ 'indent_parts' => true,
+
+ /**
+ * The styles used for HTML formatting.
+ * array($type, $flags, $span, $callback)
+ *
+ * @var array[]
+ */
+ 'formats' => array(
+ array(
+ 'type' => Token::TYPE_KEYWORD,
+ 'flags' => Token::FLAG_KEYWORD_RESERVED,
+ 'html' => 'class="sql-reserved"',
+ 'cli' => "\e[35m",
+ 'function' => 'strtoupper',
+ ),
+ array(
+ 'type' => Token::TYPE_KEYWORD,
+ 'flags' => 0,
+ 'html' => 'class="sql-keyword"',
+ 'cli' => "\e[95m",
+ 'function' => 'strtoupper',
+ ),
+ array(
+ 'type' => Token::TYPE_COMMENT,
+ 'flags' => 0,
+ 'html' => 'class="sql-comment"',
+ 'cli' => "\e[37m",
+ 'function' => '',
+ ),
+ array(
+ 'type' => Token::TYPE_BOOL,
+ 'flags' => 0,
+ 'html' => 'class="sql-atom"',
+ 'cli' => "\e[36m",
+ 'function' => 'strtoupper',
+ ),
+ array(
+ 'type' => Token::TYPE_NUMBER,
+ 'flags' => 0,
+ 'html' => 'class="sql-number"',
+ 'cli' => "\e[92m",
+ 'function' => 'strtolower',
+ ),
+ array(
+ 'type' => Token::TYPE_STRING,
+ 'flags' => 0,
+ 'html' => 'class="sql-string"',
+ 'cli' => "\e[91m",
+ 'function' => '',
+ ),
+ array(
+ 'type' => Token::TYPE_SYMBOL,
+ 'flags' => 0,
+ 'html' => 'class="sql-variable"',
+ 'cli' => "\e[36m",
+ 'function' => '',
+ ),
+ )
+ ),
+ $options
+ );
+
+ // `parts_newline` requires `clause_newline`
+ $this->options['parts_newline'] &= $this->options['clause_newline'];
+ }
+
+ /**
+ * Formats the given list of tokens.
+ *
+ * @param TokensList $list The list of tokens.
+ *
+ * @return string
+ */
+ public function formatList($list)
+ {
+
+ /**
+ * The query to be returned.
+ *
+ * @var string $ret
+ */
+ $ret = '';
+
+ /**
+ * The indentation level.
+ *
+ * @var int $indent
+ */
+ $indent = 0;
+
+ /**
+ * Whether the line ended.
+ *
+ * @var bool $lineEnded
+ */
+ $lineEnded = false;
+
+ /**
+ * The name of the last clause.
+ *
+ * @var string $lastClause
+ */
+ $lastClause = '';
+
+ /**
+ * A stack that keeps track of the indentation level every time a new
+ * block is found.
+ *
+ * @var array $blocksIndentation
+ */
+ $blocksIndentation = array();
+
+ /**
+ * A stack that keeps track of the line endings every time a new block
+ * is found.
+ *
+ * @var array $blocksLineEndings
+ */
+ $blocksLineEndings = array();
+
+ /**
+ * Whether clause's options were formatted.
+ *
+ * @var bool $formattedOptions
+ */
+ $formattedOptions = false;
+
+ /**
+ * Previously parsed token.
+ *
+ * @var Token $prev
+ */
+ $prev = null;
+
+ /**
+ * Comments are being formatted separately to maintain the whitespaces
+ * before and after them.
+ *
+ * @var string $comment
+ */
+ $comment = '';
+
+ // In order to be able to format the queries correctly, the next token
+ // must be taken into consideration. The loop below uses two pointers,
+ // `$prev` and `$curr` which store two consecutive tokens.
+ // Actually, at every iteration the previous token is being used.
+ for ($list->idx = 0; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $curr
+ */
+ $curr = $list->tokens[$list->idx];
+
+ if ($curr->type === Token::TYPE_WHITESPACE) {
+
+ // Whitespaces are skipped because the formatter adds its own.
+ continue;
+ } elseif ($curr->type === Token::TYPE_COMMENT) {
+
+ // Whether the comments should be parsed.
+ if (!empty($this->options['remove_comments'])) {
+ continue;
+ }
+
+ if ($list->tokens[$list->idx - 1]->type === Token::TYPE_WHITESPACE) {
+ // The whitespaces before and after are preserved for
+ // formatting reasons.
+ $comment .= $list->tokens[$list->idx - 1]->token;
+ }
+ $comment .= $this->toString($curr);
+ if (($list->tokens[$list->idx + 1]->type === Token::TYPE_WHITESPACE)
+ && ($list->tokens[$list->idx + 2]->type !== Token::TYPE_COMMENT)
+ ) {
+ // Adding the next whitespace only there is no comment that
+ // follows it immediately which may cause adding a
+ // whitespace twice.
+ $comment .= $list->tokens[$list->idx + 1]->token;
+ }
+
+ // Everything was handled here, no need to continue.
+ continue;
+ }
+
+ // Checking if pointers were initialized.
+ if ($prev !== null) {
+
+ // Checking if a new clause started.
+ if (static::isClause($prev) !== false) {
+ $lastClause = $prev->value;
+ $formattedOptions = false;
+ }
+
+ // The options of a clause should stay on the same line and everything that follows.
+ if (($this->options['parts_newline'])
+ && (!$formattedOptions)
+ && (empty(self::$INLINE_CLAUSES[$lastClause]))
+ && ($curr->type != Token::TYPE_KEYWORD)
+ ) {
+ $formattedOptions = true;
+ $lineEnded = true;
+ ++$indent;
+ }
+
+ // Checking if this clause ended.
+ if ($tmp = static::isClause($curr)) {
+ if (($tmp == 2) || ($this->options['clause_newline'])) {
+ $lineEnded = true;
+ if ($this->options['parts_newline']) {
+ --$indent;
+ }
+ }
+ }
+
+ // Indenting BEGIN ... END blocks.
+ if (($prev->type === Token::TYPE_KEYWORD) && ($prev->value === 'BEGIN')) {
+ $lineEnded = true;
+ array_push($blocksIndentation, $indent);
+ ++$indent;
+ } elseif (($curr->type === Token::TYPE_KEYWORD) && ($curr->value === 'END')) {
+ $lineEnded = true;
+ $indent = array_pop($blocksIndentation);
+ }
+
+ // Formatting fragments delimited by comma.
+ if (($prev->type === Token::TYPE_OPERATOR) && ($prev->value === ',')) {
+ // Fragments delimited by a comma are broken into multiple
+ // pieces only if the clause if the clause is not inlined or
+ // this fragment is between brackets that were on new line.
+ if (((empty(self::$INLINE_CLAUSES[$lastClause]))
+ && ($this->options['parts_newline']))
+ || (end($blocksLineEndings) === true)
+ ) {
+ $lineEnded = true;
+ }
+ }
+
+ // Handling brackets.
+ // Brackets are indented only if the length of the fragment between
+ // them is longer than 30 characters.
+ if (($prev->type === Token::TYPE_OPERATOR) && ($prev->value === '(')) {
+ array_push($blocksIndentation, $indent);
+ if (static::getGroupLength($list) > 30) {
+ ++$indent;
+ $lineEnded = true;
+ }
+ array_push($blocksLineEndings, $lineEnded);
+ } elseif (($curr->type === Token::TYPE_OPERATOR) && ($curr->value === ')')) {
+ $indent = array_pop($blocksIndentation);
+ $lineEnded |= array_pop($blocksLineEndings);
+ }
+
+ // Delimiter must be placed on the same line with the last
+ // clause.
+ if ($curr->type === Token::TYPE_DELIMITER) {
+ $lineEnded = false;
+ }
+
+ // Adding the token.
+ $ret .= $this->toString($prev);
+
+ // Finishing the line.
+ if ($lineEnded) {
+ if ($indent < 0) {
+ // TODO: Make sure this never occurs and delete it.
+ $indent = 0;
+ }
+
+ if ($curr->type !== Token::TYPE_COMMENT) {
+ $ret .= $this->options['line_ending']
+ . str_repeat($this->options['indentation'], $indent);
+ }
+ $lineEnded = false;
+ } else {
+ // If the line ended there is no point in adding whitespaces.
+ // Also, some tokens do not have spaces before or after them.
+ if (!((($prev->type === Token::TYPE_OPERATOR) && (($prev->value === '.') || ($prev->value === '(')))
+ // No space after . (
+ || (($curr->type === Token::TYPE_OPERATOR) && (($curr->value === '.') || ($curr->value === ',') || ($curr->value === '(') || ($curr->value === ')')))
+ // No space before . , ( )
+ || (($curr->type === Token::TYPE_DELIMITER)) && (mb_strlen($curr->value, 'UTF-8') < 2))
+ // A space after delimiters that are longer than 2 characters.
+ || ($prev->value === 'DELIMITER')
+ ) {
+ $ret .= ' ';
+ }
+ }
+ }
+
+ if (!empty($comment)) {
+ $ret .= $comment;
+ $comment = '';
+ }
+
+ // Saving the next token as the one that will be processed during
+ // the next iteration.
+ $prev = $curr;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Tries to print the query and returns the result.
+ *
+ * @param Token $token The token to be printed.
+ *
+ * @return string
+ */
+ public function toString($token)
+ {
+ $text = $token->token;
+
+ foreach ($this->options['formats'] as $format) {
+ if (($token->type === $format['type'])
+ && (($token->flags & $format['flags']) === $format['flags'])
+ ) {
+
+ // Running transformation function.
+ if (!empty($format['function'])) {
+ $func = $format['function'];
+ $text = $func($text);
+ }
+
+ // Formatting HTML.
+ if ($this->options['type'] === 'html') {
+ return '<span ' . $format['html'] . '>' . $text . '</span>';
+ } elseif ($this->options['type'] === 'cli') {
+ return $format['cli'] . $text;
+ }
+
+ break;
+ }
+ }
+
+ if ($this->options['type'] === 'cli') {
+ return "\e[39m" . $text;
+ }
+ return $text;
+ }
+
+ /**
+ * Formats a query.
+ *
+ * @param string $query The query to be formatted
+ * @param array $options The formatting options.
+ *
+ * @return string The formatted string.
+ */
+ public static function format($query, array $options = array())
+ {
+ $lexer = new Lexer($query);
+ $formatter = new Formatter($options);
+ return $formatter->formatList($lexer->list);
+ }
+
+ /**
+ * Computes the length of a group.
+ *
+ * A group is delimited by a pair of brackets.
+ *
+ * @param TokensList $list The list of tokens.
+ *
+ * @return int
+ */
+ public static function getGroupLength($list)
+ {
+ /**
+ * The number of opening brackets found.
+ * This counter starts at one because by the time this function called,
+ * the list already advanced one position and the opening bracket was
+ * already parsed.
+ *
+ * @var int $count
+ */
+ $count = 1;
+
+ /**
+ * The length of this group.
+ *
+ * @var int $length
+ */
+ $length = 0;
+
+ for ($idx = $list->idx; $idx < $list->count; ++$idx) {
+ // Counting the brackets.
+ if ($list->tokens[$idx]->type === Token::TYPE_OPERATOR) {
+ if ($list->tokens[$idx]->value === '(') {
+ ++$count;
+ } elseif ($list->tokens[$idx]->value === ')') {
+ --$count;
+ if ($count == 0) {
+ break;
+ }
+ }
+ }
+
+ // Keeping track of this group's length.
+ $length += mb_strlen($list->tokens[$idx]->value, 'UTF-8');
+ }
+
+ return $length;
+ }
+
+ /**
+ * Checks if a token is a statement or a clause inside a statement.
+ *
+ * @param Token $token The token to be checked.
+ *
+ * @return int|bool
+ */
+ public static function isClause($token)
+ {
+ if ((($token->type === Token::TYPE_NONE) && (strtoupper($token->token) === 'DELIMITER'))
+ || (($token->type === Token::TYPE_KEYWORD) && (isset(Parser::$STATEMENT_PARSERS[$token->value])))
+ ) {
+ return 2;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && (isset(Parser::$KEYWORD_PARSERS[$token->value]))) {
+ return 1;
+ }
+ return false;
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php
new file mode 100644
index 0000000000..cec5653688
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/Misc.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * Miscellaneous utilities.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Components\Expression;
+use SqlParser\Statements\SelectStatement;
+
+/**
+ * Miscellaneous utilities.
+ *
+ * @category Misc
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Misc
+{
+
+ /**
+ * Gets a list of all aliases and their original names.
+ *
+ * @param SelectStatement $statement The statement to be processed.
+ * @param string $database The name of the database.
+ *
+ * @return array
+ */
+ public static function getAliases($statement, $database)
+ {
+ if (!($statement instanceof SelectStatement)
+ || (empty($statement->expr))
+ || (empty($statement->from))
+ ) {
+ return array();
+ }
+
+ $retval = array();
+
+ $tables = array();
+
+ /**
+ * Expressions that may contain aliases.
+ * These are extracted from `FROM` and `JOIN` keywords.
+ *
+ * @var Expression[] $expressions
+ */
+ $expressions = $statement->from;
+
+ // Adding expressions from JOIN.
+ if (!empty($statement->join)) {
+ foreach ($statement->join as $join) {
+ $expressions[] = $join->expr;
+ }
+ }
+
+ foreach ($expressions as $expr) {
+ if ((!isset($expr->table)) || ($expr->table === '')) {
+ continue;
+ }
+
+ $thisDb = ((isset($expr->database)) && ($expr->database !== '')) ?
+ $expr->database : $database;
+
+ if (!isset($retval[$thisDb])) {
+ $retval[$thisDb] = array(
+ 'alias' => null,
+ 'tables' => array(),
+ );
+ }
+
+ if (!isset($retval[$thisDb]['tables'][$expr->table])) {
+ $retval[$thisDb]['tables'][$expr->table] = array(
+ 'alias' => ((isset($expr->alias)) && ($expr->alias !== '')) ?
+ $expr->alias : null,
+ 'columns' => array(),
+ );
+ }
+
+ if (!isset($tables[$thisDb])) {
+ $tables[$thisDb] = array();
+ }
+ $tables[$thisDb][$expr->alias] = $expr->table;
+ }
+
+ foreach ($statement->expr as $expr) {
+ if ((!isset($expr->column)) || ($expr->column === '')
+ || (!isset($expr->alias)) || ($expr->alias === '')
+ ) {
+ continue;
+ }
+
+ $thisDb = ((isset($expr->database)) && ($expr->database !== '')) ?
+ $expr->database : $database;
+
+ if ((isset($expr->table)) && ($expr->table !== '')) {
+ $thisTable = isset($tables[$thisDb][$expr->table]) ?
+ $tables[$thisDb][$expr->table] : $expr->table;
+ $retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias;
+ } else {
+ foreach ($retval[$thisDb]['tables'] as &$table) {
+ $table['columns'][$expr->column] = $expr->alias;
+ }
+ }
+ }
+
+ return $retval;
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php
new file mode 100644
index 0000000000..4325b6563b
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/Query.php
@@ -0,0 +1,788 @@
+<?php
+
+/**
+ * Statement utilities.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Lexer;
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+use SqlParser\Components\Expression;
+use SqlParser\Statements\AlterStatement;
+use SqlParser\Statements\AnalyzeStatement;
+use SqlParser\Statements\CallStatement;
+use SqlParser\Statements\CheckStatement;
+use SqlParser\Statements\ChecksumStatement;
+use SqlParser\Statements\CreateStatement;
+use SqlParser\Statements\DeleteStatement;
+use SqlParser\Statements\DropStatement;
+use SqlParser\Statements\ExplainStatement;
+use SqlParser\Statements\InsertStatement;
+use SqlParser\Statements\OptimizeStatement;
+use SqlParser\Statements\RenameStatement;
+use SqlParser\Statements\RepairStatement;
+use SqlParser\Statements\ReplaceStatement;
+use SqlParser\Statements\SelectStatement;
+use SqlParser\Statements\ShowStatement;
+use SqlParser\Statements\TruncateStatement;
+use SqlParser\Statements\UpdateStatement;
+
+/**
+ * Statement utilities.
+ *
+ * @category Statement
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Query
+{
+
+ /**
+ * Functions that set the flag `is_func`.
+ *
+ * @var array
+ */
+ public static $FUNCTIONS = array(
+ 'SUM', 'AVG', 'STD', 'STDDEV', 'MIN', 'MAX', 'BIT_OR', 'BIT_AND'
+ );
+
+ /**
+ * Gets an array with flags this statement has.
+ *
+ * @param Statement $statement The statement to be processed.
+ * @param bool $all If `false`, false values will not be included.
+ *
+ * @return array
+ */
+ public static function getFlags($statement, $all = false)
+ {
+ $flags = array();
+ if ($all) {
+ $flags = array(
+
+ /**
+ * select ... DISTINCT ...
+ */
+ 'distinct' => false,
+
+ /**
+ * drop ... DATABASE ...
+ */
+ 'drop_database' => false,
+
+ /**
+ * ... GROUP BY ...
+ */
+ 'group' => false,
+
+ /**
+ * ... HAVING ...
+ */
+ 'having' => false,
+
+ /**
+ * INSERT ...
+ * or
+ * REPLACE ...
+ * or
+ * DELETE ...
+ */
+ 'is_affected' => false,
+
+ /**
+ * select ... PROCEDURE ANALYSE( ... ) ...
+ */
+ 'is_analyse' => false,
+
+ /**
+ * select COUNT( ... ) ...
+ */
+ 'is_count' => false,
+
+ /**
+ * DELETE ...
+ */
+ 'is_delete' => false, // @deprecated; use `querytype`
+
+ /**
+ * EXPLAIN ...
+ */
+ 'is_explain' => false, // @deprecated; use `querytype`
+
+ /**
+ * select ... INTO OUTFILE ...
+ */
+ 'is_export' => false,
+
+ /**
+ * select FUNC( ... ) ...
+ */
+ 'is_func' => false,
+
+ /**
+ * select ... GROUP BY ...
+ * or
+ * select ... HAVING ...
+ */
+ 'is_group' => false,
+
+ /**
+ * INSERT ...
+ * or
+ * REPLACE ...
+ * or
+ * TODO: LOAD DATA ...
+ */
+ 'is_insert' => false,
+
+ /**
+ * ANALYZE ...
+ * or
+ * CHECK ...
+ * or
+ * CHECKSUM ...
+ * or
+ * OPTIMIZE ...
+ * or
+ * REPAIR ...
+ */
+ 'is_maint' => false,
+
+ /**
+ * CALL ...
+ */
+ 'is_procedure' => false,
+
+ /**
+ * REPLACE ...
+ */
+ 'is_replace' => false, // @deprecated; use `querytype`
+
+ /**
+ * SELECT ...
+ */
+ 'is_select' => false, // @deprecated; use `querytype`
+
+ /**
+ * SHOW ...
+ */
+ 'is_show' => false, // @deprecated; use `querytype`
+
+ /**
+ * Contains a subquery.
+ */
+ 'is_subquery' => false,
+
+ /**
+ * ... JOIN ...
+ */
+ 'join' => false,
+
+ /**
+ * ... LIMIT ...
+ */
+ 'limit' => false,
+
+ /**
+ * TODO
+ */
+ 'offset' => false,
+
+ /**
+ * ... ORDER ...
+ */
+ 'order' => false,
+
+ /**
+ * The type of the query (which is usually the first keyword of
+ * the statement).
+ */
+ 'querytype' => false,
+
+ /**
+ * Whether a page reload is required.
+ */
+ 'reload' => false,
+
+ /**
+ * SELECT ... FROM ...
+ */
+ 'select_from' => false,
+
+ /**
+ * ... UNION ...
+ */
+ 'union' => false
+ );
+ }
+
+ if ($statement instanceof AlterStatement) {
+ $flags['querytype'] = 'ALTER';
+ $flags['reload'] = true;
+ } elseif ($statement instanceof CreateStatement) {
+ $flags['querytype'] = 'CREATE';
+ $flags['reload'] = true;
+ } elseif ($statement instanceof AnalyzeStatement) {
+ $flags['querytype'] = 'ANALYZE';
+ $flags['is_maint'] = true;
+ } elseif ($statement instanceof CheckStatement) {
+ $flags['querytype'] = 'CHECK';
+ $flags['is_maint'] = true;
+ } elseif ($statement instanceof ChecksumStatement) {
+ $flags['querytype'] = 'CHECKSUM';
+ $flags['is_maint'] = true;
+ } elseif ($statement instanceof OptimizeStatement) {
+ $flags['querytype'] = 'OPTIMIZE';
+ $flags['is_maint'] = true;
+ } elseif ($statement instanceof RepairStatement) {
+ $flags['querytype'] = 'REPAIR';
+ $flags['is_maint'] = true;
+ } elseif ($statement instanceof CallStatement) {
+ $flags['querytype'] = 'CALL';
+ $flags['is_procedure'] = true;
+ } elseif ($statement instanceof DeleteStatement) {
+ $flags['querytype'] = 'DELETE';
+ $flags['is_delete'] = true;
+ $flags['is_affected'] = true;
+ } elseif ($statement instanceof DropStatement) {
+ $flags['querytype'] = 'DROP';
+ $flags['reload'] = true;
+
+ if (($statement->options->has('DATABASE')
+ || ($statement->options->has('SCHEMA')))
+ ) {
+ $flags['drop_database'] = true;
+ }
+ } elseif ($statement instanceof ExplainStatement) {
+ $flags['querytype'] = 'EXPLAIN';
+ $flags['is_explain'] = true;
+ } elseif ($statement instanceof InsertStatement) {
+ $flags['querytype'] = 'INSERT';
+ $flags['is_affected'] = true;
+ $flags['is_insert'] = true;
+ } elseif ($statement instanceof ReplaceStatement) {
+ $flags['querytype'] = 'REPLACE';
+ $flags['is_affected'] = true;
+ $flags['is_replace'] = true;
+ $flags['is_insert'] = true;
+ } elseif ($statement instanceof SelectStatement) {
+ $flags['querytype'] = 'SELECT';
+ $flags['is_select'] = true;
+
+ if (!empty($statement->from)) {
+ $flags['select_from'] = true;
+ }
+
+ if ($statement->options->has('DISTINCT')) {
+ $flags['distinct'] = true;
+ }
+
+ if ((!empty($statement->group)) || (!empty($statement->having))) {
+ $flags['is_group'] = true;
+ }
+
+ if ((!empty($statement->into))
+ && ($statement->into->type === 'OUTFILE')
+ ) {
+ $flags['is_export'] = true;
+ }
+
+ foreach ($statement->expr as $expr) {
+ if (!empty($expr->function)) {
+ if ($expr->function === 'COUNT') {
+ $flags['is_count'] = true;
+ } elseif (in_array($expr->function, static::$FUNCTIONS)) {
+ $flags['is_func'] = true;
+ }
+ }
+ if (!empty($expr->subquery)) {
+ $flags['is_subquery'] = true;
+ }
+ }
+
+ if ((!empty($statement->procedure))
+ && ($statement->procedure->name === 'ANALYSE')
+ ) {
+ $flags['is_analyse'] = true;
+ }
+
+ if (!empty($statement->group)) {
+ $flags['group'] = true;
+ }
+
+ if (!empty($statement->having)) {
+ $flags['having'] = true;
+ }
+
+ if (!empty($statement->union)) {
+ $flags['union'] = true;
+ }
+
+ if (!empty($statement->join)) {
+ $flags['join'] = true;
+ }
+
+ } elseif ($statement instanceof ShowStatement) {
+ $flags['querytype'] = 'SHOW';
+ $flags['is_show'] = true;
+ } elseif ($statement instanceof UpdateStatement) {
+ $flags['querytype'] = 'UPDATE';
+ $flags['is_affected'] = true;
+ }
+
+ if (($statement instanceof SelectStatement)
+ || ($statement instanceof UpdateStatement)
+ || ($statement instanceof DeleteStatement)
+ ) {
+ if (!empty($statement->limit)) {
+ $flags['limit'] = true;
+ }
+ if (!empty($statement->order)) {
+ $flags['order'] = true;
+ }
+ }
+
+ return $flags;
+ }
+
+ /**
+ * Parses a query and gets all information about it.
+ *
+ * @param string $query The query to be parsed.
+ *
+ * @return array The array returned is the one returned by
+ * `static::getFlags()`, with the following keys added:
+ * - parser - the parser used to analyze the query;
+ * - statement - the first statement resulted from parsing;
+ * - select_tables - the real name of the tables selected;
+ * if there are no table names in the `SELECT`
+ * expressions, the table names are fetched from the
+ * `FROM` expressions
+ * - select_expr - selected expressions
+ */
+ public static function getAll($query)
+ {
+ $parser = new Parser($query);
+
+ if (empty($parser->statements[0])) {
+ return array();
+ }
+
+ $statement = $parser->statements[0];
+
+ $ret = static::getFlags($statement, true);
+
+ $ret['parser'] = $parser;
+ $ret['statement'] = $statement;
+
+ if ($statement instanceof SelectStatement) {
+ $ret['select_tables'] = array();
+ $ret['select_expr'] = array();
+
+ // Finding tables' aliases and their associated real names.
+ $tableAliases = array();
+ foreach ($statement->from as $expr) {
+ if ((isset($expr->table)) && ($expr->table !== '')
+ && (isset($expr->alias)) && ($expr->alias !== '')
+ ) {
+ $tableAliases[$expr->alias] = array(
+ $expr->table,
+ isset($expr->database) ? $expr->database : null
+ );
+ }
+ }
+
+ // Trying to find selected tables only from the select expression.
+ // Sometimes, this is not possible because the tables aren't defined
+ // explicitly (e.g. SELECT * FROM film, SELECT film_id FROM film).
+ foreach ($statement->expr as $expr) {
+ if ((isset($expr->table)) && ($expr->table !== '')) {
+ if (isset($tableAliases[$expr->table])) {
+ $arr = $tableAliases[$expr->table];
+ } else {
+ $arr = array(
+ $expr->table,
+ ((isset($expr->database)) && ($expr->database !== '')) ?
+ $expr->database : null
+ );
+ }
+ if (!in_array($arr, $ret['select_tables'])) {
+ $ret['select_tables'][] = $arr;
+ }
+ } else {
+ $ret['select_expr'][] = $expr->expr;
+ }
+ }
+
+ // If no tables names were found in the SELECT clause or if there
+ // are expressions like * or COUNT(*), etc. tables names should be
+ // extracted from the FROM clause.
+ if (empty($ret['select_tables'])) {
+ foreach ($statement->from as $expr) {
+ if ((isset($expr->table)) && ($expr->table !== '')) {
+ $arr = array(
+ $expr->table,
+ ((isset($expr->database)) && ($expr->database !== '')) ?
+ $expr->database : null
+ );
+ if (!in_array($arr, $ret['select_tables'])) {
+ $ret['select_tables'][] = $arr;
+ }
+ }
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Gets a list of all tables used in this statement.
+ *
+ * @param Statement $statement Statement to be scanned.
+ *
+ * @return array
+ */
+ public static function getTables($statement)
+ {
+ $expressions = array();
+
+ if (($statement instanceof InsertStatement)
+ || ($statement instanceof ReplaceStatement)
+ ) {
+ $expressions = array($statement->into->dest);
+ } elseif ($statement instanceof UpdateStatement) {
+ $expressions = $statement->tables;
+ } elseif (($statement instanceof SelectStatement)
+ || ($statement instanceof DeleteStatement)
+ ) {
+ $expressions = $statement->from;
+ } elseif (($statement instanceof AlterStatement)
+ || ($statement instanceof TruncateStatement)
+ ) {
+ $expressions = array($statement->table);
+ } elseif ($statement instanceof DropStatement) {
+ if (!$statement->options->has('TABLE')) {
+ // No tables are dropped.
+ return array();
+ }
+ $expressions = $statement->fields;
+ } elseif ($statement instanceof RenameStatement) {
+ foreach ($statement->renames as $rename) {
+ $expressions[] = $rename->old;
+ }
+ }
+
+ $ret = array();
+ foreach ($expressions as $expr) {
+ if (!empty($expr->table)) {
+ $expr->expr = null; // Force rebuild.
+ $expr->alias = null; // Aliases are not required.
+ $ret[] = Expression::build($expr);
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Gets a specific clause.
+ *
+ * @param Statement $statement The parsed query that has to be modified.
+ * @param TokensList $list The list of tokens.
+ * @param string $clause The clause to be returned.
+ * @param int|string $type The type of the search.
+ * If int,
+ * -1 for everything that was before
+ * 0 only for the clause
+ * 1 for everything after
+ * If string, the name of the first clause that
+ * should not be included.
+ * @param bool $skipFirst Whether to skip the first keyword in clause.
+ *
+ * @return string
+ */
+ public static function getClause($statement, $list, $clause, $type = 0, $skipFirst = true)
+ {
+
+ /**
+ * The index of the current clause.
+ *
+ * @var int $currIdx
+ */
+ $currIdx = 0;
+
+ /**
+ * The count of brackets.
+ * We keep track of them so we won't insert the clause in a subquery.
+ *
+ * @var int $brackets
+ */
+ $brackets = 0;
+
+ /**
+ * The string to be returned.
+ *
+ * @var string $ret
+ */
+ $ret = '';
+
+ /**
+ * The clauses of this type of statement and their index.
+ *
+ * @var array $clauses
+ */
+ $clauses = array_flip(array_keys($statement::$CLAUSES));
+
+ // This is a cheap fix for `SELECT` statements that contain `UNION`.
+ // Replacing the `ORDER BY` or `LIMIT` clauses should replace the last
+ // clause.
+ if (($statement instanceof SelectStatement) && (!empty($statement->union))) {
+ $clauses['ORDER BY'] = count($clauses) + 1;
+ $clauses['LIMIT'] = count($clauses) + 2;
+ }
+
+ /**
+ * Lexer used for lexing the clause.
+ *
+ * @var Lexer $lexer
+ */
+ $lexer = new Lexer($clause);
+
+ /**
+ * The type of this clause.
+ *
+ * @var string $clauseType
+ */
+ $clauseType = $lexer->list->getNextOfType(Token::TYPE_KEYWORD)->value;
+
+ /**
+ * The index of this clause.
+ *
+ * @var int $clauseIdx
+ */
+ $clauseIdx = $clauses[$clauseType];
+
+ $firstClauseIdx = $clauseIdx;
+ $lastClauseIdx = $clauseIdx + 1;
+
+ // Determining the behavior of this function.
+ if ($type === -1) {
+ $firstClauseIdx = -1; // Something small enough.
+ $lastClauseIdx = $clauseIdx - 1;
+ } elseif ($type === 1) {
+ $firstClauseIdx = $clauseIdx + 1;
+ $lastClauseIdx = 10000; // Something big enough.
+ } elseif (is_string($type)) {
+ if ($clauses[$type] > $clauseIdx) {
+ $firstClauseIdx = $clauseIdx + 1;
+ $lastClauseIdx = $clauses[$type] - 1;
+ } else {
+ $firstClauseIdx = $clauses[$type] + 1;
+ $lastClauseIdx = $clauseIdx - 1;
+ }
+ }
+
+ // This option is unavailable for multiple clauses.
+ if ($type !== 0) {
+ $skipFirst = false;
+ }
+
+ for ($i = $statement->first; $i <= $statement->last; ++$i) {
+ $token = $list->tokens[$i];
+
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ if ($token->type === Token::TYPE_OPERATOR) {
+ if ($token->value === '(') {
+ ++$brackets;
+ } elseif ($token->value === ')') {
+ --$brackets;
+ }
+ }
+
+ if ($brackets == 0) {
+ // Checking if the section was changed.
+ if (($token->type === Token::TYPE_KEYWORD)
+ && (isset($clauses[$token->value]))
+ && ($clauses[$token->value] >= $currIdx)
+ ) {
+ $currIdx = $clauses[$token->value];
+ if (($skipFirst) && ($currIdx == $clauseIdx)) {
+ // This token is skipped (not added to the old
+ // clause) because it will be replaced.
+ continue;
+ }
+ }
+ }
+
+ if (($firstClauseIdx <= $currIdx) && ($currIdx <= $lastClauseIdx)) {
+ $ret .= $token->token;
+ }
+ }
+
+ return trim($ret);
+ }
+
+ /**
+ * Builds a query by rebuilding the statement from the tokens list supplied
+ * and replaces a clause.
+ *
+ * It is a very basic version of a query builder.
+ *
+ * @param Statement $statement The parsed query that has to be modified.
+ * @param TokensList $list The list of tokens.
+ * @param string $old The type of the clause that should be
+ * replaced. This can be an entire clause.
+ * @param string $new The new clause. If this parameter is omitted
+ * it is considered to be equal with `$old`.
+ * @param bool $onlyType Whether only the type of the clause should
+ * be replaced or the entire clause.
+ *
+ * @return string
+ */
+ public static function replaceClause($statement, $list, $old, $new = null, $onlyType = false)
+ {
+ // TODO: Update the tokens list and the statement.
+
+ if ($new === null) {
+ $new = $old;
+ }
+
+ if ($onlyType) {
+ return static::getClause($statement, $list, $old, -1, false) . ' ' .
+ $new . ' ' . static::getClause($statement, $list, $old, 0) . ' ' .
+ static::getClause($statement, $list, $old, 1, false);
+ }
+
+ return static::getClause($statement, $list, $old, -1, false) . ' ' .
+ $new . ' ' . static::getClause($statement, $list, $old, 1, false);
+ }
+
+ /**
+ * Builds a query by rebuilding the statement from the tokens list supplied
+ * and replaces multiple clauses.
+ *
+ * @param Statement $statement The parsed query that has to be modified.
+ * @param TokensList $list The list of tokens.
+ * @param array $ops Clauses to be replaced. Contains multiple
+ * arrays having two values: array($old, $new).
+ * Clauses must be sorted.
+ *
+ * @return string
+ */
+ public static function replaceClauses($statement, $list, array $ops)
+ {
+ $count = count($ops);
+
+ // Nothing to do.
+ if ($count === 0) {
+ return '';
+ }
+
+ /**
+ * Value to be returned.
+ *
+ * @var string $ret
+ */
+ $ret = '';
+
+ // If there is only one clause, `replaceClause()` should be used.
+ if ($count === 1) {
+ return static::replaceClause(
+ $statement,
+ $list,
+ $ops[0][0],
+ $ops[0][1]
+ );
+ }
+
+ // Adding everything before first replacement.
+ $ret .= static::getClause($statement, $list, $ops[0][0], -1) . ' ';
+
+ // Doing replacements.
+ for ($i = 0; $i < $count; ++$i) {
+ $ret .= $ops[$i][1] . ' ';
+
+ // Adding everything between this and next replacement.
+ if ($i + 1 !== $count) {
+ $ret .= static::getClause($statement, $list, $ops[$i][0], $ops[$i + 1][0]) . ' ';
+ }
+ }
+
+ // Adding everything after the last replacement.
+ $ret .= static::getClause($statement, $list, $ops[$count - 1][0], 1);
+
+ return $ret;
+ }
+
+ /**
+ * Gets the first full statement in the query.
+ *
+ * @param string $query The query to be analyzed.
+ * @param string $delimiter The delimiter to be used.
+ *
+ * @return array Array containing the first full query, the
+ * remaining part of the query and the last
+ * delimiter.
+ */
+ public static function getFirstStatement($query, $delimiter = null)
+ {
+ $lexer = new Lexer($query, false, $delimiter);
+ $list = $lexer->list;
+
+ /**
+ * Whether a full statement was found.
+ *
+ * @var bool $fullStatement
+ */
+ $fullStatement = false;
+
+ /**
+ * The first full statement.
+ *
+ * @var string $statement
+ */
+ $statement = '';
+
+ for ($list->idx = 0; $list->idx < $list->count; ++$list->idx) {
+ $token = $list->tokens[$list->idx];
+
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ $statement .= $token->token;
+
+ if (($token->type === Token::TYPE_DELIMITER) && (!empty($token->token))) {
+ $delimiter = $token->token;
+ $fullStatement = true;
+ break;
+ }
+ }
+
+ // No statement was found so we return the entire query as being the
+ // remaining part.
+ if (!$fullStatement) {
+ return array(null, $query, $delimiter);
+ }
+
+ // At least one query was found so we have to build the rest of the
+ // remaining query.
+ $query = '';
+ for (++$list->idx; $list->idx < $list->count; ++$list->idx) {
+ $query .= $list->tokens[$list->idx]->token;
+ }
+
+ return array(trim($statement), $query, $delimiter);
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php
new file mode 100644
index 0000000000..5450cac178
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/Routine.php
@@ -0,0 +1,136 @@
+<?php
+
+/**
+ * Routine utilities.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Lexer;
+use SqlParser\Parser;
+use SqlParser\Components\DataType;
+use SqlParser\Components\ParameterDefinition;
+use SqlParser\Statements\CreateStatement;
+
+/**
+ * Routine utilities.
+ *
+ * @category Routines
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Routine
+{
+
+ /**
+ * Parses a parameter of a routine.
+ *
+ * @param string $param Parameter's definition.
+ *
+ * @return array
+ */
+ public static function getReturnType($param)
+ {
+ $lexer = new Lexer($param);
+
+ // A dummy parser is used for error reporting.
+ $type = DataType::parse(new Parser(), $lexer->list);
+
+ if ($type === null) {
+ return array('', '', '', '', '');
+ }
+
+ $options = array();
+ foreach ($type->options->options as $opt) {
+ $options[] = is_string($opt) ? $opt : $opt['value'];
+ }
+
+ return array(
+ '',
+ '',
+ $type->name,
+ implode(',', $type->parameters),
+ implode(' ', $options)
+ );
+ }
+
+ /**
+ * Parses a parameter of a routine.
+ *
+ * @param string $param Parameter's definition.
+ *
+ * @return array
+ */
+ public static function getParameter($param)
+ {
+ $lexer = new Lexer('(' . $param . ')');
+
+ // A dummy parser is used for error reporting.
+ $param = ParameterDefinition::parse(new Parser(), $lexer->list);
+
+ if (empty($param[0])) {
+ return array('', '', '', '', '');
+ }
+
+ $param = $param[0];
+
+ $options = array();
+ foreach ($param->type->options->options as $opt) {
+ $options[] = is_string($opt) ? $opt : $opt['value'];
+ }
+
+ return array(
+ empty($param->inOut) ? '' : $param->inOut,
+ $param->name,
+ $param->type->name,
+ implode(',', $param->type->parameters),
+ implode(' ', $options)
+ );
+ }
+
+ /**
+ * Gets the parameters of a routine from the parse tree.
+ *
+ * @param CreateStatement $statement The statement to be processed.
+ *
+ * @return array
+ */
+ public static function getParameters($statement)
+ {
+ $retval = array(
+ 'num' => 0,
+ 'dir' => array(),
+ 'name' => array(),
+ 'type' => array(),
+ 'length' => array(),
+ 'length_arr' => array(),
+ 'opts' => array(),
+ );
+
+ if (!empty($statement->parameters)) {
+ $idx = 0;
+ foreach ($statement->parameters as $param) {
+ $retval['dir'][$idx] = $param->inOut;
+ $retval['name'][$idx] = $param->name;
+ $retval['type'][$idx] = $param->type->name;
+ $retval['length'][$idx] = implode(',', $param->type->parameters);
+ $retval['length_arr'][$idx] = $param->type->parameters;
+ $retval['opts'][$idx] = array();
+ foreach ($param->type->options->options as $opt) {
+ $retval['opts'][$idx][] = is_string($opt) ?
+ $opt : $opt['value'];
+ }
+ $retval['opts'][$idx] = implode(' ', $retval['opts'][$idx]);
+ ++$idx;
+ }
+
+ $retval['num'] = $idx;
+ }
+
+ return $retval;
+ }
+}
diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php
new file mode 100644
index 0000000000..81699ad6d0
--- /dev/null
+++ b/libraries/sql-parser/src/Utils/Table.php
@@ -0,0 +1,136 @@
+<?php
+
+/**
+ * Table utilities.
+ *
+ * @package SqlParser
+ * @subpackage Utils
+ */
+namespace SqlParser\Utils;
+
+use SqlParser\Statements\CreateStatement;
+
+/**
+ * Table utilities.
+ *
+ * @category Statement
+ * @package SqlParser
+ * @subpackage Utils
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Table
+{
+
+ /**
+ * Gets the foreign keys of the table.
+ *
+ * @param CreateStatement $statement The statement to be processed.
+ *
+ * @return array
+ */
+ public static function getForeignKeys($statement)
+ {
+ if ((empty($statement->fields))
+ || (!is_array($statement->fields))
+ || (!$statement->options->has('TABLE'))
+ ) {
+ return array();
+ }
+
+ $ret = array();
+
+ foreach ($statement->fields as $field) {
+ if ((empty($field->key)) || ($field->key->type !== 'FOREIGN KEY')) {
+ continue;
+ }
+
+ $tmp = array(
+ 'constraint' => $field->name,
+ 'index_list' => $field->key->columns,
+ );
+
+ if (!empty($field->references)) {
+ $tmp['ref_table_name'] = $field->references->table;
+ $tmp['ref_index_list'] = $field->references->columns;
+
+ if (($opt = $field->references->options->has('ON UPDATE'))) {
+ $tmp['on_update'] = str_replace(' ', '_', $opt);
+ }
+
+ if (($opt = $field->references->options->has('ON DELETE'))) {
+ $tmp['on_delete'] = str_replace(' ', '_', $opt);
+ }
+
+ // if (($opt = $field->references->options->has('MATCH'))) {
+ // $tmp['match'] = str_replace(' ', '_', $opt);
+ // }
+ }
+
+ $ret[] = $tmp;
+
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Gets fields of the table.
+ *
+ * @param CreateStatement $statement The statement to be processed.
+ *
+ * @return array
+ */
+ public static function getFields($statement)
+ {
+ if ((empty($statement->fields))
+ || (!is_array($statement->fields))
+ || (!$statement->options->has('TABLE'))
+ ) {
+ return array();
+ }
+
+ $ret = array();
+
+ foreach ($statement->fields as $field) {
+ // Skipping keys.
+ if (empty($field->type)) {
+ continue;
+ }
+
+ $ret[$field->name] = array(
+ 'type' => $field->type->name,
+ 'timestamp_not_null' => false,
+ );
+
+ if ($field->options) {
+ if ($field->type->name === 'TIMESTAMP') {
+ if ($field->options->has('NOT NULL')) {
+ $ret[$field->name]['timestamp_not_null'] = true;
+ }
+ }
+
+ if (($option = $field->options->has('DEFAULT'))) {
+ $ret[$field->name]['default_value'] = $option;
+ if ($option === 'CURRENT_TIMESTAMP') {
+ $ret[$field->name]['default_current_timestamp'] = true;
+ }
+ }
+
+ if (($option = $field->options->has('ON UPDATE'))) {
+ if ($option === 'CURRENT_TIMESTAMP') {
+ $ret[$field->name]['on_update_current_timestamp'] = true;
+ }
+ }
+
+ if (($option = $field->options->has('AS'))) {
+ $ret[$field->name]['generated'] = true;
+ $ret[$field->name]['expr'] = $option;
+ }
+ }
+
+ }
+
+ return $ret;
+ }
+}
diff --git a/libraries/sql.lib.php b/libraries/sql.lib.php
index 0489003b4c..12c7998b3d 100644
--- a/libraries/sql.lib.php
+++ b/libraries/sql.lib.php
@@ -10,57 +10,23 @@ if (!defined('PHPMYADMIN')) {
}
/**
- * Get the database name inside a query
+ * Parses and analyzes the given SQL query.
*
- * @param string $sql SQL query
- * @param array $databases array with all databases
+ * @param string $sql_query SQL query
+ * @param string $db DB name
*
- * @return string $db new database name
- */
-function PMA_getNewDatabase($sql, $databases)
-{
- $db = '';
- // loop through all the databases
- foreach ($databases as $database) {
- if (/*overload*/mb_strpos($sql, $database['SCHEMA_NAME']) !== false
- ) {
- $db = $database['SCHEMA_NAME'];
- break;
- }
- }
- return $db;
-}
-
-/**
- * Get the table name in a sql query
- * If there are several tables in the SQL query,
- * first table will return
- *
- * @param string $sql SQL query
- * @param array $tables array of names in current database
- *
- * @return string $table table name
+ * @return mixed
*/
-function PMA_getTableNameBySQL($sql, $tables)
+function PMA_parseAndAnalyze($sql_query, $db = null)
{
- $table = '';
-
- // loop through all the tables in the database
- foreach ($tables as $tbl) {
- if (/*overload*/mb_strpos($sql, $tbl)) {
- $table .= ' ' . $tbl;
- }
+ if (($db === null) && (!empty($GLOBALS['db']))) {
+ $db = $GLOBALS['db'];
}
- if (count(explode(' ', trim($table))) > 1) {
- $tmp_array = explode(' ', trim($table));
- return $tmp_array[0];
- }
-
- return trim($table);
+ // `$sql_query` is being used inside `parse_analyze.inc.php`.
+ return include 'libraries/parse_analyze.inc.php';
}
-
/**
* Handle remembered sorting order, only for single table query
*
@@ -75,34 +41,36 @@ function PMA_handleSortOrder(
$db, $table, &$analyzed_sql_results, &$full_sql_query
) {
$pmatable = new PMA_Table($table, $db);
- if (empty($analyzed_sql_results['analyzed_sql'][0]['order_by_clause'])) {
- $sorted_col = $pmatable->getUiProp(PMA_Table::PROP_SORTED_COLUMN);
- if ($sorted_col) {
- //remove the tablename from retrieved preference
- //to get just the column name and the sort order
- $sorted_col = str_replace(
- PMA_Util::backquote($table) . '.', '', $sorted_col
- );
- // retrieve the remembered sorting order for current table
- $sql_order_to_append = ' ORDER BY ' . $sorted_col . ' ';
- $full_sql_query
- = $analyzed_sql_results['analyzed_sql'][0]['section_before_limit']
- . $sql_order_to_append
- . $analyzed_sql_results['analyzed_sql'][0]['limit_clause']
- . ' '
- . $analyzed_sql_results['analyzed_sql'][0]['section_after_limit'];
-
- // update the $analyzed_sql
- $analyzed_sql_results['analyzed_sql'][0]['section_before_limit']
- .= $sql_order_to_append;
- $analyzed_sql_results['analyzed_sql'][0]['order_by_clause']
- = $sorted_col;
+
+ if (empty($analyzed_sql_results['order'])) {
+
+ // Retrieving the name of the column we should sort after.
+ $sortCol = $pmatable->getUiProp(PMA_Table::PROP_SORTED_COLUMN);
+ if (empty($sortCol)) {
+ return;
}
+
+ // Remove the name of the table from the retrieved field name.
+ $sortCol = str_replace(PMA_Util::backquote($table) . '.', '', $sortCol);
+
+ // Create the new query.
+ $full_sql_query = SqlParser\Utils\Query::replaceClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'ORDER BY ' . $sortCol
+ );
+
+ // TODO: Avoid reparsing the query.
+ $analyzed_sql_results = SqlParser\Utils\Query::getAll($full_sql_query);
} else {
- // store the remembered table into session
+ // Store the remembered table into session.
$pmatable->setUiProp(
PMA_Table::PROP_SORTED_COLUMN,
- $analyzed_sql_results['analyzed_sql'][0]['order_by_clause']
+ SqlParser\Utils\Query::getClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'ORDER BY'
+ )
);
}
}
@@ -110,43 +78,18 @@ function PMA_handleSortOrder(
/**
* Append limit clause to SQL query
*
- * @param array $analyzed_sql the analyzed query
- * @param string $sql_limit_to_append clause to append
+ * @param array &$analyzed_sql_results the analyzed query results
*
* @return string limit clause appended SQL query
*/
-function PMA_getSqlWithLimitClause($analyzed_sql,
- $sql_limit_to_append
-) {
- return $analyzed_sql[0]['section_before_limit'] . "\n"
- . $sql_limit_to_append . $analyzed_sql[0]['section_after_limit'];
-}
-
-
-/**
- * Get column name from a drop SQL statement
- *
- * @param string $sql SQL query
- *
- * @return string $drop_column Name of the column
- */
-function PMA_getColumnNameInColumnDropSql($sql)
+function PMA_getSqlWithLimitClause(&$analyzed_sql_results)
{
- $tmpArray1 = explode('DROP', $sql);
- $str_to_check = trim($tmpArray1[1]);
-
- if (/*overload*/mb_stripos($str_to_check, 'COLUMN') !== false) {
- $tmpArray2 = explode('COLUMN', $str_to_check);
- $str_to_check = trim($tmpArray2[1]);
- }
-
- $tmpArray3 = explode(' ', $str_to_check);
- $str_to_check = trim($tmpArray3[0]);
-
- $drop_column = str_replace(';', '', trim($str_to_check));
- $drop_column = str_replace('`', '', $drop_column);
-
- return $drop_column;
+ return SqlParser\Utils\Query::replaceClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'LIMIT ' . $_SESSION['tmpval']['pos'] . ', '
+ . $_SESSION['tmpval']['max_rows']
+ );
}
/**
@@ -257,61 +200,6 @@ function PMA_getHtmlForRelationalColumnDropdown($db, $table, $column, $curr_valu
}
/**
- * Get the HTML for the header of the page in print view if print view is selected.
- * Otherwise returns null.
- *
- * @param string $db current database
- * @param string $sql_query current sql query
- * @param int $num_rows the number of rows in result
- *
- * @return string $header html for the header
- */
-function PMA_getHtmlForPrintViewHeader($db, $sql_query, $num_rows)
-{
- $response = PMA_Response::getInstance();
- $header = $response->getHeader();
- if (isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
- PMA_Util::checkParameters(array('db', 'sql_query'));
- $header->enablePrintView();
- if ( $GLOBALS['cfg']['Server']['verbose']) {
- $hostname = $GLOBALS['cfg']['Server']['verbose'];
- } else {
- $hostname = $GLOBALS['cfg']['Server']['host'];
- if (! empty( $GLOBALS['cfg']['Server']['port'])) {
- $hostname .= $GLOBALS['cfg']['Server']['port'];
- }
- }
-
- $versions = "phpMyAdmin&nbsp;" . PMA_VERSION;
- $versions .= "&nbsp;/&nbsp;";
- $versions .= "MySQL&nbsp;" . PMA_MYSQL_STR_VERSION;
-
- $print_view_header = '';
- $print_view_header .= "<h1>" . __('SQL result') . "</h1>";
- $print_view_header .= "<p>";
- $print_view_header .= "<strong>" . __('Host:')
- . "</strong> $hostname<br />";
- $print_view_header .= "<strong>" . __('Database:') . "</strong> "
- . htmlspecialchars($db) . "<br />";
- $print_view_header .= "<strong>" . __('Generation Time:') . "</strong> "
- . PMA_Util::localisedDate() . "<br />";
- $print_view_header .= "<strong>" . __('Generated by:')
- . "</strong> $versions<br />";
- $print_view_header .= "<strong>" . __('SQL query:') . "</strong> "
- . htmlspecialchars($sql_query) . ";";
- if (isset($num_rows)) {
- $print_view_header .= "<br />";
- $print_view_header .= "<strong>" . __('Rows:') . "</strong> $num_rows";
- }
- $print_view_header .= "</p>";
- } else {
- $print_view_header = null;
- }
-
- return $print_view_header;
-}
-
-/**
* Get the HTML for the profiling table and accompanying chart if profiling is set.
* Otherwise returns null
*
@@ -323,7 +211,7 @@ function PMA_getHtmlForPrintViewHeader($db, $sql_query, $num_rows)
*/
function PMA_getHtmlForProfilingChart($url_query, $db, $profiling_results)
{
- if (isset($profiling_results)) {
+ if (! empty($profiling_results)) {
$pma_token = $_SESSION[' PMA_token '];
$url_query = isset($url_query)
? $url_query
@@ -332,7 +220,7 @@ function PMA_getHtmlForProfilingChart($url_query, $db, $profiling_results)
$profiling_table = '';
$profiling_table .= '<fieldset><legend>' . __('Profiling')
. '</legend>' . "\n";
- $profiling_table .= '<div style="float: left;">';
+ $profiling_table .= '<div class="floatleft">';
$profiling_table .= '<h3>' . __('Detailed profile') . '</h3>';
$profiling_table .= '<table id="profiletable"><thead>' . "\n";
$profiling_table .= ' <tr>' . "\n";
@@ -350,7 +238,7 @@ function PMA_getHtmlForProfilingChart($url_query, $db, $profiling_results)
$profiling_table .= '</tbody></table>' . "\n";
$profiling_table .= '</div>';
- $profiling_table .= '<div style="float: left; margin-left:10px;">';
+ $profiling_table .= '<div class="floatleft">';
$profiling_table .= '<h3>' . __('Summary by state') . '</h3>';
$profiling_table .= '<table id="profilesummarytable"><thead>' . "\n";
$profiling_table .= ' <tr>' . "\n";
@@ -619,7 +507,7 @@ function PMA_getHtmlForBookmark($displayParts, $cfgBookmark, $sql_query, $db,
$html = '<form action="sql.php" method="post"'
. ' onsubmit="return ! emptyCheckTheField(this,'
. '\'bkm_fields[bkm_label]\');"'
- . ' class="bookmarkQueryForm">';
+ . ' class="bookmarkQueryForm print_ignore">';
$html .= PMA_URL_getHiddenInputs();
$html .= '<input type="hidden" name="db"'
. ' value="' . htmlspecialchars($db) . '" />';
@@ -672,23 +560,16 @@ function PMA_getHtmlForBookmark($displayParts, $cfgBookmark, $sql_query, $db,
*/
function PMA_isRememberSortingOrder($analyzed_sql_results)
{
- $select_from = isset(
- $analyzed_sql_results['analyzed_sql'][0]['queryflags']['select_from']
- );
- if ($GLOBALS['cfg']['RememberSorting']
+ return $GLOBALS['cfg']['RememberSorting']
&& ! ($analyzed_sql_results['is_count']
- || $analyzed_sql_results['is_export']
- || $analyzed_sql_results['is_func']
- || $analyzed_sql_results['is_analyse'])
- && isset($analyzed_sql_results['analyzed_sql'][0]['select_expr'])
- && (count($analyzed_sql_results['analyzed_sql'][0]['select_expr']) == 0)
- && $select_from
- && count($analyzed_sql_results['analyzed_sql'][0]['table_ref']) == 1
- ) {
- return true;
- } else {
- return false;
- }
+ || $analyzed_sql_results['is_export']
+ || $analyzed_sql_results['is_func']
+ || $analyzed_sql_results['is_analyse'])
+ && $analyzed_sql_results['select_from']
+ && ((empty($analyzed_sql_results['select_expr']))
+ || (count($analyzed_sql_results['select_expr'] == 1)
+ && ($analyzed_sql_results['select_expr'][0] == '*')))
+ && count($analyzed_sql_results['select_tables']) == 1;
}
/**
@@ -701,20 +582,12 @@ function PMA_isRememberSortingOrder($analyzed_sql_results)
*/
function PMA_isAppendLimitClause($analyzed_sql_results)
{
- $select_from = isset(
- $analyzed_sql_results['analyzed_sql'][0]['queryflags']['select_from']
- );
- if (($_SESSION['tmpval']['max_rows'] != 'all')
+ return ($_SESSION['tmpval']['max_rows'] != 'all')
&& ! ($analyzed_sql_results['is_export']
|| $analyzed_sql_results['is_analyse'])
- && ($select_from || $analyzed_sql_results['is_subquery'])
- && ! isset($analyzed_sql_results['analyzed_sql'][0]['queryflags']['offset'])
- && empty($analyzed_sql_results['analyzed_sql'][0]['limit_clause'])
- ) {
- return true;
- } else {
- return false;
- }
+ && ($analyzed_sql_results['select_from']
+ || $analyzed_sql_results['is_subquery'])
+ && empty($analyzed_sql_results['limit']);
}
/**
@@ -728,29 +601,19 @@ function PMA_isAppendLimitClause($analyzed_sql_results)
*/
function PMA_isJustBrowsing($analyzed_sql_results, $find_real_end)
{
- $distinct = isset(
- $analyzed_sql_results['analyzed_sql'][0]['queryflags']['distinct']
- );
-
- $table_name = isset(
- $analyzed_sql_results['analyzed_sql'][0]['table_ref'][1]['table_name']
- );
- if (! $analyzed_sql_results['is_group']
+ return ! $analyzed_sql_results['is_group']
&& ! $analyzed_sql_results['is_func']
- && ! isset($analyzed_sql_results['analyzed_sql'][0]['queryflags']['union'])
- && ! $distinct
- && ! $table_name
- && (empty($analyzed_sql_results['analyzed_sql'][0]['where_clause'])
- || $analyzed_sql_results['analyzed_sql'][0]['where_clause'] == '1 ')
- && empty($analyzed_sql_results['analyzed_sql'][0]['group_by_clause'])
+ && empty($analyzed_sql_results['union'])
+ && empty($analyzed_sql_results['distinct'])
+ && $analyzed_sql_results['select_from']
+ && (count($analyzed_sql_results['select_tables']) <= 1)
+ && (empty($analyzed_sql_results['statement']->where)
+ || (count($analyzed_sql_results['statement']->where) == 1
+ && $analyzed_sql_results['statement']->where[0]->expr ==='1'))
+ && empty($analyzed_sql_results['group'])
&& ! isset($find_real_end)
- && !$analyzed_sql_results['is_subquery']
- && empty($analyzed_sql_results['analyzed_sql'][0]['having_clause'])
- ) {
- return true;
- } else {
- return false;
- }
+ && ! $analyzed_sql_results['is_subquery']
+ && empty($analyzed_sql_results['having']);
}
/**
@@ -763,14 +626,9 @@ function PMA_isJustBrowsing($analyzed_sql_results, $find_real_end)
*/
function PMA_isDeleteTransformationInfo($analyzed_sql_results)
{
- if (!empty($analyzed_sql_results['analyzed_sql'][0]['querytype'])
- && (($analyzed_sql_results['analyzed_sql'][0]['querytype'] == 'ALTER')
- || ($analyzed_sql_results['analyzed_sql'][0]['querytype'] == 'DROP'))
- ) {
- return true;
- } else {
- return false;
- }
+ return !empty($analyzed_sql_results['querytype'])
+ && (($analyzed_sql_results['querytype'] == 'ALTER')
+ || ($analyzed_sql_results['querytype'] == 'DROP'));
}
/**
@@ -786,16 +644,10 @@ function PMA_isDeleteTransformationInfo($analyzed_sql_results)
function PMA_hasNoRightsToDropDatabase($analyzed_sql_results,
$allowUserDropDatabase, $is_superuser
) {
- if (! defined('PMA_CHK_DROP')
+ return ! defined('PMA_CHK_DROP')
&& ! $allowUserDropDatabase
- && isset ($analyzed_sql_results['drop_database'])
- && $analyzed_sql_results['drop_database'] == 1
- && ! $is_superuser
- ) {
- return true;
- } else {
- return false;
- }
+ && $analyzed_sql_results['drop_database']
+ && ! $is_superuser;
}
/**
@@ -912,7 +764,7 @@ function PMA_addBookmark($pmaAbsoluteUri, $goto)
*/
function PMA_findRealEndOfRows($db, $table)
{
- $unlim_num_rows = PMA_Table::countRecords($db, $table, true);
+ $unlim_num_rows = $GLOBALS['dbi']->getTable($db, $table)->countRecords(true);
$_SESSION['tmpval']['pos'] = PMA_getStartPosToDisplayRow($unlim_num_rows);
return $unlim_num_rows;
@@ -1087,7 +939,7 @@ function PMA_storeTheQueryAsBookmark($db, $bkm_user, $sql_query_for_bookmark,
if (isset($bkm_replace)) {
$bookmarks = PMA_Bookmark_getList($db);
foreach ($bookmarks as $key => $val) {
- if ($val == $bkm_label) {
+ if ($val['label'] == $bkm_label) {
PMA_Bookmark_delete($key);
}
}
@@ -1106,6 +958,9 @@ function PMA_storeTheQueryAsBookmark($db, $bkm_user, $sql_query_for_bookmark,
*/
function PMA_executeQueryAndStoreResults($full_sql_query)
{
+ // close session in case the query takes too long
+ session_write_close();
+
// Measure query time.
$querytime_before = array_sum(explode(' ', microtime()));
@@ -1114,6 +969,9 @@ function PMA_executeQueryAndStoreResults($full_sql_query)
);
$querytime_after = array_sum(explode(' ', microtime()));
+ // reopen session
+ session_start();
+
$GLOBALS['querytime'] = $querytime_after - $querytime_before;
return $result;
@@ -1124,15 +982,14 @@ function PMA_executeQueryAndStoreResults($full_sql_query)
*
* @param boolean $is_affected whether the query affected a table
* @param mixed $result results of executing the query
- * @param int $num_rows number of rows affected or changed
*
* @return int $num_rows number of rows affected or changed
*/
-function PMA_getNumberOfRowsAffectedOrChanged($is_affected, $result, $num_rows)
+function PMA_getNumberOfRowsAffectedOrChanged($is_affected, $result)
{
if (! $is_affected) {
$num_rows = ($result) ? @$GLOBALS['dbi']->numRows($result) : 0;
- } elseif (! isset($num_rows)) {
+ } else {
$num_rows = @$GLOBALS['dbi']->affectedRows();
}
@@ -1149,54 +1006,40 @@ function PMA_getNumberOfRowsAffectedOrChanged($is_affected, $result, $num_rows)
*/
function PMA_hasCurrentDbChanged($db)
{
- // Checks if the current database has changed
- // This could happen if the user sends a query like "USE `database`;"
- $reload = 0;
if (/*overload*/mb_strlen($db)) {
$current_db = $GLOBALS['dbi']->fetchValue('SELECT DATABASE()');
// $current_db is false, except when a USE statement was sent
- if ($current_db != false && $db !== $current_db) {
- $reload = 1;
- }
+ return ($current_db != false) && ($db !== $current_db);
}
- return $reload;
+ return false;
}
/**
* If a table, database or column gets dropped, clean comments.
*
- * @param String $db current database
- * @param String $table current table
- * @param String $dropped_column dropped column if any
- * @param bool $purge whether purge set or not
- * @param array $extra_data extra data
+ * @param String $db current database
+ * @param String $table current table
+ * @param String $column current column
+ * @param bool $purge whether purge set or not
*
* @return array $extra_data
*/
-function PMA_cleanupRelations($db, $table, $dropped_column, $purge, $extra_data)
+function PMA_cleanupRelations($db, $table, $column, $purge)
{
include_once 'libraries/relation_cleanup.lib.php';
- if (isset($purge) && $purge == 1) {
- if (/*overload*/mb_strlen($table) && /*overload*/mb_strlen($db)) {
- PMA_relationsCleanupTable($db, $table);
- } elseif (/*overload*/mb_strlen($db)) {
+ if (! empty($purge) && /*overload*/mb_strlen($db)) {
+ if (/*overload*/mb_strlen($table)) {
+ if (isset($column) && /*overload*/mb_strlen($column)) {
+ PMA_relationsCleanupColumn($db, $table, $column);
+ } else {
+ PMA_relationsCleanupTable($db, $table);
+ }
+ } else {
PMA_relationsCleanupDatabase($db);
}
}
-
- if (isset($dropped_column)
- && !empty($dropped_column)
- && /*overload*/mb_strlen($db)
- && /*overload*/mb_strlen($table)
- ) {
- PMA_relationsCleanupColumn($db, $table, $dropped_column);
- // to refresh the list of indexes (Ajax mode)
- $extra_data['indexes_list'] = PMA_Index::getView($table, $db);
- }
-
- return $extra_data;
}
/**
@@ -1204,26 +1047,26 @@ function PMA_cleanupRelations($db, $table, $dropped_column, $purge, $extra_data)
* the 'LIMIT' clause that may have been programatically added
*
* @param int $num_rows number of rows affected/changed by the query
- * @param bool $is_select whether the query is SELECT or not
* @param bool $justBrowsing whether just browsing or not
* @param string $db the current database
* @param string $table the current table
- * @param array $parsed_sql parsed sql
* @param array $analyzed_sql_results the analyzed query and other variables set
* after analyzing the query
*
* @return int $unlim_num_rows unlimited number of rows
*/
function PMA_countQueryResults(
- $num_rows, $is_select, $justBrowsing,
- $db, $table, $parsed_sql, $analyzed_sql_results
+ $num_rows, $justBrowsing, $db, $table, $analyzed_sql_results
) {
+
if (!PMA_isAppendLimitClause($analyzed_sql_results)) {
// if we did not append a limit, set this to get a correct
// "Showing rows..." message
// $_SESSION['tmpval']['max_rows'] = 'all';
- $unlim_num_rows = $num_rows;
- } elseif ($is_select || $analyzed_sql_results['is_subquery']) {
+ $unlim_num_rows = $num_rows;
+ } elseif ($analyzed_sql_results['querytype'] == 'SELECT'
+ || $analyzed_sql_results['is_subquery']
+ ) {
// c o u n t q u e r y
// If we are "just browsing", there is only one table,
@@ -1235,11 +1078,7 @@ function PMA_countQueryResults(
// due to $find_real_end == true
if ($justBrowsing) {
// Get row count (is approximate for InnoDB)
- $unlim_num_rows = PMA_Table::countRecords(
- $db,
- $table,
- false
- );
+ $unlim_num_rows = $GLOBALS['dbi']->getTable($db, $table)->countRecords();
/**
* @todo Can we know at this point that this is InnoDB,
* (in this case there would be no need for getting
@@ -1252,70 +1091,37 @@ function PMA_countQueryResults(
* @todo In countRecords(), MaxExactCount is also verified,
* so can we avoid checking it twice?
*/
- $unlim_num_rows = PMA_Table::countRecords(
- $db,
- $table,
- true
- );
+ $unlim_num_rows = $GLOBALS['dbi']->getTable($db, $table)
+ ->countRecords(true);
}
} else {
- // add select expression after the SQL_CALC_FOUND_ROWS
- // for UNION, just adding SQL_CALC_FOUND_ROWS
- // after the first SELECT works.
+ // The SQL_CALC_FOUND_ROWS option of the SELECT statement is used.
- // take the left part, could be:
- // SELECT
- // (SELECT
+ // For UNION statements, only a SQL_CALC_FOUND_ROWS is required
+ // after the first SELECT.
- $analyzed_sql = $analyzed_sql_results['analyzed_sql'];
-
- $count_query = PMA_SQP_format(
- $parsed_sql,
- 'query_only',
- 0,
- $analyzed_sql[0]['position_of_first_select'] + 1
- );
- $count_query .= ' SQL_CALC_FOUND_ROWS ';
- // add everything that was after the first SELECT
- $count_query .= PMA_SQP_format(
- $parsed_sql,
- 'query_only',
- $analyzed_sql[0]['position_of_first_select'] + 1
+ $count_query = SqlParser\Utils\Query::replaceClause(
+ $analyzed_sql_results['statement'],
+ $analyzed_sql_results['parser']->list,
+ 'SELECT SQL_CALC_FOUND_ROWS',
+ null,
+ true
);
- // ensure there is no semicolon at the end of the
- // count query because we'll probably add
- // a LIMIT 1 clause after it
- $count_query = rtrim($count_query);
- $count_query = rtrim($count_query, ';');
- // if using SQL_CALC_FOUND_ROWS, add a LIMIT to avoid
- // long delays. Returned count will be complete anyway.
- // (but a LIMIT would disrupt results in an UNION)
+ // Another LIMIT clause is added to avoid long delays.
+ // A complete result will be returned anyway, but the LIMIT would
+ // stop the query as soon as the result that is required has been
+ // computed.
- if (! isset($analyzed_sql[0]['queryflags']['union'])) {
+ if (empty($analyzed_sql_results['union'])) {
$count_query .= ' LIMIT 1';
}
- // run the count query
-
+ // Running the count query.
$GLOBALS['dbi']->tryQuery($count_query);
- // if (mysql_error()) {
- // void.
- // I tried the case
- // (SELECT `User`, `Host`, `Db`, `Select_priv` FROM `db`)
- // UNION (SELECT `User`, `Host`, "%" AS "Db",
- // `Select_priv`
- // FROM `user`) ORDER BY `User`, `Host`, `Db`;
- // and although the generated count_query is wrong
- // the SELECT FOUND_ROWS() work! (maybe it gets the
- // count from the latest query that worked)
- //
- // another case where the count_query is wrong:
- // SELECT COUNT(*), f1 from t1 group by f1
- // and you click to sort on count(*)
- // }
+
$unlim_num_rows = $GLOBALS['dbi']->fetchValue('SELECT FOUND_ROWS()');
} // end else "just browsing"
} else {// not $is_select
@@ -1378,8 +1184,7 @@ function PMA_executeTheQuery($analyzed_sql_results, $full_sql_query, $is_gotofil
// (This must be done immediately after the query because
// mysql_affected_rows() reports about the last query done)
$num_rows = PMA_getNumberOfRowsAffectedOrChanged(
- $analyzed_sql_results['is_affected'], $result,
- isset($num_rows) ? $num_rows : null
+ $analyzed_sql_results['is_affected'], $result
);
// Grabs the profiling results
@@ -1392,20 +1197,22 @@ function PMA_executeTheQuery($analyzed_sql_results, $full_sql_query, $is_gotofil
);
$unlim_num_rows = PMA_countQueryResults(
- $num_rows, $analyzed_sql_results['is_select'], $justBrowsing, $db,
- $table, $analyzed_sql_results['parsed_sql'], $analyzed_sql_results
+ $num_rows, $justBrowsing, $db, $table, $analyzed_sql_results
);
- $extra_data = PMA_cleanupRelations(
- isset($db) ? $db : '', isset($table) ? $table : '',
+ PMA_cleanupRelations(
+ isset($db) ? $db : '',
+ isset($table) ? $table : '',
isset($_REQUEST['dropped_column']) ? $_REQUEST['dropped_column'] : null,
- isset($_REQUEST['purge']) ? $_REQUEST['purge'] : null,
- isset($extra_data) ? $extra_data : null
+ isset($_REQUEST['purge']) ? $_REQUEST['purge'] : null
);
- // Update Indexes list.
- if (isset($_REQUEST['index_change'])) {
- $extra_data['indexes_list'] = PMA_Index::getView($table, $db);
+ if (isset($_REQUEST['dropped_column'])
+ && /*overload*/mb_strlen($db)
+ && /*overload*/mb_strlen($table)
+ ) {
+ // to refresh the list of indexes (Ajax mode)
+ $extra_data['indexes_list'] = PMA_Index::getHtmlForIndexes($table, $db);
}
}
@@ -1416,31 +1223,29 @@ function PMA_executeTheQuery($analyzed_sql_results, $full_sql_query, $is_gotofil
/**
* Delete related tranformatioinformationn information
*
- * @param String $db current database
- * @param String $table current table
- * @param array $analyzed_sql analyzed sql query
+ * @param String $db current database
+ * @param String $table current table
+ * @param array $analyzed_sql_results analyzed sql results
*
* @return void
*/
-function PMA_deleteTransformationInfo($db, $table, $analyzed_sql)
+function PMA_deleteTransformationInfo($db, $table, $analyzed_sql_results)
{
include_once 'libraries/transformations.lib.php';
- if ($analyzed_sql[0]['querytype'] == 'ALTER') {
- $posDrop = /*overload*/mb_stripos(
- $analyzed_sql[0]['unsorted_query'],
- 'DROP'
- );
- if ($posDrop !== false) {
- $drop_column = PMA_getColumnNameInColumnDropSql(
- $analyzed_sql[0]['unsorted_query']
- );
-
- if ($drop_column != '') {
- PMA_clearTransformations($db, $table, $drop_column);
+ $statement = $analyzed_sql_results['statement'];
+ if ($statement instanceof SqlParser\Statements\AlterStatement) {
+ if (!empty($statement->altered[0])
+ && $statement->altered[0]->options->has('DROP')
+ ) {
+ if (!empty($statement->altered[0]->field->column)) {
+ PMA_clearTransformations(
+ $db,
+ $table,
+ $statement->altered[0]->field->column
+ );
}
}
-
- } else if (($analyzed_sql[0]['querytype'] == 'DROP') && ($table != '')) {
+ } elseif ($statement instanceof SqlParser\Statements\DropStatement) {
PMA_clearTransformations($db, $table);
}
}
@@ -1454,14 +1259,14 @@ function PMA_deleteTransformationInfo($db, $table, $analyzed_sql)
*
* @return string $message
*/
-function PMA_getMessageForNoRowsReturned($message_to_show, $analyzed_sql_results,
- $num_rows
+function PMA_getMessageForNoRowsReturned($message_to_show,
+ $analyzed_sql_results, $num_rows
) {
- if ($analyzed_sql_results['is_delete']) {
+ if ($analyzed_sql_results['querytype'] == 'DELETE"') {
$message = PMA_Message::getMessageForDeletedRows($num_rows);
} elseif ($analyzed_sql_results['is_insert']) {
- if ($analyzed_sql_results['is_replace']) {
- // For replace we get DELETED + INSERTED row count,
+ if ($analyzed_sql_results['querytype'] == 'REPLACE') {
+ // For REPLACE we get DELETED + INSERTED row count,
// so we have to call it affected
$message = PMA_Message::getMessageForAffectedRows($num_rows);
} else {
@@ -1489,7 +1294,9 @@ function PMA_getMessageForNoRowsReturned($message_to_show, $analyzed_sql_results
// fact that $message_to_show is sent for every case.
// The $message_to_show containing a success message and sent with
// the form should not have priority over errors
- } elseif (! empty($message_to_show) && ! $analyzed_sql_results['is_select']) {
+ } elseif (! empty($message_to_show)
+ && $analyzed_sql_results['querytype'] != 'SELECT'
+ ) {
$message = PMA_Message::rawSuccess(htmlspecialchars($message_to_show));
} elseif (! empty($GLOBALS['show_as_php'])) {
$message = PMA_Message::success(__('Showing as PHP code'));
@@ -1543,20 +1350,18 @@ function PMA_getQueryResponseForNoResultsReturned($analyzed_sql_results, $db,
$table, $message_to_show, $num_rows, $displayResultsObject, $extra_data
) {
if (PMA_isDeleteTransformationInfo($analyzed_sql_results)) {
- PMA_deleteTransformationInfo(
- $db, $table, $analyzed_sql_results['analyzed_sql']
- );
+ PMA_deleteTransformationInfo($db, $table, $analyzed_sql_results);
}
$message = PMA_getMessageForNoRowsReturned(
- isset($message_to_show) ? $message_to_show : null, $analyzed_sql_results,
- $num_rows
+ isset($message_to_show) ? $message_to_show : null,
+ $analyzed_sql_results, $num_rows
);
$html_output = '';
if (!isset($GLOBALS['show_as_php'])) {
- if (isset($GLOBALS['reload']) && $GLOBALS['reload'] == 1) {
+ if (! empty($GLOBALS['reload'])) {
$extra_data['reload'] = 1;
$extra_data['db'] = $GLOBALS['db'];
}
@@ -1577,10 +1382,9 @@ function PMA_getQueryResponseForNoResultsReturned($analyzed_sql_results, $db,
$response = PMA_Response::getInstance();
$response->addJSON(isset($extra_data) ? $extra_data : array());
- $query_type = PMA_DisplayResults::QUERY_TYPE_SELECT;
- if ($analyzed_sql_results['analyzed_sql'][0]['querytype'] == $query_type) {
+ if (!empty($analyzed_sql_results['is_select'])) {
$html_output .= $displayResultsObject->getCreateViewQueryResultOp(
- $analyzed_sql_results['analyzed_sql']
+ $analyzed_sql_results
);
}
}
@@ -1610,21 +1414,23 @@ function PMA_sendResponseForGridEdit($result)
/**
* Function to get html for the sql query results div
*
- * @param string $previous_update_query_html html for the previously executed query
- * @param string $profiling_chart_html html for profiling
- * @param object $missing_unique_column_msg message for the missing unique column
- * @param object $bookmark_created_msg message for bookmark creation
- * @param string $table_html html for the table for displaying sql
- * results
- * @param string $indexes_problems_html html for displaying errors in indexes
- * @param string $bookmark_support_html html for displaying bookmark form
- * @param string $print_button_html html for the print button in printview
+ * @param string $previous_update_query_html html for the previously
+ * executed query
+ * @param string $profiling_chart_html html for profiling
+ * @param PMA_Message $missing_unique_column_msg message for the missing
+ * unique column
+ * @param PMA_Message $bookmark_created_msg message for bookmark creation
+ * @param string $table_html html for the table for
+ * displaying sql results
+ * @param string $indexes_problems_html html for displaying errors
+ * in indexes
+ * @param string $bookmark_support_html html for displaying bookmark form
*
* @return string $html_output
*/
function PMA_getHtmlForSqlQueryResults($previous_update_query_html,
$profiling_chart_html, $missing_unique_column_msg, $bookmark_created_msg,
- $table_html, $indexes_problems_html, $bookmark_support_html, $print_button_html
+ $table_html, $indexes_problems_html, $bookmark_support_html
) {
//begin the sqlqueryresults div here. container div
$html_output = '<div class="sqlqueryresults ajax">';
@@ -1638,7 +1444,6 @@ function PMA_getHtmlForSqlQueryResults($previous_update_query_html,
$html_output .= $table_html;
$html_output .= isset($indexes_problems_html) ? $indexes_problems_html : '';
$html_output .= isset($bookmark_support_html) ? $bookmark_support_html : '';
- $html_output .= isset($print_button_html) ? $print_button_html : '';
$html_output .= '</div>'; // end sqlqueryresults div
return $html_output;
@@ -1730,7 +1535,6 @@ function PMA_getHtmlForSqlQueryResultsTable($displayResultsObject,
'del_lnk' => $displayResultsObject::NO_EDIT_OR_DELETE,
'sort_lnk' => '1',
'nav_bar' => '1',
- 'ins_row' => '0',
'bkm_form' => '1',
'text_btn' => '1',
'pview_lnk' => '1'
@@ -1739,7 +1543,7 @@ function PMA_getHtmlForSqlQueryResultsTable($displayResultsObject,
$table_html .= $displayResultsObject->getTable(
$result,
$displayParts,
- $analyzed_sql_results['analyzed_sql']
+ $analyzed_sql_results
);
}
@@ -1755,17 +1559,29 @@ function PMA_getHtmlForSqlQueryResultsTable($displayResultsObject,
}
$_SESSION['is_multi_query'] = false;
$displayResultsObject->setProperties(
- $unlim_num_rows, $fields_meta, $analyzed_sql_results['is_count'],
- $analyzed_sql_results['is_export'], $analyzed_sql_results['is_func'],
- $analyzed_sql_results['is_analyse'], $num_rows,
- $fields_cnt, $GLOBALS['querytime'], $pmaThemeImage, $GLOBALS['text_dir'],
- $analyzed_sql_results['is_maint'], $analyzed_sql_results['is_explain'],
- $analyzed_sql_results['is_show'], $showtable, $printview, $url_query,
- $editable, $browse_dist
+ $unlim_num_rows,
+ $fields_meta,
+ $analyzed_sql_results['is_count'],
+ $analyzed_sql_results['is_export'],
+ $analyzed_sql_results['is_func'],
+ $analyzed_sql_results['is_analyse'],
+ $num_rows,
+ $fields_cnt, $GLOBALS['querytime'],
+ $pmaThemeImage, $GLOBALS['text_dir'],
+ $analyzed_sql_results['is_maint'],
+ $analyzed_sql_results['is_explain'],
+ $analyzed_sql_results['is_show'],
+ $showtable,
+ $printview,
+ $url_query,
+ $editable,
+ $browse_dist
);
$table_html .= $displayResultsObject->getTable(
- $result, $displayParts, $analyzed_sql_results['analyzed_sql']
+ $result,
+ $displayParts,
+ $analyzed_sql_results
);
$GLOBALS['dbi']->freeResult($result);
}
@@ -1802,20 +1618,35 @@ function PMA_getHtmlForPreviousUpdateQuery($disp_query, $showSql, $sql_data,
/**
* To get the message if a column index is missing. If not will return null
*
- * @param string $table current table
- * @param string $db current database
- * @param boolean $editable whether the results table can be editable or not
+ * @param string $table current table
+ * @param string $db current database
+ * @param boolean $editable whether the results table can be editable or not
+ * @param boolean $has_unique whether there is a unique key
*
* @return PMA_message $message
*/
-function PMA_getMessageIfMissingColumnIndex($table, $db, $editable)
+function PMA_getMessageIfMissingColumnIndex($table, $db, $editable, $has_unique)
{
if (!empty($table) && ($GLOBALS['dbi']->isSystemSchema($db) || !$editable)) {
$missing_unique_column_msg = PMA_message::notice(
- __(
- 'Current selection does not contain a unique column.'
- . ' Grid edit, checkbox, Edit, Copy and Delete features'
- . ' are not available.'
+ sprintf(
+ __(
+ 'Current selection does not contain a unique column.'
+ . ' Grid edit, checkbox, Edit, Copy and Delete features'
+ . ' are not available. %s'
+ ),
+ PMA_Util::showDocu('config', 'cfg_RowActionLinksWithoutUnique')
+ )
+ );
+ } elseif (! empty($table) && ! $has_unique) {
+ $missing_unique_column_msg = PMA_message::notice(
+ sprintf(
+ __(
+ 'Current selection does not contain a unique column.'
+ . ' Grid edit, Edit, Copy and Delete features may result in'
+ . ' undesired behavior. %s'
+ ),
+ PMA_Util::showDocu('config', 'cfg_RowActionLinksWithoutUnique')
)
);
} else {
@@ -1863,26 +1694,9 @@ function PMA_getHtmlForIndexesProblems($query_type, $selectedTables, $db)
}
/**
- * Function to get the html for the print button in printview
- *
- * @return string $print_button_html html for the print button
- */
-function PMA_getHtmlForPrintButton()
-{
- // Do print the page if required
- if (isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
- $print_button_html = PMA_Util::getButton();
- } else {
- $print_button_html = null;
- }
-
- return $print_button_html;
-}
-
-/**
* Function to display results when the executed query returns non empty results
*
- * @param array $result executed query results
+ * @param object $result executed query results
* @param array $analyzed_sql_results analysed sql results
* @param string $db current database
* @param string $table current table
@@ -1892,7 +1706,6 @@ function PMA_getHtmlForPrintButton()
* @param string $pmaThemeImage uri of the theme image
* @param int $unlim_num_rows unlimited number of rows
* @param int $num_rows number of rows
- * @param string $full_sql_query full sql query
* @param string $disp_query display query
* @param string $disp_message display message
* @param array $profiling_results profiling results
@@ -1908,12 +1721,10 @@ function PMA_getHtmlForPrintButton()
*
* @return string html
*/
-function PMA_getQueryResponseForResultsReturned($result,
- $analyzed_sql_results, $db, $table, $message, $sql_data,
- $displayResultsObject, $pmaThemeImage,
- $unlim_num_rows, $num_rows, $full_sql_query, $disp_query,
- $disp_message, $profiling_results, $query_type, $selectedTables, $sql_query,
- $complete_query
+function PMA_getQueryResponseForResultsReturned($result, $analyzed_sql_results,
+ $db, $table, $message, $sql_data, $displayResultsObject, $pmaThemeImage,
+ $unlim_num_rows, $num_rows, $disp_query, $disp_message, $profiling_results,
+ $query_type, $selectedTables, $sql_query, $complete_query
) {
// If we are retrieving the full value of a truncated field or the original
// value of a transformed field, show it here
@@ -1940,10 +1751,17 @@ function PMA_getQueryResponseForResultsReturned($result,
// - if the result set does not contain all the columns of a unique key
// (unless this is an updatable view)
- $sele_exp_cls = $analyzed_sql_results['analyzed_sql'][0]['select_expr_clause'];
- $updatableView
- = trim($sele_exp_cls) == '*'
- && PMA_Table::isUpdatableView($db, $table);
+ $updatableView = false;
+
+ $statement = $analyzed_sql_results['statement'];
+ if ($statement instanceof SqlParser\Statements\SelectStatement) {
+ if (!empty($statement->expr)) {
+ if ($statement->expr[0]->expr === '*') {
+ $_table = new PMA_Table($table, $db);
+ $updatableView = $_table->isUpdatableView();
+ }
+ }
+ }
$has_unique = PMA_resultSetContainsUniqueKey(
$db, $table, $fields_meta
@@ -1951,14 +1769,16 @@ function PMA_getQueryResponseForResultsReturned($result,
$just_one_table = PMA_resultSetHasJustOneTable($fields_meta);
- $editable = ($has_unique || $updatableView) && $just_one_table;
+ $editable = ($has_unique
+ || $GLOBALS['cfg']['RowActionLinksWithoutUnique']
+ || $updatableView)
+ && $just_one_table;
$displayParts = array(
'edit_lnk' => $displayResultsObject::UPDATE_ROW,
'del_lnk' => $displayResultsObject::DELETE_ROW,
'sort_lnk' => '1',
'nav_bar' => '1',
- 'ins_row' => '1',
'bkm_form' => '1',
'text_btn' => '0',
'pview_lnk' => '1'
@@ -1970,20 +1790,18 @@ function PMA_getQueryResponseForResultsReturned($result,
'del_lnk' => $displayResultsObject::NO_EDIT_OR_DELETE,
'sort_lnk' => '1',
'nav_bar' => '1',
- 'ins_row' => '0',
'bkm_form' => '1',
'text_btn' => '1',
'pview_lnk' => '1'
);
}
- if ( isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
+ if (isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
$displayParts = array(
'edit_lnk' => $displayResultsObject::NO_EDIT_OR_DELETE,
'del_lnk' => $displayResultsObject::NO_EDIT_OR_DELETE,
'sort_lnk' => '0',
'nav_bar' => '0',
- 'ins_row' => '0',
'bkm_form' => '0',
'text_btn' => '0',
'pview_lnk' => '0'
@@ -2021,10 +1839,6 @@ function PMA_getQueryResponseForResultsReturned($result,
$GLOBALS['buffer_message'] = false;
}
- $print_view_header_html = PMA_getHtmlForPrintViewHeader(
- $db, $full_sql_query, $num_rows
- );
-
$previous_update_query_html = PMA_getHtmlForPreviousUpdateQuery(
isset($disp_query) ? $disp_query : null,
$GLOBALS['cfg']['ShowSQL'], isset($sql_data) ? $sql_data : null,
@@ -2032,11 +1846,11 @@ function PMA_getQueryResponseForResultsReturned($result,
);
$profiling_chart_html = PMA_getHtmlForProfilingChart(
- $url_query, $db, isset($profiling_results) ? $profiling_results : null
+ $url_query, $db, isset($profiling_results) ? $profiling_results :array()
);
$missing_unique_column_msg = PMA_getMessageIfMissingColumnIndex(
- $table, $db, $editable
+ $table, $db, $editable, $has_unique
);
$bookmark_created_msg = PMA_getBookmarkCreatedMessage();
@@ -2066,17 +1880,12 @@ function PMA_getQueryResponseForResultsReturned($result,
$bookmark_support_html = '';
}
- $print_button_html = PMA_getHtmlForPrintButton();
-
$html_output = isset($table_maintenance_html) ? $table_maintenance_html : '';
- $html_output .= isset($print_view_header_html) ? $print_view_header_html : '';
-
$html_output .= PMA_getHtmlForSqlQueryResults(
$previous_update_query_html, $profiling_chart_html,
$missing_unique_column_msg, $bookmark_created_msg,
- $table_html, $indexes_problems_html, $bookmark_support_html,
- $print_button_html
+ $table_html, $indexes_problems_html, $bookmark_support_html
);
return $html_output;
@@ -2092,7 +1901,6 @@ function PMA_getQueryResponseForResultsReturned($result,
* @param bool|null $find_real_end whether to find real end or not
* @param string $sql_query_for_bookmark the sql query to be stored as bookmark
* @param array|null $extra_data extra data
- * @param bool $is_affected whether affected or not
* @param string $message_to_show message to show
* @param string $message message
* @param array|null $sql_data sql data
@@ -2102,7 +1910,7 @@ function PMA_getQueryResponseForResultsReturned($result,
* @param string $disp_message display message
* @param string $query_type query type
* @param string $sql_query sql query
- * @param array $selectedTables array of table names selected from the
+ * @param array|null $selectedTables array of table names selected from the
* database structure page, for an action
* like check table, optimize table,
* analyze table or repair table
@@ -2112,16 +1920,29 @@ function PMA_getQueryResponseForResultsReturned($result,
*/
function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results,
$is_gotofile, $db, $table, $find_real_end, $sql_query_for_bookmark,
- $extra_data, $is_affected, $message_to_show, $message,
- $sql_data, $goto, $pmaThemeImage, $disp_query, $disp_message,
- $query_type, $sql_query, $selectedTables, $complete_query
+ $extra_data, $message_to_show, $message, $sql_data, $goto, $pmaThemeImage,
+ $disp_query, $disp_message, $query_type, $sql_query, $selectedTables,
+ $complete_query
) {
$html_output = PMA_executeQueryAndGetQueryResponse(
- $analyzed_sql_results, $is_gotofile, $db, $table,
- $find_real_end, $sql_query_for_bookmark,
- $extra_data, $is_affected, $message_to_show, $message,
- $sql_data, $goto, $pmaThemeImage, $disp_query, $disp_message,
- $query_type, $sql_query, $selectedTables, $complete_query
+ $analyzed_sql_results, // analyzed_sql_results
+ $is_gotofile, // is_gotofile
+ $db, // db
+ $table, // table
+ $find_real_end, // find_real_end
+ $sql_query_for_bookmark, // sql_query_for_bookmark
+ $extra_data, // extra_data
+ $message_to_show, // message_to_show
+ $message, // message
+ $sql_data, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ $disp_query, // disp_query
+ $disp_message, // disp_message
+ $query_type, // query_type
+ $sql_query, // sql_query
+ $selectedTables, // selectedTables
+ $complete_query // complete_query
);
$response = PMA_Response::getInstance();
@@ -2138,7 +1959,6 @@ function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results,
* @param bool|null $find_real_end whether to find real end or not
* @param string $sql_query_for_bookmark the sql query to be stored as bookmark
* @param array|null $extra_data extra data
- * @param bool $is_affected whether affected or not
* @param string $message_to_show message to show
* @param string $message message
* @param array|null $sql_data sql data
@@ -2148,7 +1968,7 @@ function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results,
* @param string $disp_message display message
* @param string $query_type query type
* @param string $sql_query sql query
- * @param array $selectedTables array of table names selected from the
+ * @param array|null $selectedTables array of table names selected from the
* database structure page, for an action
* like check table, optimize table,
* analyze table or repair table
@@ -2158,20 +1978,26 @@ function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results,
*/
function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results,
$is_gotofile, $db, $table, $find_real_end, $sql_query_for_bookmark,
- $extra_data, $is_affected, $message_to_show, $message,
- $sql_data, $goto, $pmaThemeImage, $disp_query, $disp_message,
- $query_type, $sql_query, $selectedTables, $complete_query
+ $extra_data, $message_to_show, $message, $sql_data, $goto, $pmaThemeImage,
+ $disp_query, $disp_message, $query_type, $sql_query, $selectedTables,
+ $complete_query
) {
// Include PMA_Index class for use in PMA_DisplayResults class
include_once './libraries/Index.class.php';
include_once 'libraries/DisplayResults.class.php';
- // Handle remembered sorting order, only for single table query
+ // Handle disable/enable foreign key checks
+ $default_fk_check = PMA_Util::handleDisableFKCheckInit();
+
+ // Handle remembered sorting order, only for single table query.
// Handling is not required when it's a union query
- // (the parser never sets the 'union' key to 0)
+ // (the parser never sets the 'union' key to 0).
+ // Handling is also not required if we came from the "Sort by key"
+ // drop-down.
if (PMA_isRememberSortingOrder($analyzed_sql_results)
- && ! isset($analyzed_sql_results['analyzed_sql'][0]['queryflags']['union'])
+ && empty($analyzed_sql_results['union'])
+ && ! isset($_REQUEST['sort_by_key'])
) {
if (! isset($_SESSION['sql_from_query_box'])) {
PMA_handleSortOrder($db, $table, $analyzed_sql_results, $sql_query);
@@ -2191,11 +2017,7 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results,
// Do append a "LIMIT" clause?
if (PMA_isAppendLimitClause($analyzed_sql_results)) {
- $full_sql_query = PMA_getSqlWithLimitClause(
- $analyzed_sql_results['analyzed_sql'],
- ' LIMIT ' . $_SESSION['tmpval']['pos']
- . ', ' . $_SESSION['tmpval']['max_rows'] . " "
- );
+ $full_sql_query = PMA_getSqlWithLimitClause($analyzed_sql_results);
}
$GLOBALS['reload'] = PMA_hasCurrentDbChanged($db);
@@ -2215,7 +2037,9 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results,
);
// No rows returned -> move back to the calling page
- if ((0 == $num_rows && 0 == $unlim_num_rows) || $is_affected) {
+ if ((0 == $num_rows && 0 == $unlim_num_rows)
+ || $analyzed_sql_results['is_affected']
+ ) {
$html_output = PMA_getQueryResponseForNoResultsReturned(
$analyzed_sql_results, $db, $table,
isset($message_to_show) ? $message_to_show : null,
@@ -2234,7 +2058,6 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results,
$pmaThemeImage,
$unlim_num_rows,
$num_rows,
- $full_sql_query,
isset($disp_query) ? $disp_query : null,
isset($disp_message) ? $disp_message : null,
$profiling_results,
@@ -2245,6 +2068,9 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results,
);
}
+ // Handle disable/enable foreign key checks
+ PMA_Util::handleDisableFKCheckCleanup($default_fk_check);
+
return $html_output;
}
@@ -2281,7 +2107,8 @@ function PMA_calculatePosForLastPage($db, $table, $pos)
$pos = $_SESSION['tmpval']['pos'];
}
- $unlim_num_rows = PMA_Table::countRecords($db, $table, true);
+ $_table = new PMA_Table($table, $db);
+ $unlim_num_rows = $_table->countRecords(true);
//If position is higher than number of rows
if ($unlim_num_rows <= $pos && 0 != $pos) {
$pos = PMA_getStartPosToDisplayRow($unlim_num_rows);
@@ -2290,4 +2117,3 @@ function PMA_calculatePosForLastPage($db, $table, $pos)
return $pos;
}
-?>
diff --git a/libraries/sql_query_form.lib.php b/libraries/sql_query_form.lib.php
index 8a48361b71..19a177acab 100644
--- a/libraries/sql_query_form.lib.php
+++ b/libraries/sql_query_form.lib.php
@@ -25,7 +25,7 @@ require_once './libraries/bookmark.lib.php'; // used for bookmarks
*
* @param boolean|string $query query to display in the textarea
* or true to display last executed
- * @param boolean|string $display_tab sql|files|history|full|false
+ * @param boolean|string $display_tab sql|full|false
* what part to display
* false if not inside querywindow
* @param string $delimiter delimiter
@@ -97,13 +97,8 @@ function PMA_getHtmlForSqlQueryForm(
);
}
- // display uploads
- if ($display_tab === 'files' && $GLOBALS['is_upload']) {
- $html .= PMA_getHtmlForSqlQueryFormUpload();
- }
-
// Bookmark Support
- if ($display_tab === 'full' || $display_tab === 'history') {
+ if ($display_tab === 'full') {
$cfgBookmark = PMA_Bookmark_getParams();
if ($cfgBookmark) {
$html .= PMA_getHtmlForSqlQueryFormBookmark();
@@ -124,29 +119,17 @@ function PMA_getHtmlForSqlQueryForm(
}
/**
- * return HTML for Sql Query Form Insert
+ * Get initial values for Sql Query Form Insert
*
- * @param string $query query to display in the textarea
- * @param string $delimiter default delimiter to use
+ * @param string $query query to display in the textarea
*
- * @return string
+ * @return array ($legend, $query, $columns_list)
*
- * @usedby PMA_getHtmlForSqlQueryForm()
+ * @usedby PMA_getHtmlForSqlQueryFormInsert()
*/
-function PMA_getHtmlForSqlQueryFormInsert(
- $query = '', $delimiter = ';'
-) {
- // enable auto select text in textarea
- if ($GLOBALS['cfg']['TextareaAutoSelect']) {
- $auto_sel = ' onclick="selectContent(this, sql_box_locked, true);"';
- } else {
- $auto_sel = '';
- }
-
- $locking = '';
- $height = $GLOBALS['cfg']['TextareaRows'] * 2;
-
- $fields_list = array();
+function PMA_initQueryForm($query)
+{
+ $columns_list = array();
if (! /*overload*/mb_strlen($GLOBALS['db'])) {
// prepare for server related
$legend = sprintf(
@@ -161,12 +144,12 @@ function PMA_getHtmlForSqlQueryFormInsert(
// prepare for db related
$db = $GLOBALS['db'];
// if you want navigation:
- $tmp_db_link = '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
+ $tmp_db_link = '<a href="' . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ )
. PMA_URL_getCommon(array('db' => $db)) . '"';
$tmp_db_link .= '>'
. htmlspecialchars($db) . '</a>';
- // else use
- // $tmp_db_link = htmlspecialchars($db);
$legend = sprintf(__('Run SQL query/queries on database %s'), $tmp_db_link);
if (empty($query)) {
$query = PMA_Util::expandUserString(
@@ -179,16 +162,15 @@ function PMA_getHtmlForSqlQueryFormInsert(
// Get the list and number of fields
// we do a try_query here, because we could be in the query window,
// trying to synchronize and the table has not yet been created
- $fields_list = $GLOBALS['dbi']->getColumns(
+ $columns_list = $GLOBALS['dbi']->getColumns(
$db, $GLOBALS['table'], null, true
);
- $tmp_tbl_link = '<a href="' . $GLOBALS['cfg']['DefaultTabTable']
- . PMA_URL_getCommon(array('db' => $db, 'table' => $table)) . '"';
- $tmp_tbl_link .= '>' . htmlspecialchars($db)
+ $tmp_tbl_link = '<a href="' . PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ ) . PMA_URL_getCommon(array('db' => $db, 'table' => $table)) . '" >';
+ $tmp_tbl_link .= htmlspecialchars($db)
. '.' . htmlspecialchars($table) . '</a>';
- // else use
- // $tmp_db_link = htmlspecialchars($db);
$legend = sprintf(__('Run SQL query/queries on table %s'), $tmp_tbl_link);
if (empty($query)) {
$query = PMA_Util::expandUserString(
@@ -198,7 +180,35 @@ function PMA_getHtmlForSqlQueryFormInsert(
}
$legend .= ': ' . PMA_Util::showMySQLDocu('SELECT');
- if (count($fields_list)) {
+ return array($legend, $query, $columns_list);
+}
+
+/**
+ * return HTML for Sql Query Form Insert
+ *
+ * @param string $query query to display in the textarea
+ * @param string $delimiter default delimiter to use
+ *
+ * @return string
+ *
+ * @usedby PMA_getHtmlForSqlQueryForm()
+ */
+function PMA_getHtmlForSqlQueryFormInsert(
+ $query = '', $delimiter = ';'
+) {
+ // enable auto select text in textarea
+ if ($GLOBALS['cfg']['TextareaAutoSelect']) {
+ $auto_sel = ' onclick="selectContent(this, sql_box_locked, true);"';
+ } else {
+ $auto_sel = '';
+ }
+
+ $locking = '';
+ $height = $GLOBALS['cfg']['TextareaRows'] * 2;
+
+ list($legend, $query, $columns_list) = PMA_initQueryForm($query);
+
+ if (! empty($columns_list)) {
$sqlquerycontainer_id = 'sqlquerycontainer';
} else {
$sqlquerycontainer_id = 'sqlquerycontainerfull';
@@ -213,14 +223,13 @@ function PMA_getHtmlForSqlQueryFormInsert(
. '<textarea tabindex="100" name="sql_query" id="sqlquery"'
. ' cols="' . $GLOBALS['cfg']['TextareaCols'] . '"'
. ' rows="' . $height . '"'
- . ' dir="' . $GLOBALS['text_dir'] . '"'
. $auto_sel . $locking . '>'
. htmlspecialchars($query)
. '</textarea>';
$html .= '<div id="querymessage"></div>';
// Add buttons to generate query easily for
// select all, single select, insert, update and delete
- if (count($fields_list)) {
+ if (! empty($columns_list)) {
$html .= '<input type="button" value="SELECT *" id="selectall"'
. ' class="button sqlbutton" />';
$html .= '<input type="button" value="SELECT" id="select"'
@@ -238,17 +247,26 @@ function PMA_getHtmlForSqlQueryFormInsert(
$html .= '<input type="button" value="' . __('Format') . '" id="format"'
. ' class="button sqlbutton" />';
}
- $html .= '<input type="button" value="' . __('Get auto-saved query') . '" id="saved"'
- . ' class="button sqlbutton" />';
+ $html .= '<input type="button" value="' . __('Get auto-saved query')
+ . '" id="saved" class="button sqlbutton" />';
+
+ // parameter binding
+ $html .= '<div>';
+ $html .= '<input type="checkbox" name="parameterized" id="parameterized" />';
+ $html .= '<label for="parameterized">' . __('Bind parameters') . '</label>';
+ $html .= PMA_Util::showDocu('faq', 'faq6-40');
+ $html .= '<div id="parametersDiv"></div>';
+ $html .= '</div>';
+
$html .= '</div>' . "\n";
- if (count($fields_list)) {
+ if (! empty($columns_list)) {
$html .= '<div id="tablefieldscontainer">'
. '<label>' . __('Columns') . '</label>'
. '<select id="tablefields" name="dummy" '
. 'size="' . ($GLOBALS['cfg']['TextareaRows'] - 2) . '" '
. 'multiple="multiple" ondblclick="insertValueQuery()">';
- foreach ($fields_list as $field) {
+ foreach ($columns_list as $field) {
$html .= '<option value="'
. PMA_Util::backquote(htmlspecialchars($field['Field'])) . '"';
if (isset($field['Field'])
@@ -307,20 +325,24 @@ function PMA_getHtmlForSqlQueryFormInsert(
$html .= '<fieldset id="queryboxfooter" class="tblFooters">' . "\n";
$html .= '<div class="formelement">' . "\n";
-
$html .= '</div>' . "\n";
- $html .= '<div class="formelement">' . "\n";
+
+ $html .= '<div class="formelement">';
$html .= '<label for="id_sql_delimiter">[ ' . __('Delimiter')
. '</label>' . "\n";
$html .= '<input type="text" name="sql_delimiter" tabindex="131" size="3" '
. 'value="' . $delimiter . '" '
. 'id="id_sql_delimiter" /> ]';
+ $html .= '</div>';
+ $html .= '<div class="formelement">';
$html .= '<input type="checkbox" name="show_query" value="1" '
. 'id="checkbox_show_query" tabindex="132" checked="checked" />'
. '<label for="checkbox_show_query">' . __('Show this query here again')
. '</label>';
+ $html .= '</div>';
+ $html .= '<div class="formelement">';
$html .= '<input type="checkbox" name="retain_query_box" value="1" '
. 'id="retain_query_box" tabindex="133" '
. ($GLOBALS['cfg']['RetainQueryBox'] === false
@@ -328,13 +350,20 @@ function PMA_getHtmlForSqlQueryFormInsert(
. ' />'
. '<label for="retain_query_box">' . __('Retain query box')
. '</label>';
+ $html .= '</div>';
+ $html .= '<div class="formelement">';
$html .= '<input type="checkbox" name="rollback_query" value="1" '
. 'id="rollback_query" tabindex="134" />'
. '<label for="rollback_query">' . __('Rollback when finished')
. '</label>';
+ $html .= '</div>';
+
+ // Disable/Enable foreign key checks
+ $html .= '<div class="formelement">';
+ $html .= PMA_Util::getFKCheckbox();
+ $html .= '</div>';
- $html .= '</div>' . "\n";
$html .= '<input type="submit" id="button_submit_query" name="SQL"';
$html .= ' tabindex="200" value="' . __('Go') . '" />' . "\n";
@@ -354,7 +383,7 @@ function PMA_getHtmlForSqlQueryFormInsert(
function PMA_getHtmlForSqlQueryFormBookmark()
{
$bookmark_list = PMA_Bookmark_getList($GLOBALS['db']);
- if (! $bookmark_list || count($bookmark_list) < 1) {
+ if (empty($bookmark_list) || count($bookmark_list) < 1) {
return null;
}
@@ -365,19 +394,15 @@ function PMA_getHtmlForSqlQueryFormBookmark()
$html .= '<select name="id_bookmark" id="id_bookmark">' . "\n";
$html .= '<option value="">&nbsp;</option>' . "\n";
foreach ($bookmark_list as $key => $value) {
- $html .= '<option value="' . htmlspecialchars($key) . '">'
- . htmlspecialchars($value) . '</option>' . "\n";
+ $html .= '<option value="' . htmlspecialchars($key) . '"'
+ . ' data-varcount="' . PMA_Bookmark_getVariableCount($value['query'])
+ . '">'
+ . htmlspecialchars($value['label']) . '</option>' . "\n";
}
// &nbsp; is required for correct display with styles/line height
$html .= '</select>&nbsp;' . "\n";
$html .= '</div>' . "\n";
$html .= '<div class="formelement">' . "\n";
- $html .= __('Variable');
- $html .= PMA_Util::showDocu('faq', 'faqbookmark');
- $html .= '<input type="text" name="bookmark_variable" class="textfield"'
- . ' size="10" />' . "\n";
- $html .= '</div>' . "\n";
- $html .= '<div class="formelement">' . "\n";
$html .= '<input type="radio" name="action_bookmark" value="0"'
. ' id="radio_bookmark_exe" checked="checked" />'
. '<label for="radio_bookmark_exe">' . __('Submit')
@@ -392,6 +417,11 @@ function PMA_getHtmlForSqlQueryFormBookmark()
. '</label>' . "\n";
$html .= '</div>' . "\n";
$html .= '<div class="clearfloat"></div>' . "\n";
+ $html .= '<div class="formelement hide">' . "\n";
+ $html .= __('Variables');
+ $html .= PMA_Util::showDocu('faq', 'faqbookmark');
+ $html .= '<div id="bookmark_variables"></div>';
+ $html .= '</div>' . "\n";
$html .= '</fieldset>' . "\n";
$html .= '<fieldset id="fieldsetBookmarkOptionsFooter" class="tblFooters">';
@@ -402,77 +432,3 @@ function PMA_getHtmlForSqlQueryFormBookmark()
return $html;
}
-
-/**
- * return HTML for Sql Query Form Upload
- *
- * @return string
- *
- * @usedby PMA_getHtmlForSqlQueryForm()
- */
-function PMA_getHtmlForSqlQueryFormUpload()
-{
- global $timeout_passed, $local_import_file;
-
- $errors = array();
-
- // we allow only SQL here
- $matcher = '@\.sql(\.(' . PMA_supportedDecompressions() . '))?$@';
-
- if (!empty($GLOBALS['cfg']['UploadDir'])) {
- $files = PMA_getFileSelectOptions(
- PMA_Util::userDir($GLOBALS['cfg']['UploadDir']), $matcher,
- (isset($timeout_passed) && $timeout_passed && isset($local_import_file))
- ? $local_import_file
- : ''
- );
- } else {
- $files = '';
- }
-
- // start output
- $html = '<fieldset id="">';
- $html .= '<legend>';
- $html .= __('Browse your computer:') . '</legend>';
- $html .= '<div class="formelement">';
- $html .= '<input type="file" name="sql_file" class="textfield" /> ';
- $html .= PMA_Util::getFormattedMaximumUploadSize($GLOBALS['max_upload_size']);
- // some browsers should respect this :)
- $html .= PMA_Util::generateHiddenMaxFileSize($GLOBALS['max_upload_size']) . "\n";
- $html .= '</div>';
-
- if ($files === false) {
- $errors[] = PMA_Message::error(
- __('The directory you set for upload work cannot be reached.')
- );
- } elseif (!empty($files)) {
- $html .= '<div class="formelement">';
- $html .= '<strong>' . __('web server upload directory:') . '</strong>';
- $html .= '<select size="1" name="sql_localfile">' . "\n";
- $html .= '<option value="" selected="selected"></option>' . "\n";
- $html .= $files;
- $html .= '</select>' . "\n";
- $html .= '</div>';
- }
-
- $html .= '<div class="clearfloat"></div>' . "\n";
- $html .= '</fieldset>';
-
- $html .= '<fieldset id="" class="tblFooters">';
- $html .= __('Character set of the file:') . "\n";
- $html .= PMA_generateCharsetDropdownBox(
- PMA_CSDROPDOWN_CHARSET,
- 'charset_of_file', null, 'utf8', false
- );
- $html .= '<input type="submit" name="SQL" value="' . __('Go')
- . '" />' . "\n";
- $html .= '<div class="clearfloat"></div>' . "\n";
- $html .= '</fieldset>';
-
- foreach ($errors as $error) {
- $html .= $error->getDisplay();
- }
-
- return $html;
-}
-?>
diff --git a/libraries/sqlparser.data.php b/libraries/sqlparser.data.php
deleted file mode 100644
index c1379864d6..0000000000
--- a/libraries/sqlparser.data.php
+++ /dev/null
@@ -1,999 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * SQL Parser Matching Data
- *
- * Copyright 2002 Robin Johnson <robbat2@users.sourceforge.net>
- * http://www.orbis-terrarum.net/?l=people.robbat2
- *
- * This data is used by the SQL Parser to recognize keywords
- *
- * It has been extracted from the lex.h file in the MySQL BK tree
- * (around 4.0.2) as well as the MySQL documentation.
- *
- * It's easier to use only uppercase for proper sorting. In case of
- * doubt, use the test case to verify.
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-if (! isset($GLOBALS['sql_delimiter'])) {
- $GLOBALS['sql_delimiter'] = ';';
-}
-
-/**
- * @global array MySQL function names
- */
-$PMA_SQPdata_function_name = array (
- 'ABS',
- 'ACOS',
- 'ADDDATE',
- 'ADDTIME',
- 'AES_DECRYPT',
- 'AES_ENCRYPT',
- 'AREA', // polygon-property-functions.html
- 'ASBINARY',
- 'ASCII',
- 'ASIN',
- 'ASTEXT',
- 'ATAN',
- 'ATAN2',
- 'AVG',
- 'BDMPOLYFROMTEXT',
- 'BDMPOLYFROMWKB',
- 'BDPOLYFROMTEXT',
- 'BDPOLYFROMWKB',
- 'BENCHMARK',
- 'BIN',
- 'BIT_AND',
- 'BIT_COUNT',
- 'BIT_LENGTH',
- 'BIT_OR',
- 'BIT_XOR', // group-by-functions.html
- 'BOUNDARY', // general-geometry-property-functions.html
- 'BUFFER',
- 'CAST',
- 'CEIL',
- 'CEILING',
- 'CENTROID', // multipolygon-property-functions.html
- 'CHAR', // string-functions.html
- 'CHARACTER_LENGTH',
- 'CHARSET', // information-functions.html
- 'CHAR_LENGTH',
- 'COALESCE',
- 'COERCIBILITY', // information-functions.html
- 'COLLATION', // information-functions.html
- 'COMPRESS', // string-functions.html
- 'CONCAT',
- 'CONCAT_WS',
- 'CONNECTION_ID',
- 'CONTAINS',
- 'CONV',
- 'CONVERT',
- 'CONVERT_TZ',
- 'CONVEXHULL',
- 'COS',
- 'COT',
- 'COUNT',
- 'CRC32', // mathematical-functions.html
- 'CROSSES',
- 'CURDATE',
- 'CURRENT_DATE',
- 'CURRENT_TIME',
- 'CURRENT_TIMESTAMP',
- 'CURRENT_USER',
- 'CURTIME',
- 'DATABASE',
- 'DATE', // date-and-time-functions.html
- 'DATEDIFF', // date-and-time-functions.html
- 'DATE_ADD',
- 'DATE_DIFF',
- 'DATE_FORMAT',
- 'DATE_SUB',
- 'DAY',
- 'DAYNAME',
- 'DAYOFMONTH',
- 'DAYOFWEEK',
- 'DAYOFYEAR',
- 'DECODE',
- 'DEFAULT', // miscellaneous-functions.html
- 'DEGREES',
- 'DES_DECRYPT',
- 'DES_ENCRYPT',
- 'DIFFERENCE',
- 'DIMENSION', // general-geometry-property-functions.html
- 'DISJOINT',
- 'DISTANCE',
- 'ELT',
- 'ENCODE',
- 'ENCRYPT',
- 'ENDPOINT', // linestring-property-functions.html
- 'ENVELOPE', // general-geometry-property-functions.html
- 'EQUALS',
- 'EXP',
- 'EXPORT_SET',
- 'EXTERIORRING', // polygon-property-functions.html
- 'EXTRACT',
- 'EXTRACTVALUE', // xml-functions.html
- 'FIELD',
- 'FIND_IN_SET',
- 'FLOOR',
- 'FORMAT',
- 'FOUND_ROWS',
- 'FROM_DAYS',
- 'FROM_UNIXTIME',
- 'GEOMCOLLFROMTEXT',
- 'GEOMCOLLFROMWKB',
- 'GEOMETRYCOLLECTION',
- 'GEOMETRYCOLLECTIONFROMTEXT',
- 'GEOMETRYCOLLECTIONFROMWKB',
- 'GEOMETRYFROMTEXT',
- 'GEOMETRYFROMWKB',
- 'GEOMETRYN', // geometrycollection-property-functions.html
- 'GEOMETRYTYPE', // general-geometry-property-functions.html
- 'GEOMFROMTEXT',
- 'GEOMFROMWKB',
- 'GET_FORMAT',
- 'GET_LOCK',
- 'GLENGTH', // linestring-property-functions.html
- 'GREATEST',
- 'GROUP_CONCAT',
- 'GROUP_UNIQUE_USERS',
- 'HEX',
- 'HOUR',
- 'IF', //control-flow-functions.html
- 'IFNULL',
- 'INET_ATON',
- 'INET_NTOA',
- 'INSERT', // string-functions.html
- 'INSTR',
- 'INTERIORRINGN', // polygon-property-functions.html
- 'INTERSECTION',
- 'INTERSECTS',
- 'INTERVAL',
- 'ISCLOSED', // multilinestring-property-functions.html
- 'ISEMPTY', // general-geometry-property-functions.html
- 'ISNULL',
- 'ISRING', // linestring-property-functions.html
- 'ISSIMPLE', // general-geometry-property-functions.html
- 'IS_FREE_LOCK',
- 'IS_USED_LOCK', // miscellaneous-functions.html
- 'LAST_DAY',
- 'LAST_INSERT_ID',
- 'LCASE',
- 'LEAST',
- 'LEFT',
- 'LENGTH',
- 'LINEFROMTEXT',
- 'LINEFROMWKB',
- 'LINESTRING',
- 'LINESTRINGFROMTEXT',
- 'LINESTRINGFROMWKB',
- 'LN',
- 'LOAD_FILE',
- 'LOCALTIME',
- 'LOCALTIMESTAMP',
- 'LOCATE',
- 'LOG',
- 'LOG10',
- 'LOG2',
- 'LOWER',
- 'LPAD',
- 'LTRIM',
- 'MAKEDATE',
- 'MAKETIME',
- 'MAKE_SET',
- 'MASTER_POS_WAIT',
- 'MAX',
- 'MBRCONTAINS',
- 'MBRDISJOINT',
- 'MBREQUAL',
- 'MBRINTERSECTS',
- 'MBROVERLAPS',
- 'MBRTOUCHES',
- 'MBRWITHIN',
- 'MD5',
- 'MICROSECOND',
- 'MID',
- 'MIN',
- 'MINUTE',
- 'MLINEFROMTEXT',
- 'MLINEFROMWKB',
- 'MOD',
- 'MONTH',
- 'MONTHNAME',
- 'MPOINTFROMTEXT',
- 'MPOINTFROMWKB',
- 'MPOLYFROMTEXT',
- 'MPOLYFROMWKB',
- 'MULTILINESTRING',
- 'MULTILINESTRINGFROMTEXT',
- 'MULTILINESTRINGFROMWKB',
- 'MULTIPOINT',
- 'MULTIPOINTFROMTEXT',
- 'MULTIPOINTFROMWKB',
- 'MULTIPOLYGON',
- 'MULTIPOLYGONFROMTEXT',
- 'MULTIPOLYGONFROMWKB',
- 'NAME_CONST', // NAME_CONST()
- 'NOW',
- 'NULLIF',
- 'NUMGEOMETRIES', // geometrycollection-property-functions.html
- 'NUMINTERIORRINGS', // polygon-property-functions.html
- 'NUMPOINTS', // linestring-property-functions.html
- 'OCT',
- 'OCTET_LENGTH',
- 'OLD_PASSWORD',
- 'ORD',
- 'OVERLAPS',
- 'PASSWORD',
- 'PERIOD_ADD',
- 'PERIOD_DIFF',
- 'PI',
- 'POINT',
- 'POINTFROMTEXT',
- 'POINTFROMWKB',
- 'POINTN', // inestring-property-functions.html
- 'POINTONSURFACE', // multipolygon-property-functions.html
- 'POLYFROMTEXT',
- 'POLYFROMWKB',
- 'POLYGON',
- 'POLYGONFROMTEXT',
- 'POLYGONFROMWKB',
- 'POSITION',
- 'POW',
- 'POWER',
- 'QUARTER',
- 'QUOTE',
- 'RADIANS',
- 'RAND',
- 'RELATED',
- 'RELEASE_LOCK',
- 'REPEAT',
- 'REPLACE', // string-functions.html
- 'REVERSE',
- 'RIGHT',
- 'ROUND',
- 'ROW_COUNT', // information-functions.html
- 'RPAD',
- 'RTRIM',
- 'SCHEMA', // information-functions.html
- 'SECOND',
- 'SEC_TO_TIME',
- 'SESSION_USER',
- 'SHA',
- 'SHA1',
- 'SIGN',
- 'SIN',
- 'SLEEP', // miscellaneous-functions.html
- 'SOUNDEX',
- 'SPACE',
- 'SQRT',
- 'SRID', // general-geometry-property-functions.html
- 'STARTPOINT', // linestring-property-functions.html
- 'STD',
- 'STDDEV',
- 'STDDEV_POP', // group-by-functions.html
- 'STDDEV_SAMP', // group-by-functions.html
- 'STRCMP',
- 'STR_TO_DATE',
- 'SUBDATE',
- 'SUBSTR',
- 'SUBSTRING',
- 'SUBSTRING_INDEX',
- 'SUBTIME',
- 'SUM',
- 'SYMDIFFERENCE',
- 'SYSDATE',
- 'SYSTEM_USER',
- 'TAN',
- 'TIME',
- 'TIMEDIFF',
- 'TIMESTAMP',
- 'TIMESTAMPADD',
- 'TIMESTAMPDIFF',
- 'TIME_FORMAT',
- 'TIME_TO_SEC',
- 'TOUCHES',
- 'TO_DAYS',
- 'TRIM',
- 'TRUNCATE', // mathematical-functions.html
- 'UCASE',
- 'UNCOMPRESS', // string-functions.html
- 'UNCOMPRESSED_LENGTH', // string-functions.html
- 'UNHEX', // string-functions.html
- 'UNIQUE_USERS',
- 'UNIX_TIMESTAMP',
- 'UPDATEXML', // xml-functions.html
- 'UPPER',
- 'USER',
- 'UTC_DATE',
- 'UTC_TIME',
- 'UTC_TIMESTAMP',
- 'UUID', // miscellaneous-functions.html
- 'VARIANCE', // group-by-functions.html
- 'VAR_POP', // group-by-functions.html
- 'VAR_SAMP', // group-by-functions.html
- 'VERSION',
- 'WEEK',
- 'WEEKDAY',
- 'WEEKOFYEAR',
- 'WITHIN',
- 'X', // point-property-functions.html
- 'Y', // point-property-functions.html
- 'YEAR',
- 'YEARWEEK'
-);
-
-/**
- * @global array MySQL attributes
- */
-$PMA_SQPdata_column_attrib = array (
- 'ARCHIVE', // Engine
- 'ASCII',
- 'AUTO_INCREMENT',
- 'BDB', // Engine
- 'BERKELEYDB', // Engine alias BDB
- 'BINARY',
- 'BLACKHOLE', // Engine
- 'CSV', // Engine
- 'DEFAULT',
- 'EXAMPLE', // Engine
- 'FEDERATED', // Engine
- 'HEAP', // Engine
- 'INNOBASE', // Engine alias InnoDB
- 'INNODB', // Engine InnoDB
- 'ISAM', // Engine
- 'MARIA', // Engine
- 'MEMORY', // Engine alias HEAP, but preferred
- 'MERGE', // Engine
- 'MRG_ISAM', // Engine
- 'MRG_MYISAM', // Engine alias MERGE
- 'MYISAM', // Engine MyISAM
- 'NATIONAL',
- 'NDB', // Engine alias NDBCLUSTER
- 'NDBCLUSTER', // Engine
- 'PRECISION',
- 'UNDEFINED',
- 'UNICODE',
- 'UNSIGNED',
- 'VARYING',
- 'ZEROFILL'
-);
-
-/**
- * words that are reserved by MySQL and may not be used as identifiers without
- * quotes
- *
- * @see http://dev.mysql.com/doc/refman/5.5/en/reserved-words.html
- *
- * @global array MySQL reserved words
- */
-$PMA_SQPdata_reserved_word = array (
- 'ACCESSIBLE', // 5.1
- 'ACTION',
- 'ADD',
- 'AFTER',
- 'AGAINST',
- 'AGGREGATE',
- 'ALGORITHM',
- 'ALL',
- 'ALTER',
- 'ANALYSE',
- 'ANALYZE',
- 'AND',
- 'AS',
- 'ASC',
- 'AUTOCOMMIT',
- 'AUTO_INCREMENT',
- 'AVG_ROW_LENGTH',
- 'BACKUP',
- 'BEFORE',
- 'BEGIN',
- 'BETWEEN',
- 'BINLOG',
- 'BOTH',
- 'BY',
- 'CALL',
- 'CASCADE',
- 'CASE',
- 'CHANGE',
- 'CHANGED',
- 'CHARSET',
- 'CHECK',
- 'CHECKSUM',
- 'COLLATE',
- 'COLLATION',
- 'COLUMN',
- 'COLUMNS',
- 'COMMENT',
- 'COMMIT',
- 'COMMITTED',
- 'COMPRESSED',
- 'CONCURRENT',
- 'CONSTRAINT',
- 'CONTAINS',
- 'CONVERT',
- 'CREATE',
- 'CROSS',
- 'CURRENT_TIMESTAMP',
- 'DATABASE',
- 'DATABASES',
- 'DAY',
- 'DAY_HOUR',
- 'DAY_MINUTE',
- 'DAY_SECOND',
- 'DECLARE',
- 'DEFINER',
- 'DELAYED',
- 'DELAY_KEY_WRITE',
- 'DELETE',
- 'DESC',
- 'DESCRIBE',
- 'DETERMINISTIC',
- 'DISTINCT',
- 'DISTINCTROW',
- 'DIV',
- 'DO',
- 'DROP',
- 'DUMPFILE',
- 'DUPLICATE',
- 'DYNAMIC',
- 'EACH',
- 'ELSE',
- 'ELSEIF',
- 'ENCLOSED',
- 'END',
- 'ENGINE',
- 'ENGINES',
- 'ESCAPE',
- 'ESCAPED',
- 'EVENTS',
- 'EXECUTE',
- 'EXISTS',
- 'EXIT',
- 'EXPLAIN',
- 'EXTENDED',
- 'FALSE',
- 'FAST',
- 'FIELDS',
- 'FILE',
- 'FIRST',
- 'FIXED',
- 'FLUSH',
- 'FOR',
- 'FORCE',
- 'FOREIGN',
- 'FROM',
- 'FULL',
- 'FULLTEXT',
- 'FUNCTION',
- 'GEMINI',
- 'GEMINI_SPIN_RETRIES',
- 'GENERAL',
- 'GLOBAL',
- 'GRANT',
- 'GRANTS',
- 'GROUP',
- 'HAVING',
- 'HEAP',
- 'HIGH_PRIORITY',
- 'HOSTS',
- 'HOUR',
- 'HOUR_MINUTE',
- 'HOUR_SECOND',
- 'IDENTIFIED',
- 'IF',
- 'IGNORE',
- 'IGNORE_SERVER_IDS',
- 'IN',
- 'INDEX',
- 'INDEXES',
- 'INFILE',
- 'INNER',
- 'INOUT',
- 'INSERT',
- 'INSERT_ID',
- 'INSERT_METHOD',
- 'INTERVAL',
- 'INTO',
- 'INVOKER',
- 'IS',
- 'ISOLATION',
- 'JOIN',
- 'KEY',
- 'KEYS',
- 'KILL',
- 'LAST_INSERT_ID',
- 'LEADING',
- 'LEFT',
- 'LIKE',
- 'LIMIT',
- 'LINEAR', // 5.1
- 'LINES',
- 'LOAD',
- 'LOCAL',
- 'LOCK',
- 'LOCKS',
- 'LOGS',
- 'LOW_PRIORITY',
- 'MARIA', // 5.1 ?
- 'MASTER_CONNECT_RETRY',
- 'MASTER_HEARTBEAT_PERIOD',
- 'MASTER_HOST',
- 'MASTER_LOG_FILE',
- 'MASTER_LOG_POS',
- 'MASTER_PASSWORD',
- 'MASTER_PORT',
- 'MASTER_USER',
- 'MATCH',
- 'MAXVALUE',
- 'MAX_CONNECTIONS_PER_HOUR',
- 'MAX_QUERIES_PER_HOUR',
- 'MAX_ROWS',
- 'MAX_UPDATES_PER_HOUR',
- 'MAX_USER_CONNECTIONS',
- 'MEDIUM',
- 'MERGE',
- 'MINUTE',
- 'MINUTE_SECOND',
- 'MIN_ROWS',
- 'MODE',
- 'MODIFIES',
- 'MODIFY',
- 'MONTH',
- 'MRG_MYISAM',
- 'MYISAM',
- 'NAMES',
- 'NATURAL',
- // 'NO' is not allowed in SQL-99 but is allowed in MySQL
- //'NO',
- 'NOT',
- 'NULL',
- 'OFFSET',
- 'ON',
- 'OPEN',
- 'OPTIMIZE',
- 'OPTION',
- 'OPTIONALLY',
- 'OR',
- 'ORDER',
- 'OUT',
- 'OUTER',
- 'OUTFILE',
- 'PACK_KEYS',
- 'PAGE', // 5.1-maria ?
- 'PAGE_CHECKSUM', // 5.1
- 'PARTIAL',
- 'PARTITION', // 5.1
- 'PARTITIONS', // 5.1
- 'PASSWORD',
- 'PRIMARY',
- 'PRIVILEGES',
- 'PROCEDURE',
- 'PROCESS',
- 'PROCESSLIST',
- 'PURGE',
- 'QUICK',
- 'RAID0',
- 'RAID_CHUNKS',
- 'RAID_CHUNKSIZE',
- 'RAID_TYPE',
- 'RANGE', // 5.1
- 'READ',
- 'READS',
- 'READ_ONLY', // 5.1
- 'READ_WRITE', // 5.1
- 'REFERENCES',
- 'REGEXP',
- 'RELOAD',
- 'RENAME',
- 'REPAIR',
- 'REPEATABLE',
- 'REPLACE',
- 'REPLICATION',
- 'RESET',
- 'RESIGNAL',
- 'RESTORE',
- 'RESTRICT',
- 'RETURN',
- 'RETURNS',
- 'REVOKE',
- 'RIGHT',
- 'RLIKE',
- 'ROLLBACK',
- 'ROW',
- 'ROWS',
- 'ROW_FORMAT',
- 'SECOND',
- 'SECURITY',
- 'SELECT',
- 'SEPARATOR',
- 'SERIALIZABLE',
- 'SESSION',
- 'SHARE',
- 'SHOW',
- 'SHUTDOWN',
- 'SIGNAL',
- 'SLAVE',
- 'SLOW',
- 'SONAME',
- 'SOUNDS', // string-functions.html
- 'SQL',
- 'SQL_AUTO_IS_NULL',
- 'SQL_BIG_RESULT',
- 'SQL_BIG_SELECTS',
- 'SQL_BIG_TABLES',
- 'SQL_BUFFER_RESULT',
- 'SQL_CACHE',
- 'SQL_CALC_FOUND_ROWS',
- 'SQL_LOG_BIN',
- 'SQL_LOG_OFF',
- 'SQL_LOG_UPDATE',
- 'SQL_LOW_PRIORITY_UPDATES',
- 'SQL_MAX_JOIN_SIZE',
- 'SQL_NO_CACHE',
- 'SQL_QUOTE_SHOW_CREATE',
- 'SQL_SAFE_UPDATES',
- 'SQL_SELECT_LIMIT',
- 'SQL_SLAVE_SKIP_COUNTER',
- 'SQL_SMALL_RESULT',
- 'SQL_WARNINGS',
- 'START',
- 'STARTING',
- 'STATUS',
- 'STOP',
- 'STORAGE',
- 'STRAIGHT_JOIN',
- 'STRING',
- 'STRIPED',
- 'SUPER',
- 'TABLE',
- 'TABLES',
- 'TEMPORARY',
- 'TERMINATED',
- 'THEN',
- 'TO',
- 'TRAILING',
- 'TRANSACTIONAL', // 5.1 ?
- 'TRIGGER',
- 'TRUE',
- 'TRUNCATE',
- 'TYPE',
- 'TYPES',
- 'UNCOMMITTED',
- 'UNION',
- 'UNIQUE',
- 'UNLOCK',
- 'UPDATE',
- 'USAGE',
- 'USE',
- 'USING',
- 'VALUES',
- 'VARIABLES',
- 'VIEW',
- 'WHEN',
- 'WHERE',
- 'WITH',
- 'WORK',
- 'WRITE',
- 'XOR',
- 'YEAR_MONTH'
-);
-
-/**
- * words forbidden to be used as column or table name without quotes
- * as seen in http://dev.mysql.com/doc/refman/5.6/en/reserved-words.html
- *
- * @global array MySQL forbidden words
- */
-$PMA_SQPdata_forbidden_word = array (
- 'ACCESSIBLE',
- 'ADD',
- 'ALL',
- 'ALTER',
- 'ANALYZE',
- 'AND',
- 'AS',
- 'ASC',
- 'ASENSITIVE',
- 'BEFORE',
- 'BETWEEN',
- 'BIGINT',
- 'BINARY',
- 'BLOB',
- 'BOTH',
- 'BY',
- 'CALL',
- 'CASCADE',
- 'CASE',
- 'CHANGE',
- 'CHAR',
- 'CHARACTER',
- 'CHECK',
- 'COLLATE',
- 'COLUMN',
- 'CONDITION',
- 'CONSTRAINT',
- 'CONTINUE',
- 'CONVERT',
- 'CREATE',
- 'CROSS',
- 'CURRENT_DATE',
- 'CURRENT_TIME',
- 'CURRENT_TIMESTAMP',
- 'CURRENT_USER',
- 'CURSOR',
- 'DATABASE',
- 'DATABASES',
- 'DAY_HOUR',
- 'DAY_MICROSECOND',
- 'DAY_MINUTE',
- 'DAY_SECOND',
- 'DEC',
- 'DECIMAL',
- 'DECLARE',
- 'DEFAULT',
- 'DELAYED',
- 'DELETE',
- 'DESC',
- 'DESCRIBE',
- 'DETERMINISTIC',
- 'DISTINCT',
- 'DISTINCTROW',
- 'DIV',
- 'DOUBLE',
- 'DROP',
- 'DUAL',
- 'EACH',
- 'ELSE',
- 'ELSEIF',
- 'ENCLOSED',
- 'ESCAPED',
- 'EXISTS',
- 'EXIT',
- 'EXPLAIN',
- 'FALSE',
- 'FETCH',
- 'FLOAT',
- 'FLOAT4',
- 'FLOAT8',
- 'FOR',
- 'FORCE',
- 'FOREIGN',
- 'FROM',
- 'FULLTEXT',
- 'GENERAL',
- 'GET',
- 'GRANT',
- 'GROUP',
- 'HAVING',
- 'HIGH_PRIORITY',
- 'HOUR_MICROSECOND',
- 'HOUR_MINUTE',
- 'HOUR_SECOND',
- 'IF',
- 'IGNORE',
- 'IGNORE_SERVER_IDS',
- 'IN',
- 'INDEX',
- 'INFILE',
- 'INNER',
- 'INOUT',
- 'INSENSITIVE',
- 'INSERT',
- 'INT',
- 'INT1',
- 'INT2',
- 'INT3',
- 'INT4',
- 'INT8',
- 'INTEGER',
- 'INTERVAL',
- 'INTO',
- 'IO_AFTER_GTIDS',
- 'IO_BEFORE_GTIDS',
- 'IS',
- 'ITERATE',
- 'JOIN',
- 'KEY',
- 'KEYS',
- 'KILL',
- 'LEADING',
- 'LEAVE',
- 'LEFT',
- 'LIKE',
- 'LIMIT',
- 'LINEAR',
- 'LINES',
- 'LOAD',
- 'LOCALTIME',
- 'LOCALTIMESTAMP',
- 'LOCK',
- 'LONG',
- 'LONGBLOB',
- 'LONGTEXT',
- 'LOOP',
- 'LOW_PRIORITY',
- 'MASTER_BIND',
- 'MASTER_HEARTBEAT_PERIOD',
- 'MASTER_SSL_VERIFY_SERVER_CERT',
- 'MATCH',
- 'MAXVALUE',
- 'MEDIUMBLOB',
- 'MEDIUMINT',
- 'MEDIUMTEXT',
- 'MIDDLEINT',
- 'MINUTE_MICROSECOND',
- 'MINUTE_SECOND',
- 'MOD',
- 'MODIFIES',
- 'NATURAL',
- 'NOT',
- 'NO_WRITE_TO_BINLOG',
- 'NULL',
- 'NUMERIC',
- 'ON',
- 'ONE_SHOT',
- 'OPTIMIZE',
- 'OPTION',
- 'OPTIONALLY',
- 'OR',
- 'ORDER',
- 'OUT',
- 'OUTER',
- 'OUTFILE',
- 'PARTITION',
- 'PRECISION',
- 'PRIMARY',
- 'PROCEDURE',
- 'PURGE',
- 'RANGE',
- 'READ',
- 'READS',
- 'READ_WRITE',
- 'REAL',
- 'REFERENCES',
- 'REGEXP',
- 'RELEASE',
- 'RENAME',
- 'REPEAT',
- 'REPLACE',
- 'REQUIRE',
- 'RESIGNAL',
- 'RESTRICT',
- 'RETURN',
- 'REVOKE',
- 'RIGHT',
- 'RLIKE',
- 'SCHEMA',
- 'SCHEMAS',
- 'SECOND_MICROSECOND',
- 'SELECT',
- 'SENSITIVE',
- 'SEPARATOR',
- 'SET',
- 'SHOW',
- 'SIGNAL',
- 'SLOW',
- 'SMALLINT',
- 'SPATIAL',
- 'SPECIFIC',
- 'SQL',
- 'SQLEXCEPTION',
- 'SQLSTATE',
- 'SQLWARNING',
- 'SQL_AFTER_GTIDS',
- 'SQL_BEFORE_GTIDS',
- 'SQL_BIG_RESULT',
- 'SQL_CALC_FOUND_ROWS',
- 'SQL_SMALL_RESULT',
- 'SSL',
- 'STARTING',
- 'STRAIGHT_JOIN',
- 'TABLE',
- 'TERMINATED',
- 'THEN',
- 'TINYBLOB',
- 'TINYINT',
- 'TINYTEXT',
- 'TO',
- 'TRAILING',
- 'TRIGGER',
- 'TRUE',
- 'UNDO',
- 'UNION',
- 'UNIQUE',
- 'UNLOCK',
- 'UNSIGNED',
- 'UPDATE',
- 'USAGE',
- 'USE',
- 'USING',
- 'UTC_DATE',
- 'UTC_TIME',
- 'UTC_TIMESTAMP',
- 'VALUES',
- 'VARBINARY',
- 'VARCHAR',
- 'VARCHARACTER',
- 'VARYING',
- 'WHEN',
- 'WHERE',
- 'WHILE',
- 'WITH',
- 'WRITE',
- 'XOR',
- 'YEAR_MONTH',
- 'ZEROFILL'
-);
-
-/**
- * the MySQL column/data types
- *
- * @see http://dev.mysql.com/doc/refman/5.1/en/data-types.html
- * @see http://dev.mysql.com/doc/refman/5.1/en/mysql-spatial-datatypes.html
- *
- * @global array MySQL column types
- */
-$PMA_SQPdata_column_type = array (
- 'BIGINT',
- 'BINARY',
- 'BIT',
- 'BLOB',
- 'BOOL',
- 'BOOLEAN', // numeric-type-overview.html
- 'CHAR',
- 'CHARACTER',
- 'DATE',
- 'DATETIME',
- 'DEC',
- 'DECIMAL',
- 'DOUBLE',
- 'ENUM',
- 'FLOAT',
- 'FLOAT4',
- 'FLOAT8',
- 'GEOMETRY', // spatial
- 'GEOMETRYCOLLECTION', // spatial
- 'INT',
- 'INT1',
- 'INT2',
- 'INT3',
- 'INT4',
- 'INT8',
- 'INTEGER',
- 'LINESTRING', // spatial
- 'LONG',
- 'LONGBLOB',
- 'LONGTEXT',
- 'MEDIUMBLOB',
- 'MEDIUMINT',
- 'MEDIUMTEXT',
- 'MIDDLEINT',
- 'MULTILINESTRING', // spatial
- 'MULTIPOINT', // spatial
- 'MULTIPOLYGON', // spatial
- 'NCHAR',
- 'NUMERIC',
- 'POINT', // spatial
- 'POLYGON', // spatial
- 'REAL',
- 'SERIAL', // alias
- 'SET',
- 'SMALLINT',
- 'TEXT',
- 'TIME',
- 'TIMESTAMP',
- 'TINYBLOB',
- 'TINYINT',
- 'TINYTEXT',
- 'VARBINARY',
- 'VARCHAR',
- 'YEAR'
-);
-
-?>
diff --git a/libraries/sqlparser.lib.php b/libraries/sqlparser.lib.php
deleted file mode 100644
index d9df780665..0000000000
--- a/libraries/sqlparser.lib.php
+++ /dev/null
@@ -1,2997 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/** SQL Parser Functions for phpMyAdmin
- *
- * These functions define an SQL parser system, capable of understanding and
- * extracting data from a MySQL type SQL query.
- *
- * The basic procedure for using the new SQL parser:
- * On any page that needs to extract data from a query or to pretty-print a
- * query, you need code like this up at the top:
- *
- * ($sql contains the query)
- * $parsed_sql = PMA_SQP_parse($sql);
- *
- * If you want to extract data from it then, you just need to run
- * $sql_info = PMA_SQP_analyze($parsed_sql);
- *
- * See comments in PMA_SQP_analyze for the returned info
- * from the analyzer.
- *
- * If you want a pretty-printed version of the query, do:
- * $string = PMA_SQP_format($parsed_sql);
- * (note that that you need to have syntax.css.php included somehow in your
- * page for it to work, I recommend '<link rel="stylesheet" type="text/css"
- * href="syntax.css.php" />' at the moment.)
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Include data for the SQL Parser
- */
-require_once './libraries/sqlparser.data.php';
-
-/**
- * Charset information
- */
-if (!defined('TESTSUITE') && ! PMA_DRIZZLE) {
- include_once './libraries/mysql_charsets.inc.php';
-}
-if (! isset($mysql_charsets)) {
- $mysql_charsets = array();
- $mysql_collations_flat = array();
-}
-
-/**
- * Stores parsed elements of query to array.
- *
- * @param array &$arr Array to store element
- * @param string $type Type of element
- * @param string $data Data (text) of element
- * @param int &$arrsize Size of array
- * @param int $pos Position of an element
- *
- * @return void
- */
-function PMA_SQP_arrayAdd(&$arr, $type, $data, &$arrsize, $pos = 0)
-{
- $arr[] = array('type' => $type, 'data' => $data, 'pos' => $pos);
- $arrsize++;
-} // end of the "PMA_SQP_arrayAdd()" function
-
-/**
- * Reset the error variable for the SQL parser
- *
- * @access public
- *
- * @return void
- */
-function PMA_SQP_resetError()
-{
- global $SQP_errorString;
- $SQP_errorString = '';
- unset($SQP_errorString);
-}
-
-/**
- * Get the contents of the error variable for the SQL parser
- *
- * @return string Error string from SQL parser
- *
- * @access public
- */
-function PMA_SQP_getErrorString()
-{
- global $SQP_errorString;
- return isset($SQP_errorString) ? $SQP_errorString : '';
-}
-
-/**
- * Check if the SQL parser hit an error
- *
- * @return boolean error state
- *
- * @access public
- */
-function PMA_SQP_isError()
-{
- global $SQP_errorString;
- return isset($SQP_errorString) && !empty($SQP_errorString);
-}
-
-/**
- * Set an error message for the system
- *
- * @param string $message The error message
- * @param string $sql The failing SQL query
- *
- * @return void
- *
- * @access private
- * @scope SQL Parser internal
- */
-function PMA_SQP_throwError($message, $sql)
-{
- global $SQP_errorString;
- $SQP_errorString = '<p>'
- . __(
- 'There seems to be an error in your SQL query. The MySQL server '
- . 'error output below, if there is any, may also help you in '
- . 'diagnosing the problem.'
- )
- . '</p>' . "\n"
- . '<pre>' . "\n"
- . 'ERROR: ' . $message . "\n"
- . 'SQL: ' . htmlspecialchars($sql) . "\n"
- . '</pre>' . "\n";
-
-} // end of the "PMA_SQP_throwError()" function
-
-
-/**
- * Do display the bug report
- *
- * @param string $message The error message
- * @param string $sql The failing SQL query
- *
- * @return void
- *
- * @access public
- */
-function PMA_SQP_bug($message, $sql)
-{
- global $SQP_errorString;
- $debugstr = 'ERROR: ' . $message . "\n";
- $debugstr .= 'MySQL: ' . PMA_MYSQL_STR_VERSION . "\n";
- $debugstr .= 'USR OS, AGENT, VER: ' . PMA_USR_OS . ' ';
- $debugstr .= PMA_USR_BROWSER_AGENT . ' ' . PMA_USR_BROWSER_VER . "\n";
- $debugstr .= 'PMA: ' . PMA_VERSION . "\n";
- $debugstr .= 'PHP VER,OS: ' . PMA_PHP_STR_VERSION . ' ' . PHP_OS . "\n";
- $debugstr .= 'LANG: ' . $GLOBALS['lang'] . "\n";
- $debugstr .= 'SQL: ' . htmlspecialchars($sql);
-
- $encodedstr = $debugstr;
- if (@function_exists('gzcompress')) {
- $encodedstr = gzcompress($debugstr, 9);
- }
- $encodedstr = preg_replace(
- "/(\015\012)|(\015)|(\012)/",
- '<br />' . "\n",
- chunk_split(base64_encode($encodedstr))
- );
-
- $SQP_errorString .= __(
- 'There is a chance that you may have found a bug in the SQL parser. '
- . 'Please examine your query closely, and check that the quotes are '
- . 'correct and not mis-matched. Other possible failure causes may be '
- . 'that you are uploading a file with binary outside of a quoted text '
- . 'area. You can also try your query on the MySQL command line '
- . 'interface. The MySQL server error output below, if there is any, '
- . 'may also help you in diagnosing the problem. If you still have '
- . 'problems or if the parser fails where the command line interface '
- . 'succeeds, please reduce your SQL query input to the single query '
- . 'that causes problems, and submit a bug report with the data chunk '
- . 'in the CUT section below:'
- );
- $SQP_errorString .= '<br />' . "\n"
- . '----' . __('BEGIN CUT') . '----' . '<br />' . "\n"
- . $encodedstr . "\n"
- . '----' . __('END CUT') . '----' . '<br />' . "\n";
-
- $SQP_errorString .= '----' . __('BEGIN RAW') . '----<br />' . "\n"
- . '<pre>' . "\n"
- . $debugstr
- . '</pre>' . "\n"
- . '----' . __('END RAW') . '----<br />' . "\n";
-
-} // end of the "PMA_SQP_bug()" function
-
-
-/**
- * Parses the SQL queries
- *
- * @param string $sql The SQL query list
- *
- * @return mixed Most of times, nothing...
- *
- * @global array The current PMA configuration
- * @global array MySQL column attributes
- * @global array MySQL reserved words
- * @global array MySQL column types
- * @global array MySQL function names
- * @global array List of available character sets
- * @global array List of available collations
- *
- * @access public
- */
-function PMA_SQP_parse($sql)
-{
- static $PMA_SQPdata_column_attrib, $PMA_SQPdata_reserved_word;
- static $PMA_SQPdata_column_type;
- static $PMA_SQPdata_function_name, $PMA_SQPdata_forbidden_word;
- global $mysql_charsets, $mysql_collations_flat;
-
- /** @var PMA_String $pmaString */
- $pmaString = $GLOBALS['PMA_String'];
-
- // Convert all line feeds to Unix style
- $sql = str_replace("\r\n", "\n", $sql);
- $sql = str_replace("\r", "\n", $sql);
-
- $len = /*overload*/mb_strlen($sql);
- if ($len == 0) {
- return array();
- }
-
- // Create local hashtables
- if (!isset($PMA_SQPdata_column_attrib)) {
- $PMA_SQPdata_column_attrib = array_flip(
- $GLOBALS['PMA_SQPdata_column_attrib']
- );
- $PMA_SQPdata_function_name = array_flip(
- $GLOBALS['PMA_SQPdata_function_name']
- );
- $PMA_SQPdata_reserved_word = array_flip(
- $GLOBALS['PMA_SQPdata_reserved_word']
- );
- $PMA_SQPdata_forbidden_word = array_flip(
- $GLOBALS['PMA_SQPdata_forbidden_word']
- );
- $PMA_SQPdata_column_type = array_flip(
- $GLOBALS['PMA_SQPdata_column_type']
- );
- }
-
- $sql_array = array();
- $sql_array['raw'] = $sql;
- $count2 = 0;
- $punct_queryend = ';';
- $punct_qualifier = '.';
- $punct_listsep = ',';
- $bracket_list = '()[]{}';
- $allpunct_list = '-,;:!?/.^~\*&%+<=>|';
- $allpunct_list_pair = array(
- '!=' => 1,
- '&&' => 1,
- ':=' => 1,
- '<<' => 1,
- '<=' => 1,
- '<=>' => 1,
- '<>' => 1,
- '>=' => 1,
- '>>' => 1,
- '||' => 1,
- '==' => 1
- );
- $quote_list = '\'"`';
- $arraysize = 0;
-
- $this_was_space = false;
- $this_was_bracket = false;
- $this_was_punct = false;
- $this_was_listsep = false;
- $this_was_quote = false;
-
- while ($count2 < $len) {
- $c = /*overload*/mb_substr($sql, $count2, 1);
- $count1 = $count2;
-
- $previous_was_space = $this_was_space;
- $this_was_space = false;
- $previous_was_bracket = $this_was_bracket;
- $this_was_bracket = false;
- $previous_was_punct = $this_was_punct;
- $this_was_punct = false;
- $previous_was_listsep = $this_was_listsep;
- $this_was_listsep = false;
- $previous_was_quote = $this_was_quote;
- $this_was_quote = false;
-
- if (($c === "\n")) {
- $this_was_space = true;
- $count2++;
- PMA_SQP_arrayAdd($sql_array, 'white_newline', "\n", $arraysize, $count2);
- continue;
- }
-
- // Checks for white space
- if ($pmaString->isSpace($c)) {
- $this_was_space = true;
- $count2++;
- continue;
- }
-
- // Checks for comment lines.
- // MySQL style #
- // C style /* */
- // ANSI style --
- $next_c = /*overload*/mb_substr($sql, $count2 + 1, 1);
- if (($c == '#')
- || (($count2 + 1 < $len) && ($c == '/') && ($next_c == '*'))
- || (($count2 + 2 == $len) && ($c == '-') && ($next_c == '-'))
- || (($count2 + 2 < $len) && ($c == '-') && ($next_c == '-')
- && ((/*overload*/mb_substr($sql, $count2 + 2, 1) <= ' ')))
- ) {
- $count2++;
- $pos = 0;
- $type = 'bad';
- switch ($c) {
- case '#':
- $type = 'mysql';
- $pos = /*overload*/mb_strpos($sql, "\n", $count2);
- break;
- case '-':
- $type = 'ansi';
- $pos = /*overload*/mb_strpos($sql, "\n", $count2);
- break;
- case '/':
- $type = 'c';
- $pos = /*overload*/mb_strpos($sql, '*/', $count2);
- $pos += 2;
- break;
- default:
- break;
- } // end switch
- $count2 = ($pos < $count2) ? $len : $pos;
- $str = /*overload*/mb_substr(
- $sql, $count1, $count2 - $count1
- );
- PMA_SQP_arrayAdd(
- $sql_array, 'comment_' . $type, $str, $arraysize, $count2
- );
- continue;
- } // end if
-
- // Checks for something inside quotation marks
- if (/*overload*/mb_strpos($quote_list, $c) !== false) {
- $startquotepos = $count2;
- $quotetype = $c;
- $count2++;
- $pos = $count2;
- do {
- $oldpos = $pos;
- $pos = /*overload*/mb_strpos(
- ' ' . $sql, $quotetype, $oldpos + 1
- ) - 1;
- // ($pos === false)
- if ($pos < 0) {
- if ($c != '`') {
- $debugstr = __('Unclosed quote')
- . ' @ ' . $startquotepos . "\n"
- . 'STR: ' . htmlspecialchars($quotetype);
- PMA_SQP_throwError($debugstr, $sql);
- return $sql_array;
- }
-
- /*
- * Behave same as MySQL and accept end of query as end
- * of backtick.
- * I know this is sick, but MySQL behaves like this:
- *
- * SELECT * FROM `table
- *
- * is treated like
- *
- * SELECT * FROM `table`
- */
- $pos_quote_separator = /*overload*/mb_strpos(
- ' ' . $sql, $GLOBALS['sql_delimiter'], $oldpos + 1
- ) - 1;
- if ($pos_quote_separator < 0) {
- $len += 1;
- $sql .= '`';
- $sql_array['raw'] .= '`';
- $pos = $len;
- } else {
- $len += 1;
- $sql = /*overload*/mb_substr(
- $sql, 0, $pos_quote_separator
- ) . '`' . /*overload*/mb_substr(
- $sql, $pos_quote_separator
- );
- $sql_array['raw'] = $sql;
- $pos = $pos_quote_separator;
- }
- if (class_exists('PMA_Message')
- && $GLOBALS['is_ajax_request'] != true
- ) {
- PMA_Message::notice(
- __('Automatically appended backtick to the end of query!')
- )->display();
- }
- }
-
- // If the quote is the first character, it can't be
- // escaped, so don't do the rest of the code
- if ($pos == 0) {
- break;
- }
-
- // Checks for MySQL escaping using a \
- // And checks for ANSI escaping using the $quotetype character
- if (($pos < $len)
- && $pmaString->charIsEscaped($sql, $pos)
- && $c != '`'
- ) {
- $pos ++;
- continue;
- } elseif (($pos + 1 < $len)
- && (/*overload*/mb_substr($sql, $pos, 1) == $quotetype)
- && (/*overload*/mb_substr($sql, $pos + 1, 1) == $quotetype)
- ) {
- $pos = $pos + 2;
- continue;
- } else {
- break;
- }
- } while ($len > $pos); // end do
-
- $count2 = $pos;
- $count2++;
- $type = 'quote_';
- switch ($quotetype) {
- case '\'':
- $type .= 'single';
- $this_was_quote = true;
- break;
- case '"':
- $type .= 'double';
- $this_was_quote = true;
- break;
- case '`':
- $type .= 'backtick';
- $this_was_quote = true;
- break;
- default:
- break;
- } // end switch
- $data = /*overload*/mb_substr($sql, $count1, $count2 - $count1);
- PMA_SQP_arrayAdd($sql_array, $type, $data, $arraysize, $count2);
- continue;
- }
-
- // Checks for brackets
- if (/*overload*/mb_strpos($bracket_list, $c) !== false) {
- // All bracket tokens are only one item long
- $this_was_bracket = true;
- $count2++;
- if (/*overload*/mb_strpos('([{', $c) !== false) {
- $type_type = 'open';
- } else {
- $type_type = 'close';
- }
-
- if (/*overload*/mb_strpos('()', $c) !== false) {
- $type_style = 'round';
- } elseif (/*overload*/mb_strpos('[]', $c) !== false) {
- $type_style = 'square';
- } else {
- $type_style = 'curly';
- }
-
- $type = 'punct_bracket_' . $type_type . '_' . $type_style;
- PMA_SQP_arrayAdd($sql_array, $type, $c, $arraysize, $count2);
- continue;
- }
-
- /* DEBUG
- echo '<pre>1';
- var_dump($pmaString->isSqlIdentifier($c, false));
- var_dump($c == '@');
- var_dump($c == '.');
- var_dump(
- $pmaString->isDigit(
- $pmaString->substr($sql, $count2 + 1, 1)
- )
- );
- var_dump($previous_was_space);
- var_dump($previous_was_bracket);
- var_dump($previous_was_listsep);
- echo '</pre>';
- */
-
- // Checks for identifier (alpha or numeric)
- if ($pmaString->isSqlIdentifier($c, false)
- || $c == '@'
- || ($c == '.'
- && $pmaString->isDigit(/*overload*/mb_substr($sql, $count2 + 1, 1))
- && ($previous_was_space || $previous_was_bracket
- || $previous_was_listsep))
- ) {
- /* DEBUG
- echo $pmaString->substr($sql, $count2);
- echo '<hr />';
- */
-
- $count2++;
-
- /**
- * @todo a @ can also be present in expressions like
- * FROM 'user'@'%' or TO 'user'@'%'
- * in this case, the @ is wrongly marked as alpha_variable
- */
- $is_identifier = $previous_was_punct;
- $is_sql_variable = $c == '@' && ! $previous_was_quote;
- $is_user = $c == '@' && $previous_was_quote;
- $is_digit = (
- !$is_identifier
- && !$is_sql_variable
- && $pmaString->isDigit($c)
- );
- $is_hex_digit = (
- $is_digit
- && $c == '0'
- && $count2 < $len
- && /*overload*/mb_substr($sql, $count2, 1) == 'x'
- );
- $is_float_digit = $c == '.';
- $is_float_digit_exponent = false;
-
- /* DEBUG
- echo '<pre>2';
- var_dump($is_identifier);
- var_dump($is_sql_variable);
- var_dump($is_digit);
- var_dump($is_float_digit);
- echo '</pre>';
- */
-
- // Fast skip is especially needed for huge BLOB data
- if ($is_hex_digit) {
- $count2++;
- $pos = strspn($sql, '0123456789abcdefABCDEF', $count2);
- if ($pos > $count2) {
- $count2 = $pos;
- }
- unset($pos);
- } elseif ($is_digit) {
- $pos = strspn($sql, '0123456789', $count2);
- if ($pos > $count2) {
- $count2 = $pos;
- }
- unset($pos);
- }
-
- while (($count2 < $len)
- && $pmaString->isSqlIdentifier(
- /*overload*/mb_substr($sql, $count2, 1),
- ($is_sql_variable || $is_digit)
- )
- ) {
- $c2 = /*overload*/mb_substr($sql, $count2, 1);
- if ($is_sql_variable && ($c2 == '.')) {
- $count2++;
- continue;
- }
- if ($is_digit && (!$is_hex_digit) && ($c2 == '.')) {
- $count2++;
- if (!$is_float_digit) {
- $is_float_digit = true;
- continue;
- } else {
- $debugstr = __('Invalid Identifer')
- . ' @ ' . ($count1+1) . "\n"
- . 'STR: ' . htmlspecialchars(
- /*overload*/mb_substr(
- $sql, $count1, $count2 - $count1
- )
- );
- PMA_SQP_throwError($debugstr, $sql);
- return $sql_array;
- }
- }
- if ($is_digit
- && (!$is_hex_digit)
- && (($c2 == 'e') || ($c2 == 'E'))
- ) {
- if (!$is_float_digit_exponent) {
- $is_float_digit_exponent = true;
- $is_float_digit = true;
- $count2++;
- continue;
- } else {
- $is_digit = false;
- $is_float_digit = false;
- }
- }
- if (($is_hex_digit && $pmaString->isHexDigit($c2))
- || ($is_digit && $pmaString->isDigit($c2))
- ) {
- $count2++;
- continue;
- } else {
- $is_digit = false;
- $is_hex_digit = false;
- }
-
- $count2++;
- } // end while
-
- $l = $count2 - $count1;
- $str = /*overload*/mb_substr($sql, $count1, $l);
-
- if ($is_digit || $is_float_digit || $is_hex_digit) {
- $type = 'digit';
- if ($is_float_digit) {
- $type .= '_float';
- } elseif ($is_hex_digit) {
- $type .= '_hex';
- } else {
- $type .= '_integer';
- }
- } elseif ($is_user) {
- $type = 'punct_user';
- } elseif ($is_sql_variable != false) {
- $type = 'alpha_variable';
- } else {
- $type = 'alpha';
- } // end if... else....
- PMA_SQP_arrayAdd($sql_array, $type, $str, $arraysize, $count2);
-
- continue;
- }
-
- // Checks for punct
- if (/*overload*/mb_strpos($allpunct_list, $c) !== false) {
- while (($count2 < $len)
- && /*overload*/mb_strpos(
- $allpunct_list, /*overload*/mb_substr(
- $sql, $count2, 1
- )
- ) !== false
- ) {
- $count2++;
- }
- $l = $count2 - $count1;
- if ($l == 1) {
- $punct_data = $c;
- } else {
- $punct_data = /*overload*/mb_substr($sql, $count1, $l);
- }
-
- // Special case, sometimes, although two characters are
- // adjacent directly, they ACTUALLY need to be separate
- /* DEBUG
- echo '<pre>';
- var_dump($l);
- var_dump($punct_data);
- echo '</pre>';
- */
-
- if ($l == 1) {
- $t_suffix = '';
- switch ($punct_data) {
- case $punct_queryend:
- $t_suffix = '_queryend';
- break;
- case $punct_qualifier:
- $t_suffix = '_qualifier';
- $this_was_punct = true;
- break;
- case $punct_listsep:
- $this_was_listsep = true;
- $t_suffix = '_listsep';
- break;
- default:
- break;
- }
- PMA_SQP_arrayAdd(
- $sql_array, 'punct' . $t_suffix, $punct_data, $arraysize, $count2
- );
- } elseif ($punct_data == $GLOBALS['sql_delimiter']
- || isset($allpunct_list_pair[$punct_data])
- ) {
- // Ok, we have one of the valid combined punct expressions
- PMA_SQP_arrayAdd(
- $sql_array, 'punct', $punct_data, $arraysize, $count2
- );
- } else {
- // Bad luck, lets split it up more
- $first = $punct_data[0];
- $last2 = $punct_data[$l - 2] . $punct_data[$l - 1];
- $last = $punct_data[$l - 1];
- if (($first == ',') || ($first == ';') || ($first == '.')
- || ($first == '*')
- ) {
- $count2 = $count1 + 1;
- $punct_data = $first;
- } elseif (($last2 == '/*')
- || (($last2 == '--')
- && ($count2 == $len
- || /*overload*/mb_substr($sql, $count2, 1) <= ' '))
- ) {
- $count2 -= 2;
- $punct_data = /*overload*/mb_substr(
- $sql, $count1, $count2 - $count1
- );
- } elseif (($last == '-') || ($last == '+') || ($last == '!')) {
- $count2--;
- $punct_data = /*overload*/mb_substr(
- $sql, $count1, $count2 - $count1
- );
- } elseif ($last != '~') {
- /**
- * @todo for negation operator, split in 2 tokens ?
- * "select x&~1 from t"
- * becomes "select x & ~ 1 from t" ?
- */
- $debugstr = __('Unknown Punctuation String')
- . ' @ ' . ($count1+1) . "\n"
- . 'STR: ' . htmlspecialchars($punct_data);
- PMA_SQP_throwError($debugstr, $sql);
- return $sql_array;
- }
- PMA_SQP_arrayAdd(
- $sql_array, 'punct', $punct_data, $arraysize, $count2
- );
- continue;
- } // end if... elseif... else
- continue;
- }
-
- // DEBUG
- $count2++;
-
- $debugstr = 'C1 C2 LEN: ' . $count1 . ' ' . $count2 . ' ' . $len . "\n"
- . 'STR: ' . /*overload*/mb_substr(
- $sql, $count1, $count2 - $count1
- ) . "\n";
- PMA_SQP_bug($debugstr, $sql);
- return $sql_array;
-
- } // end while ($count2 < $len)
-
- /*
- echo '<pre>';
- print_r($sql_array);
- echo '</pre>';
- */
-
- if ($arraysize > 0) {
- $t_next = $sql_array[0]['type'];
- $t_prev = '';
- $t_cur = '';
- $d_next = $sql_array[0]['data'];
- $d_prev = '';
- $d_cur = '';
- $d_next_upper = $t_next == 'alpha'
- ? /*overload*/mb_strtoupper($d_next)
- : $d_next;
- $d_prev_upper = '';
- $d_cur_upper = '';
- }
-
- for ($i = 0; $i < $arraysize; $i++) {
- $t_prev = $t_cur;
- $t_cur = $t_next;
- $d_prev = $d_cur;
- $d_cur = $d_next;
- $d_bef_prev_upper = $d_prev_upper;
- $d_prev_upper = $d_cur_upper;
- $d_cur_upper = $d_next_upper;
- if (($i + 1) < $arraysize) {
- $t_next = $sql_array[$i + 1]['type'];
- $d_next = $sql_array[$i + 1]['data'];
- $d_next_upper
- = $t_next == 'alpha' ? /*overload*/mb_strtoupper($d_next) : $d_next;
- } else {
- $t_next = '';
- $d_next = '';
- $d_next_upper = '';
- }
-
- /* DEBUG
- echo "[prev: <strong>".$d_prev."</strong> ".$t_prev."][cur: <strong>"
- . $d_cur."</strong> ".$t_cur."][next: <strong>".$d_next."</strong> "
- . $t_next."]<br />";
- */
-
- if ($t_cur == 'alpha') {
- $t_suffix = '_identifier';
- // for example: `thebit` bit(8) NOT NULL DEFAULT b'0'
- if ($t_prev == 'alpha' && $d_prev == 'DEFAULT' && $d_cur == 'b'
- && $t_next == 'quote_single'
- ) {
- $t_suffix = '_bitfield_constant_introducer';
- } elseif (($t_next == 'punct_qualifier')
- || ($t_prev == 'punct_qualifier')
- ) {
- $t_suffix = '_identifier';
- } elseif (($t_next == 'punct_bracket_open_round')
- && isset($PMA_SQPdata_function_name[$d_cur_upper])
- ) {
- /**
- * @todo 2005-10-16: in the case of a CREATE TABLE containing
- * a TIMESTAMP, since TIMESTAMP() is also a function, it's
- * found here and the token is wrongly marked as alpha_functionName.
- * But we compensate for this when analysing for timestamp_not_null
- * later in this script.
- *
- * Same applies to CHAR vs. CHAR() function.
- */
- $t_suffix = '_functionName';
- /* There are functions which might be as well column types */
- } elseif (isset($PMA_SQPdata_column_type[$d_cur_upper])) {
- $t_suffix = '_columnType';
-
- /**
- * Temporary fix for bugs #621357 and #2027720
- *
- * @todo FIX PROPERLY NEEDS OVERHAUL OF SQL TOKENIZER
- */
- if (($d_cur_upper == 'SET' || $d_cur_upper == 'BINARY')
- && $t_next != 'punct_bracket_open_round'
- ) {
- $t_suffix = '_reservedWord';
- }
- //END OF TEMPORARY FIX
-
- // CHARACTER is a synonym for CHAR, but can also be meant as
- // CHARACTER SET. In this case, we have a reserved word.
- if ($d_cur_upper == 'CHARACTER' && $d_next_upper == 'SET') {
- $t_suffix = '_reservedWord';
- }
-
- // experimental
- // current is a column type, so previous must not be
- // a reserved word but an identifier
- // CREATE TABLE SG_Persons (first varchar(64))
-
- //if ($sql_array[$i-1]['type'] =='alpha_reservedWord') {
- // $sql_array[$i-1]['type'] = 'alpha_identifier';
- //}
-
- } elseif (isset($PMA_SQPdata_reserved_word[$d_cur_upper])) {
- $t_suffix = '_reservedWord';
- } elseif (isset($PMA_SQPdata_column_attrib[$d_cur_upper])) {
- $t_suffix = '_columnAttrib';
- // INNODB is a MySQL table type, but in "SHOW ENGINE INNODB STATUS",
- // it should be regarded as a reserved word.
- if ($d_cur_upper == 'INNODB'
- && $d_prev_upper == 'SHOW'
- && $d_next_upper == 'STATUS'
- ) {
- $t_suffix = '_reservedWord';
- }
-
- if ($d_cur_upper == 'DEFAULT' && $d_next_upper == 'CHARACTER') {
- $t_suffix = '_reservedWord';
- }
- // Binary as character set
- if ($d_cur_upper == 'BINARY'
- && (($d_bef_prev_upper == 'CHARACTER' && $d_prev_upper == 'SET')
- || ($d_bef_prev_upper == 'SET' && $d_prev_upper == '=')
- || ($d_bef_prev_upper == 'CHARSET' && $d_prev_upper == '=')
- || $d_prev_upper == 'CHARSET')
- && in_array($d_cur, $mysql_charsets)
- ) {
- $t_suffix = '_charset';
- }
- } elseif (in_array($d_cur, $mysql_charsets)
- || in_array($d_cur, $mysql_collations_flat)
- || ($d_cur{0} == '_'
- && in_array(/*overload*/mb_substr($d_cur, 1), $mysql_charsets))
- ) {
- $t_suffix = '_charset';
- } else {
- // Do nothing
- }
- // check if present in the list of forbidden words
- if ($t_suffix == '_reservedWord'
- && isset($PMA_SQPdata_forbidden_word[$d_cur_upper])
- ) {
- $sql_array[$i]['forbidden'] = true;
- } else {
- $sql_array[$i]['forbidden'] = false;
- }
- $sql_array[$i]['type'] .= $t_suffix;
- }
- } // end for
-
- // Stores the size of the array inside the array, as count() is a slow
- // operation.
- $sql_array['len'] = $arraysize;
-
- // DEBUG echo 'After parsing<pre>'; print_r($sql_array); echo '</pre>';
- // Sends the data back
- return $sql_array;
-} // end of the "PMA_SQP_parse()" function
-
-/**
- * Checks for token types being what we want...
- *
- * @param string $toCheck String of type that we have
- * @param string $whatWeWant String of type that we want
- *
- * @return boolean result of check
- *
- * @access private
- */
-function PMA_SQP_typeCheck($toCheck, $whatWeWant)
-{
- $typeSeparator = '_';
- if (strcmp($whatWeWant, $toCheck) == 0) {
- return true;
- }
-
- if (/*overload*/mb_strpos($whatWeWant, $typeSeparator) !== false) {
- return false;
- }
-
- return strncmp(
- $whatWeWant, $toCheck,
- /*overload*/mb_strpos($toCheck, $typeSeparator)
- ) == 0;
-}
-
-
-/**
- * Analyzes SQL queries
- *
- * @param array $arr The SQL queries
- *
- * @return array The analyzed SQL queries
- *
- * @access public
- */
-function PMA_SQP_analyze($arr)
-{
- if ($arr == array() || ! isset($arr['len'])) {
- return array();
- }
- $result = array();
- $size = $arr['len'];
- $subresult = array(
- 'querytype' => '',
- // the whole stuff between SELECT and FROM , except DISTINCT
- 'select_expr_clause'=> '',
- 'position_of_first_select' => '', // the array index
- 'from_clause'=> '',
- 'group_by_clause'=> '',
- 'order_by_clause'=> '',
- 'having_clause' => '',
- 'limit_clause' => '',
- 'where_clause' => '',
- 'where_clause_identifiers' => array(),
- 'unsorted_query' => '',
- 'queryflags' => array(),
- 'select_expr' => array(),
- 'table_ref' => array(),
- 'foreign_keys' => array(),
- 'create_table_fields' => array()
- );
- $subresult_empty = $subresult;
- $seek_queryend = false;
- $seen_end_of_table_ref = false;
- $number_of_brackets_in_extract = 0;
- $number_of_brackets_in_group_concat = 0;
-
- $number_of_brackets = 0;
- $in_subquery = false;
- $seen_subquery = false;
- $seen_from = false;
-
- // for SELECT EXTRACT(YEAR_MONTH FROM CURDATE())
- // we must not use CURDATE as a table_ref
- // so we track whether we are in the EXTRACT()
- $in_extract = false;
-
- // for GROUP_CONCAT(...)
- $in_group_concat = false;
-
- /* Description of analyzer results
- *
- * db, table, column, alias
- * ------------------------
- *
- * Inside the $subresult array, we create ['select_expr'] and ['table_ref']
- * arrays.
- *
- * The SELECT syntax (simplified) is
- *
- * SELECT
- * select_expression,...
- * [FROM [table_references]
- *
- *
- * ['select_expr'] is filled with each expression, the key represents the
- * expression position in the list (0-based) (so we don't lose track of
- * multiple occurrences of the same column).
- *
- * ['table_ref'] is filled with each table ref, same thing for the key.
- *
- * I create all sub-values empty, even if they are
- * not present (for example no select_expression alias).
- *
- * There is a debug section at the end of loop #1, if you want to
- * see the exact contents of select_expr and table_ref
- *
- * queryflags
- * ----------
- *
- * In $subresult, array 'queryflags' is filled, according to what we
- * find in the query.
- *
- * Currently, those are generated:
- *
- * ['queryflags']['select_from'] = 1; if this is a real SELECT...FROM
- * ['queryflags']['drop_database'] = 1;if this is a DROP DATABASE
- * ['queryflags']['reload'] = 1; for the purpose of reloading the
- * navigation bar
- * ['queryflags']['distinct'] = 1; for a DISTINCT
- * ['queryflags']['union'] = 1; for a UNION
- * ['queryflags']['join'] = 1; for a JOIN
- * ['queryflags']['offset'] = 1; for the presence of OFFSET
- * ['queryflags']['procedure'] = 1; for the presence of PROCEDURE
- * ['queryflags']['is_explain'] = 1; for the presence of EXPLAIN
- * ['queryflags']['is_delete'] = 1; for the presence of DELETE
- * ['queryflags']['is_affected'] = 1; for the presence of UPDATE, DELETE
- * or INSERT|LOAD DATA|REPLACE
- * ['queryflags']['is_replace'] = 1; for the presence of REPLACE
- * ['queryflags']['is_insert'] = 1; for the presence of INSERT
- * ['queryflags']['is_maint'] = 1; for the presence of CHECK|ANALYZE
- * |REPAIR|OPTIMIZE TABLE
- * ['queryflags']['is_show'] = 1; for the presence of SHOW
- * ['queryflags']['is_analyse'] = 1; for the presence of PROCEDURE ANALYSE
- * ['queryflags']['is_export'] = 1; for the presence of INTO OUTFILE
- * ['queryflags']['is_group'] = 1; for the presence of GROUP BY|HAVING|
- * SELECT DISTINCT
- * ['queryflags']['is_func'] = 1; for the presence of SUM|AVG|STD|STDDEV
- * |MIN|MAX|BIT_OR|BIT_AND
- * ['queryflags']['is_count'] = 1; for the presence of SELECT COUNT
- * ['queryflags']['is_procedure'] = 1; for the presence of CALL
- * ['queryflags']['is_subquery'] = 1; contains a subquery
- *
- * query clauses
- * -------------
- *
- * The select is split in those clauses:
- * ['select_expr_clause']
- * ['from_clause']
- * ['group_by_clause']
- * ['order_by_clause']
- * ['having_clause']
- * ['limit_clause']
- * ['where_clause']
- *
- * The identifiers of the WHERE clause are put into the array
- * ['where_clause_identifier']
- *
- * For a SELECT, the whole query without the ORDER BY clause is put into
- * ['unsorted_query']
- *
- * foreign keys
- * ------------
- * The CREATE TABLE may contain FOREIGN KEY clauses, so they get
- * analyzed and ['foreign_keys'] is an array filled with
- * the constraint name, the index list,
- * the REFERENCES table name and REFERENCES index list,
- * and ON UPDATE | ON DELETE clauses
- *
- * position_of_first_select
- * ------------------------
- *
- * The array index of the first SELECT we find. Will be used to
- * insert a SQL_CALC_FOUND_ROWS.
- *
- * create_table_fields
- * -------------------
- *
- * Used to detect the DEFAULT CURRENT_TIMESTAMP and
- * ON UPDATE CURRENT_TIMESTAMP clauses of the CREATE TABLE query.
- * Also used to store the default value of the field.
- * An array, each element is the identifier name.
- * Note that for now, the timestamp_not_null element is created
- * even for non-TIMESTAMP fields.
- *
- * Sub-elements: ['type'] which contains the column type
- * optional (currently they are never false but can be absent):
- * ['default_current_timestamp'] boolean
- * ['on_update_current_timestamp'] boolean
- * ['timestamp_not_null'] boolean
- *
- * section_before_limit, section_after_limit
- * -----------------------------------------
- *
- * Marks the point of the query where we can insert a LIMIT clause;
- * so the section_before_limit will contain the left part before
- * a possible LIMIT clause
- *
- *
- * End of description of analyzer results
- */
-
- // must be sorted
- // TODO: current logic checks for only one word, so I put only the
- // first word of the reserved expressions that end a table ref;
- // maybe this is not ok (the first word might mean something else)
- // $words_ending_table_ref = array(
- // 'FOR UPDATE',
- // 'GROUP BY',
- // 'HAVING',
- // 'LIMIT',
- // 'LOCK IN SHARE MODE',
- // 'ORDER BY',
- // 'PROCEDURE',
- // 'UNION',
- // 'WHERE'
- // );
- $words_ending_table_ref = array(
- 'FOR' => 1,
- 'GROUP' => 1,
- 'HAVING' => 1,
- 'LIMIT' => 1,
- 'LOCK' => 1,
- 'ORDER' => 1,
- 'PROCEDURE' => 1,
- 'UNION' => 1,
- 'WHERE' => 1
- );
-
- $words_ending_clauses = array(
- 'FOR' => 1,
- 'LIMIT' => 1,
- 'LOCK' => 1,
- 'PROCEDURE' => 1,
- 'UNION' => 1
- );
-
- $supported_query_types = array(
- 'SELECT' => 1,
- /*
- // Support for these additional query types will come later on.
- 'DELETE' => 1,
- 'INSERT' => 1,
- 'REPLACE' => 1,
- 'TRUNCATE' => 1,
- 'UPDATE' => 1,
- 'EXPLAIN' => 1,
- 'DESCRIBE' => 1,
- 'SHOW' => 1,
- 'CREATE' => 1,
- 'SET' => 1,
- 'ALTER' => 1
- */
- );
-
- // loop #1 for each token: select_expr, table_ref for SELECT
-
- for ($i = 0; $i < $size; $i++) {
- //DEBUG echo "Loop1 <strong>" . $arr[$i]['data']
- //. "</strong> (" . $arr[$i]['type'] . ")<br />";
-
- // High speed seek for locating the end of the current query
- if ($seek_queryend == true) {
- if ($arr[$i]['type'] == 'punct_queryend') {
- $seek_queryend = false;
- } else {
- continue;
- } // end if (type == punct_queryend)
- } // end if ($seek_queryend)
-
- /**
- * Note: do not split if this is a punct_queryend for the first and only
- * query
- * @todo when we find a UNION, should we split in another subresult?
- */
- if ($arr[$i]['type'] == 'punct_queryend' && ($i + 1 != $size)) {
- $result[] = $subresult;
- $subresult = $subresult_empty;
- continue;
- } // end if (type == punct_queryend)
-
- // ==============================================================
- if ($arr[$i]['type'] == 'punct_bracket_open_round') {
- $number_of_brackets++;
- if ($in_extract) {
- $number_of_brackets_in_extract++;
- }
- if ($in_group_concat) {
- $number_of_brackets_in_group_concat++;
- }
- }
- // ==============================================================
- if ($arr[$i]['type'] == 'punct_bracket_close_round') {
- $number_of_brackets--;
- if ($number_of_brackets == 0) {
- $in_subquery = false;
- }
- if ($in_extract) {
- $number_of_brackets_in_extract--;
- if ($number_of_brackets_in_extract == 0) {
- $in_extract = false;
- }
- }
- if ($in_group_concat) {
- $number_of_brackets_in_group_concat--;
- if ($number_of_brackets_in_group_concat == 0) {
- $in_group_concat = false;
- }
- }
- }
-
- if ($in_subquery) {
- /**
- * skip the subquery to avoid setting
- * select_expr or table_ref with the contents
- * of this subquery; this is to avoid a bug when
- * trying to edit the results of
- * select * from child where not exists (select id from
- * parent where child.parent_id = parent.id);
- */
- continue;
- }
- // ==============================================================
- if ($arr[$i]['type'] == 'alpha_functionName') {
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
- if ($upper_data =='EXTRACT') {
- $in_extract = true;
- $number_of_brackets_in_extract = 0;
- }
- if ($upper_data =='GROUP_CONCAT') {
- $in_group_concat = true;
- $number_of_brackets_in_group_concat = 0;
- }
- }
-
- // ==============================================================
- if ($arr[$i]['type'] == 'alpha_reservedWord') {
- // We don't know what type of query yet, so run this
- if ($subresult['querytype'] == '') {
- $subresult['querytype'] = /*overload*/mb_strtoupper(
- $arr[$i]['data']
- );
- } // end if (querytype was empty)
-
- // Check if we support this type of query
- if (!isset($supported_query_types[$subresult['querytype']])) {
- // Skip ahead to the next one if we don't
- $seek_queryend = true;
- continue;
- } // end if (query not supported)
-
- // upper once
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
- /**
- * @todo reset for each query?
- */
-
- if ($upper_data == 'SELECT') {
- if ($number_of_brackets > 0) {
- $in_subquery = true;
- $seen_subquery = true;
- $subresult['queryflags']['is_subquery'] = 1;
- // this is a subquery so do not analyze inside it
- continue;
- }
- $seen_from = false;
- $previous_was_identifier = false;
- $current_select_expr = -1;
- $seen_end_of_table_ref = false;
- } // end if (data == SELECT)
-
- if ($upper_data =='FROM' && !$in_extract) {
- $current_table_ref = -1;
- $seen_from = true;
- $previous_was_identifier = false;
- $save_table_ref = true;
- } // end if (data == FROM)
-
- // here, do not 'continue' the loop, as we have more work for
- // reserved words below
- } // end if (type == alpha_reservedWord)
-
- // ==============================
- if ($arr[$i]['type'] == 'quote_backtick'
- || $arr[$i]['type'] == 'quote_double'
- || $arr[$i]['type'] == 'quote_single'
- || $arr[$i]['type'] == 'alpha_identifier'
- || ($arr[$i]['type'] == 'alpha_reservedWord'
- && $arr[$i]['forbidden'] == false)
- ) {
- switch ($arr[$i]['type']) {
- case 'alpha_identifier':
- case 'alpha_reservedWord':
- /**
- * this is not a real reservedWord, because it's not
- * present in the list of forbidden words, for example
- * "storage" which can be used as an identifier
- *
- */
- $identifier = $arr[$i]['data'];
- break;
-
- case 'quote_backtick':
- case 'quote_double':
- case 'quote_single':
- $identifier = PMA_Util::unQuote($arr[$i]['data']);
- break;
- } // end switch
-
- if ($subresult['querytype'] == 'SELECT'
- && ! $in_group_concat
- && ! ($seen_subquery
- && $arr[$i - 1]['type'] == 'punct_bracket_close_round')
- ) {
- if (!$seen_from) {
- if ($previous_was_identifier && isset($chain)) {
- // found alias for this select_expr, save it
- // but only if we got something in $chain
- // (for example, SELECT COUNT(*) AS cnt
- // puts nothing in $chain, so we avoid
- // setting the alias)
- $alias_for_select_expr = $identifier;
- } else {
- if (! isset($chain)) {
- $chain = array();
- }
- $chain[] = $identifier;
- $previous_was_identifier = true;
-
- } // end if !$previous_was_identifier
- } else {
- // ($seen_from)
- if ($save_table_ref && !$seen_end_of_table_ref) {
- if ($previous_was_identifier) {
- // found alias for table ref
- // save it for later
- $alias_for_table_ref = $identifier;
- } else {
- if (! isset($chain)) {
- $chain = array();
- }
- $chain[] = $identifier;
- $previous_was_identifier = true;
-
- } // end if ($previous_was_identifier)
- } // end if ($save_table_ref &&!$seen_end_of_table_ref)
- } // end if (!$seen_from)
- } // end if (querytype SELECT)
- } // end if (quote_backtick or double quote or alpha_identifier)
-
- // ===================================
- if ($arr[$i]['type'] == 'punct_qualifier') {
- // to be able to detect an identifier following another
- $previous_was_identifier = false;
- continue;
- } // end if (punct_qualifier)
-
- /**
- * @todo check if 3 identifiers following one another -> error
- */
-
- // s a v e a s e l e c t e x p r
- // finding a list separator or FROM
- // means that we must save the current chain of identifiers
- // into a select expression
-
- // for now, we only save a select expression if it contains
- // at least one identifier, as we are interested in checking
- // the columns and table names, so in "select * from persons",
- // the "*" is not saved
-
- if (isset($chain) && !$seen_end_of_table_ref
- && ((!$seen_from && $arr[$i]['type'] == 'punct_listsep')
- || ($arr[$i]['type'] == 'alpha_reservedWord' && $upper_data == 'FROM'))
- ) {
- $size_chain = count($chain);
- $current_select_expr++;
- $subresult['select_expr'][$current_select_expr] = array(
- 'expr' => '',
- 'alias' => '',
- 'db' => '',
- 'table_name' => '',
- 'table_true_name' => '',
- 'column' => ''
- );
-
- if (isset($alias_for_select_expr)
- && /*overload*/mb_strlen($alias_for_select_expr)
- ) {
- // we had found an alias for this select expression
- $subresult['select_expr'][$current_select_expr]['alias']
- = $alias_for_select_expr;
- unset($alias_for_select_expr);
- }
- // there is at least a column
- $subresult['select_expr'][$current_select_expr]['column']
- = $chain[$size_chain - 1];
- $subresult['select_expr'][$current_select_expr]['expr']
- = $chain[$size_chain - 1];
-
- // maybe a table
- if ($size_chain > 1) {
- $subresult['select_expr'][$current_select_expr]['table_name']
- = $chain[$size_chain - 2];
- // we assume for now that this is also the true name
- $subresult['select_expr'][$current_select_expr]['table_true_name']
- = $chain[$size_chain - 2];
- $subresult['select_expr'][$current_select_expr]['expr']
- = $subresult['select_expr'][$current_select_expr]['table_name']
- . '.' . $subresult['select_expr'][$current_select_expr]['expr'];
- } // end if ($size_chain > 1)
-
- // maybe a db
- if ($size_chain > 2) {
- $subresult['select_expr'][$current_select_expr]['db']
- = $chain[$size_chain - 3];
- $subresult['select_expr'][$current_select_expr]['expr']
- = $subresult['select_expr'][$current_select_expr]['db']
- . '.' . $subresult['select_expr'][$current_select_expr]['expr'];
- } // end if ($size_chain > 2)
- unset($chain);
-
- /**
- * @todo explain this:
- */
- if (($arr[$i]['type'] == 'alpha_reservedWord')
- && ($upper_data != 'FROM')
- ) {
- $previous_was_identifier = true;
- }
-
- } // end if (save a select expr)
-
- //======================================
- // s a v e a t a b l e r e f
- //======================================
-
- // maybe we just saw the end of table refs
- // but the last table ref has to be saved
- // or we are at the last token
- // or we just got a reserved word
- /**
- * @todo there could be another query after this one
- */
-
- if (isset($chain) && $seen_from && $save_table_ref
- && ($arr[$i]['type'] == 'punct_listsep'
- || ($arr[$i]['type'] == 'alpha_reservedWord' && $upper_data != "AS")
- || $seen_end_of_table_ref
- || $i == $size - 1)
- ) {
-
- $size_chain = count($chain);
- $current_table_ref++;
- $subresult['table_ref'][$current_table_ref] = array(
- 'expr' => '',
- 'db' => '',
- 'table_name' => '',
- 'table_alias' => '',
- 'table_true_name' => ''
- );
- if (isset($alias_for_table_ref)
- && /*overload*/mb_strlen($alias_for_table_ref)
- ) {
- $subresult['table_ref'][$current_table_ref]['table_alias']
- = $alias_for_table_ref;
- unset($alias_for_table_ref);
- }
- $subresult['table_ref'][$current_table_ref]['table_name']
- = $chain[$size_chain - 1];
- // we assume for now that this is also the true name
- $subresult['table_ref'][$current_table_ref]['table_true_name']
- = $chain[$size_chain - 1];
- $subresult['table_ref'][$current_table_ref]['expr']
- = $subresult['table_ref'][$current_table_ref]['table_name'];
- // maybe a db
- if ($size_chain > 1) {
- $subresult['table_ref'][$current_table_ref]['db']
- = $chain[$size_chain - 2];
- $subresult['table_ref'][$current_table_ref]['expr']
- = $subresult['table_ref'][$current_table_ref]['db']
- . '.' . $subresult['table_ref'][$current_table_ref]['expr'];
- } // end if ($size_chain > 1)
-
- // add the table alias into the whole expression
- $subresult['table_ref'][$current_table_ref]['expr']
- .= ' ' . $subresult['table_ref'][$current_table_ref]['table_alias'];
-
- unset($chain);
- $previous_was_identifier = true;
- //continue;
-
- } // end if (save a table ref)
-
- // when we have found all table refs,
- // for each table_ref alias, put the true name of the table
- // in the corresponding select expressions
-
- if (isset($current_table_ref)
- && ($seen_end_of_table_ref || $i == $size-1)
- && $subresult != $subresult_empty
- ) {
- for ($tr=0; $tr <= $current_table_ref; $tr++) {
- $alias = $subresult['table_ref'][$tr]['table_alias'];
- $truename = $subresult['table_ref'][$tr]['table_true_name'];
- for ($se=0; $se <= $current_select_expr; $se++) {
- if (isset($alias)
- && /*overload*/mb_strlen($alias)
- && $subresult['select_expr'][$se]['table_true_name'] == $alias
- ) {
- $subresult['select_expr'][$se]['table_true_name']
- = $truename;
- } // end if (found the alias)
- } // end for (select expressions)
-
- } // end for (table refs)
- } // end if (set the true names)
-
- // e n d i n g l o o p #1
- // set the $previous_was_identifier to false if the current
- // token is not an identifier
- if (($arr[$i]['type'] != 'alpha_identifier')
- && ($arr[$i]['type'] != 'quote_double')
- && ($arr[$i]['type'] != 'quote_single')
- && ($arr[$i]['type'] != 'quote_backtick')
- ) {
- $previous_was_identifier = false;
- } // end if
-
- // however, if we are on AS, we must keep the $previous_was_identifier
- if (($arr[$i]['type'] == 'alpha_reservedWord')
- && ($upper_data == 'AS')
- ) {
- $previous_was_identifier = true;
- }
-
- if (($arr[$i]['type'] == 'alpha_reservedWord')
- && ($upper_data =='ON' || $upper_data =='USING')
- ) {
- $save_table_ref = false;
- } // end if (data == ON)
-
- if (($arr[$i]['type'] == 'alpha_reservedWord')
- && ($upper_data =='JOIN' || $upper_data =='FROM')
- ) {
- $save_table_ref = true;
- } // end if (data == JOIN)
-
- /**
- * no need to check the end of table ref if we already did
- *
- * @todo maybe add "&& $seen_from"
- */
- if (!$seen_end_of_table_ref) {
- // if this is the last token, it implies that we have
- // seen the end of table references
- // Check for the end of table references
- //
- // Note: if we are analyzing a GROUP_CONCAT clause,
- // we might find a word that seems to indicate that
- // we have found the end of table refs (like ORDER)
- // but it's a modifier of the GROUP_CONCAT so
- // it's not the real end of table refs
- if (($i == $size-1)
- || ($arr[$i]['type'] == 'alpha_reservedWord'
- && !$in_group_concat
- && isset($words_ending_table_ref[$upper_data]))
- ) {
- $seen_end_of_table_ref = true;
- // to be able to save the last table ref, but do not
- // set it true if we found a word like "ON" that has
- // already set it to false
- if (isset($save_table_ref) && $save_table_ref != false) {
- $save_table_ref = true;
- } //end if
-
- } // end if (check for end of table ref)
- } //end if (!$seen_end_of_table_ref)
-
- if ($seen_end_of_table_ref) {
- $save_table_ref = false;
- } // end if
-
- } // end for $i (loop #1)
-
- //DEBUG
- /*
- if (isset($current_select_expr)) {
- for ($trace=0; $trace<=$current_select_expr; $trace++) {
- echo "<br />";
- reset ($subresult['select_expr'][$trace]);
- while (list ($key, $val) = each ($subresult['select_expr'][$trace]))
- echo "sel expr $trace $key => $val<br />\n";
- }
- }
-
- if (isset($current_table_ref)) {
- echo "current_table_ref = " . $current_table_ref . "<br>";
- for ($trace=0; $trace<=$current_table_ref; $trace++) {
-
- echo "<br />";
- reset ($subresult['table_ref'][$trace]);
- while (list ($key, $val) = each ($subresult['table_ref'][$trace]))
- echo "table ref $trace $key => $val<br />\n";
- }
- }
- */
- // -------------------------------------------------------
-
- // loop #2: - queryflags
- // - querytype (for queries != 'SELECT')
- // - section_before_limit, section_after_limit
- //
- // we will also need this queryflag in loop 2
- // so set it here
- if (isset($current_table_ref) && $current_table_ref > -1) {
- $subresult['queryflags']['select_from'] = 1;
- }
-
- $section_before_limit = '';
- $section_after_limit = ''; // truly the section after the limit clause
- $seen_reserved_word = false;
- $seen_group = false;
- $seen_order = false;
- $seen_order_by = false;
- $in_group_by = false; // true when we are inside the GROUP BY clause
- $in_order_by = false; // true when we are inside the ORDER BY clause
- $in_having = false; // true when we are inside the HAVING clause
- $in_select_expr = false; // true when we are inside the select expr clause
- $in_where = false; // true when we are inside the WHERE clause
- $seen_limit = false; // true if we have seen a LIMIT clause
- $in_limit = false; // true when we are inside the LIMIT clause
- $after_limit = false; // true when we are after the LIMIT clause
- $in_from = false; // true when we are in the FROM clause
- $in_group_concat = false;
- $first_reserved_word = '';
- $current_identifier = '';
- $unsorted_query = $arr['raw']; // in case there is no ORDER BY
- $number_of_brackets = 0;
- $in_subquery = false;
-
- $arrayFunctions = array(
- "SUM","AVG","STD","STDDEV","MIN","MAX","BIT_OR","BIT_AND"
- );
- $arrayKeyWords = array("BY", "HAVING", "SELECT");
-
- for ($i = 0; $i < $size; $i++) {
- //DEBUG echo "Loop2 <strong>" . $arr[$i]['data']
- //. "</strong> (" . $arr[$i]['type'] . ")<br />";
-
- if ($arr[$i]['type'] == 'punct_bracket_open_round') {
- $number_of_brackets++;
- }
-
- if ($arr[$i]['type'] == 'punct_bracket_close_round') {
- $number_of_brackets--;
- if ($number_of_brackets == 0) {
- $in_subquery = false;
- }
- }
-
- if ($arr[$i]['type'] == 'alpha_reservedWord') {
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
-
- if ($upper_data == 'SELECT' && $number_of_brackets > 0) {
- $in_subquery = true;
- }
-
- if (!$seen_reserved_word) {
- $first_reserved_word = $upper_data;
- $subresult['querytype'] = $upper_data;
- $seen_reserved_word = true;
-
- if ($first_reserved_word === 'SELECT') {
- $position_of_first_select = $i;
- } elseif ($first_reserved_word === 'EXPLAIN') {
- $subresult['queryflags']['is_explain'] = 1;
- } elseif ($first_reserved_word === 'DELETE') {
- $subresult['queryflags']['is_delete'] = 1;
- $subresult['queryflags']['is_affected'] = 1;
- } elseif ($first_reserved_word === 'UPDATE') {
- $subresult['queryflags']['is_affected'] = 1;
- } elseif ($first_reserved_word === 'REPLACE') {
- $subresult['queryflags']['is_replace'] = 1;
- $subresult['queryflags']['is_affected'] = 1;
- } elseif ($first_reserved_word === 'INSERT') {
- $subresult['queryflags']['is_insert'] = 1;
- $subresult['queryflags']['is_affected'] = 1;
- } elseif ($first_reserved_word === 'SHOW') {
- $subresult['queryflags']['is_show'] = 1;
- }
-
- } else {
- // for the presence of DROP DATABASE
- if ($first_reserved_word == 'DROP' && $upper_data == 'DATABASE') {
- $subresult['queryflags']['drop_database'] = 1;
- }
- // A table has to be created, renamed, dropped -> navi panel
- // should be reloaded
- $keywords1 = array('CREATE', 'ALTER', 'DROP');
- $keywords2 = array('VIEW', 'TABLE', 'DATABASE', 'SCHEMA');
- if (in_array($first_reserved_word, $keywords1)
- && in_array($upper_data, $keywords2)
- ) {
- $subresult['queryflags']['reload'] = 1;
- }
- // for the presence of CHECK|ANALYZE|REPAIR|OPTIMIZE TABLE
- $keywords = array(
- 'CHECK', 'ANALYZE', 'REPAIR', 'OPTIMIZE'
- );
- if (in_array($first_reserved_word, $keywords)
- && $upper_data == 'TABLE'
- ) {
- $subresult['queryflags']['is_maint'] = 1;
- }
- }
-
- if ($upper_data == 'LIMIT' && ! $in_subquery) {
- $section_before_limit = /*overload*/mb_substr(
- $arr['raw'], 0, $arr[$i]['pos'] - 5
- );
- $in_limit = true;
- $seen_limit = true;
- $limit_clause = '';
- $in_order_by = false; // @todo maybe others to set false
- }
-
- if ($upper_data == 'PROCEDURE') {
- $subresult['queryflags']['procedure'] = 1;
- $in_limit = false;
- $after_limit = true;
-
- // for the presence of PROCEDURE ANALYSE
- if (isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- && ($i + 1) < $size
- && $arr[$i + 1]['type'] == 'alpha_reservedWord'
- && /*overload*/mb_strtoupper($arr[$i + 1]['data']) == 'ANALYSE'
- ) {
- $subresult['queryflags']['is_analyse'] = 1;
- }
- }
-
- // for the presence of INTO OUTFILE
- if ($upper_data == 'INTO'
- && isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- && ($i + 1) < $size
- && $arr[$i + 1]['type'] == 'alpha_reservedWord'
- && /*overload*/mb_strtoupper($arr[$i + 1]['data']) == 'OUTFILE'
- ) {
- $subresult['queryflags']['is_export'] = 1;
- }
- /**
- * @todo set also to false if we find FOR UPDATE or LOCK IN SHARE MODE
- */
- if ($upper_data == 'SELECT') {
- $in_select_expr = true;
- $select_expr_clause = '';
-
- // for the presence of SELECT COUNT
- if (isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- && !isset($subresult['queryflags']['is_group'])
- && ($i + 1) < $size
- && $arr[$i + 1]['type'] == 'alpha_functionName'
- && /*overload*/mb_strtoupper($arr[$i + 1]['data']) == 'COUNT'
- ) {
- $subresult['queryflags']['is_count'] = 1;
- }
- }
-
- if ($upper_data == 'DISTINCT' && !$in_group_concat) {
- $subresult['queryflags']['distinct'] = 1;
- }
-
- if ($upper_data == 'UNION') {
- $subresult['queryflags']['union'] = 1;
- }
-
- if ($upper_data == 'JOIN') {
- $subresult['queryflags']['join'] = 1;
- }
-
- if ($upper_data == 'OFFSET') {
- $subresult['queryflags']['offset'] = 1;
- }
-
- // for the presence of CALL
- if ($upper_data == 'CALL') {
- $subresult['queryflags']['is_procedure'] = 1;
- }
-
- // if this is a real SELECT...FROM
- if ($upper_data == 'FROM'
- && isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- ) {
- $in_from = true;
- $from_clause = '';
- $in_select_expr = false;
- }
-
- // (we could have less resetting of variables to false
- // if we trust that the query respects the standard
- // MySQL order for clauses)
-
- // we use $seen_group and $seen_order because we are looking
- // for the BY
- if ($upper_data == 'GROUP') {
- $seen_group = true;
- $seen_order = false;
- $in_having = false;
- $in_order_by = false;
- $in_where = false;
- $in_select_expr = false;
- $in_from = false;
-
- // for the presence of GROUP BY|HAVING|SELECT DISTINCT
- if (isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- && ($i + 1) < $size
- && $arr[$i + 1]['type'] == 'alpha_reservedWord'
- && in_array(
- /*overload*/mb_strtoupper($arr[$i + 1]['data']),
- $arrayKeyWords
- )
- && ($i + 2) < $size
- && $arr[$i + 2]['type'] == 'alpha_reservedWord'
- && /*overload*/mb_strtoupper($arr[$i + 2]['data']) == 'DISTINCT'
- ) {
- $subresult['queryflags']['is_group'] = 1;
- }
- }
- if ($upper_data == 'ORDER' && !$in_group_concat) {
- $seen_order = true;
- $seen_group = false;
- $in_having = false;
- $in_group_by = false;
- $in_where = false;
- $in_select_expr = false;
- $in_from = false;
- }
- if ($upper_data == 'HAVING') {
- $in_having = true;
- $having_clause = '';
- $seen_group = false;
- $seen_order = false;
- $in_group_by = false;
- $in_order_by = false;
- $in_where = false;
- $in_select_expr = false;
- $in_from = false;
- }
-
- if ($upper_data == 'WHERE') {
- $in_where = true;
- $where_clause = '';
- $where_clause_identifiers = array();
- $seen_group = false;
- $seen_order = false;
- $in_group_by = false;
- $in_order_by = false;
- $in_having = false;
- $in_select_expr = false;
- $in_from = false;
- }
-
- if ($upper_data == 'BY') {
- if ($seen_group) {
- $in_group_by = true;
- $group_by_clause = '';
- }
- if ($seen_order) {
- $seen_order_by = true;
- // Here we assume that the ORDER BY keywords took
- // exactly 8 characters.
- // We use $GLOBALS['PMA_String']->substr() to be charset-safe;
- // otherwise if the table name contains accents, the unsorted
- // query would be missing some characters.
- $unsorted_query = /*overload*/mb_substr(
- $arr['raw'], 0, $arr[$i]['pos'] - 8
- );
- $in_order_by = true;
- $order_by_clause = '';
- }
- }
-
- // if we find one of the words that could end the clause
- if (isset($words_ending_clauses[$upper_data])) {
-
- $in_group_by = false;
- $in_order_by = false;
- $in_having = false;
- $in_where = false;
- $in_select_expr = false;
- $in_from = false;
- }
-
- } // endif (reservedWord)
-
- // do not add a space after a function name
- /**
- * @todo can we combine loop 2 and loop 1? some code is repeated here...
- */
-
- $sep = ' ';
- if ($arr[$i]['type'] == 'alpha_functionName') {
- $sep='';
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
- if ($upper_data =='GROUP_CONCAT') {
- $in_group_concat = true;
- $number_of_brackets_in_group_concat = 0;
- }
- }
-
- if ($arr[$i]['type'] == 'punct_bracket_open_round') {
- if ($in_group_concat) {
- $number_of_brackets_in_group_concat++;
- }
- }
- if ($arr[$i]['type'] == 'punct_bracket_close_round') {
- if ($in_group_concat) {
- $number_of_brackets_in_group_concat--;
- if ($number_of_brackets_in_group_concat == 0) {
- $in_group_concat = false;
- }
- }
- }
-
- // do not add a space after an identifier if followed by a dot
- if ($arr[$i]['type'] == 'alpha_identifier'
- && $i < $size - 1 && $arr[$i + 1]['data'] == '.'
- ) {
- $sep = '';
- }
-
- // do not add a space after a dot if followed by an identifier
- if ($arr[$i]['data'] == '.' && $i < $size - 1
- && $arr[$i + 1]['type'] == 'alpha_identifier'
- ) {
- $sep = '';
- }
-
- // for the presence of INSERT|LOAD DATA
- if ($arr[$i]['type'] == 'alpha_identifier'
- && /*overload*/mb_strtoupper($arr[$i]['data']) == 'DATA'
- && ($i - 1) >= 0
- && $arr[$i - 1]['type'] == 'alpha_reservedWord'
- && in_array(
- /*overload*/mb_strtoupper($arr[$i - 1]['data']),
- array("INSERT", "LOAD")
- )
- ) {
- $subresult['queryflags']['is_insert'] = 1;
- $subresult['queryflags']['is_affected'] = 1;
- }
-
- // for the presence of SUM|AVG|STD|STDDEV|MIN|MAX|BIT_OR|BIT_AND
- if ($arr[$i]['type'] == 'alpha_functionName'
- && in_array(/*overload*/mb_strtoupper($arr[$i]['data']), $arrayFunctions)
- && isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- && !isset($subresult['queryflags']['is_group'])
- ) {
- $subresult['queryflags']['is_func'] = 1;
- }
-
- if ($in_select_expr && $upper_data != 'SELECT'
- && $upper_data != 'DISTINCT'
- ) {
- $select_expr_clause .= $arr[$i]['data'] . $sep;
- }
- if ($in_from && $upper_data != 'FROM') {
- $from_clause .= $arr[$i]['data'] . $sep;
- }
- if ($in_group_by && $upper_data != 'GROUP' && $upper_data != 'BY') {
- $group_by_clause .= $arr[$i]['data'] . $sep;
- }
- if ($in_order_by && $upper_data != 'ORDER' && $upper_data != 'BY') {
- // add a space only before ASC or DESC
- // not around the dot between dbname and tablename
- if ($arr[$i]['type'] == 'alpha_reservedWord') {
- $order_by_clause .= $sep;
- }
- $order_by_clause .= $arr[$i]['data'];
- }
- if ($in_having && $upper_data != 'HAVING') {
- $having_clause .= $arr[$i]['data'] . $sep;
- }
- if ($in_where && $upper_data != 'WHERE') {
- $where_clause .= $arr[$i]['data'] . $sep;
-
- if (($arr[$i]['type'] == 'quote_backtick')
- || ($arr[$i]['type'] == 'alpha_identifier')
- ) {
- $where_clause_identifiers[] = $arr[$i]['data'];
- }
- }
-
- // to grab the rest of the query after the ORDER BY clause
- if (isset($subresult['queryflags']['select_from'])
- && $subresult['queryflags']['select_from'] == 1
- && ! $in_order_by
- && $seen_order_by
- && $upper_data != 'BY'
- ) {
- $unsorted_query .= $arr[$i]['data'];
- if ($arr[$i]['type'] != 'punct_bracket_open_round'
- && $arr[$i]['type'] != 'punct_bracket_close_round'
- && $arr[$i]['type'] != 'punct'
- ) {
- $unsorted_query .= $sep;
- }
- }
-
- if ($in_limit) {
- if ($upper_data == 'OFFSET') {
- $limit_clause .= $sep;
- }
- $limit_clause .= $arr[$i]['data'];
- if ($upper_data == 'LIMIT' || $upper_data == 'OFFSET') {
- $limit_clause .= $sep;
- }
- }
- if ($after_limit && $seen_limit) {
- $section_after_limit .= $arr[$i]['data'] . $sep;
- }
-
- // clear $upper_data for next iteration
- $upper_data='';
- } // end for $i (loop #2)
- if (empty($section_before_limit)) {
- $section_before_limit = $arr['raw'];
- }
-
- // -----------------------------------------------------
- // loop #3: foreign keys and MySQL 4.1.2+ TIMESTAMP options
- // (for now, check only the first query)
- // (for now, identifiers are assumed to be backquoted)
-
- // If we find that we are dealing with a CREATE TABLE query,
- // we look for the next punct_bracket_open_round, which
- // introduces the fields list. Then, when we find a
- // quote_backtick, it must be a field, so we put it into
- // the create_table_fields array. Even if this field is
- // not a timestamp, it will be useful when logic has been
- // added for complete field attributes analysis.
-
- $seen_foreign = false;
- $seen_references = false;
- $seen_constraint = false;
- $foreign_key_number = -1;
- $seen_create_table = false;
- $seen_create = false;
- $seen_alter = false;
- $in_create_table_fields = false;
- $brackets_level = 0;
- $in_timestamp_options = false;
- $seen_default = false;
-
- for ($i = 0; $i < $size; $i++) {
- if ($arr[$i]['type'] == 'alpha_reservedWord') {
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
-
- if ($upper_data == 'NOT' && $in_timestamp_options) {
- if (! isset($create_table_fields)) {
- $create_table_fields = array();
- }
- $create_table_fields[$current_identifier]['timestamp_not_null']
- = true;
-
- }
-
- if ($upper_data == 'CREATE') {
- $seen_create = true;
- }
-
- if ($upper_data == 'ALTER') {
- $seen_alter = true;
- }
-
- if ($upper_data == 'TABLE' && $seen_create) {
- $seen_create_table = true;
- $create_table_fields = array();
- }
-
- if ($upper_data == 'CURRENT_TIMESTAMP') {
- if ($in_timestamp_options) {
- if ($seen_default) {
- $create_table_fields[$current_identifier]
- ['default_current_timestamp'] = true;
- }
- }
- }
-
- if ($upper_data == 'CONSTRAINT') {
- $foreign_key_number++;
- $seen_foreign = false;
- $seen_references = false;
- $seen_constraint = true;
- }
- if ($upper_data == 'FOREIGN') {
- $seen_foreign = true;
- $seen_references = false;
- $seen_constraint = false;
- }
- if ($upper_data == 'REFERENCES') {
- $seen_foreign = false;
- $seen_references = true;
- $seen_constraint = false;
- }
-
- // Cases covered:
-
- // [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
- // [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
-
- // but we set ['on_delete'] or ['on_cascade'] to
- // CASCADE | SET_NULL | NO_ACTION | RESTRICT
-
- // ON UPDATE CURRENT_TIMESTAMP
-
- if ($upper_data == 'ON') {
- if (isset($arr[$i+1])
- && $arr[$i+1]['type'] == 'alpha_reservedWord'
- ) {
- $second_upper_data = /*overload*/mb_strtoupper(
- $arr[$i+1]['data']
- );
- if ($second_upper_data == 'DELETE') {
- $clause = 'on_delete';
- }
- if ($second_upper_data == 'UPDATE') {
- $clause = 'on_update';
- }
- // ugly workaround because currently, NO is not
- // in the list of reserved words in sqlparser.data
- // (we got a bug report about not being able to use
- // 'no' as an identifier)
- if (isset($clause)
- && ($arr[$i+2]['type'] == 'alpha_reservedWord'
- || ($arr[$i+2]['type'] == 'alpha_identifier'
- && /*overload*/mb_strtoupper($arr[$i+2]['data'])=='NO'))
- ) {
- $third_upper_data = /*overload*/mb_strtoupper(
- $arr[$i+2]['data']
- );
- if ($third_upper_data == 'CASCADE'
- || $third_upper_data == 'RESTRICT'
- ) {
- $value = $third_upper_data;
- } elseif ($third_upper_data == 'SET'
- || $third_upper_data == 'NO'
- ) {
- if ($arr[$i+3]['type'] == 'alpha_reservedWord') {
- $value = $third_upper_data . '_'
- . /*overload*/mb_strtoupper($arr[$i+3]['data']);
- }
- } elseif ($third_upper_data == 'CURRENT_TIMESTAMP') {
- if ($clause == 'on_update'
- && $in_timestamp_options
- ) {
- $create_table_fields[$current_identifier]
- ['on_update_current_timestamp']
- = true;
- $seen_default = false;
- }
-
- } else {
- $value = '';
- }
- if (!empty($value)) {
- if (! isset($foreign)) {
- $foreign = array();
- }
- $foreign[$foreign_key_number][$clause] = $value;
- }
- unset($clause);
- } // endif (isset($clause))
- }
- }
-
- } // end of reserved words analysis
-
- if ($arr[$i]['type'] == 'punct_bracket_open_round') {
- $brackets_level++;
- if ($seen_create_table && $brackets_level == 1) {
- $in_create_table_fields = true;
- }
- }
-
- if ($arr[$i]['type'] == 'punct_bracket_close_round') {
- $brackets_level--;
- if ($seen_references) {
- $seen_references = false;
- }
- if ($seen_create_table && $brackets_level == 0) {
- $in_create_table_fields = false;
- }
- }
-
- if (($arr[$i]['type'] == 'alpha_columnAttrib')) {
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
- if ($seen_create_table && $in_create_table_fields) {
- if ($upper_data == 'DEFAULT') {
- $seen_default = true;
- $create_table_fields[$current_identifier]['default_value']
- = $arr[$i + 1]['data'];
- }
- }
- }
-
- /**
- * @see @todo 2005-10-16 note: the "or" part here is a workaround for a bug
- */
- if (($arr[$i]['type'] == 'alpha_columnType')
- || ($arr[$i]['type'] == 'alpha_functionName' && $seen_create_table)
- ) {
- $upper_data = /*overload*/mb_strtoupper($arr[$i]['data']);
- if ($seen_create_table && $in_create_table_fields
- && isset($current_identifier)
- ) {
- $create_table_fields[$current_identifier]['type'] = $upper_data;
- if ($upper_data == 'TIMESTAMP') {
- $arr[$i]['type'] = 'alpha_columnType';
- $in_timestamp_options = true;
- } else {
- $in_timestamp_options = false;
- if ($upper_data == 'CHAR') {
- $arr[$i]['type'] = 'alpha_columnType';
- }
- }
- }
- }
-
- if ($arr[$i]['type'] == 'quote_backtick'
- || $arr[$i]['type'] == 'alpha_identifier'
- ) {
-
- if ($arr[$i]['type'] == 'quote_backtick') {
- // remove backquotes
- $identifier = PMA_Util::unQuote($arr[$i]['data']);
- } else {
- $identifier = $arr[$i]['data'];
- }
-
- if ($seen_create_table && $in_create_table_fields) {
- $current_identifier = $identifier;
- // we set this one even for non TIMESTAMP type
- $create_table_fields[$current_identifier]['timestamp_not_null']
- = false;
- }
-
- if ($seen_constraint) {
- $foreign[$foreign_key_number]['constraint'] = $identifier;
- }
-
- if ($seen_foreign && $brackets_level > 0) {
- $foreign[$foreign_key_number]['index_list'][] = $identifier;
- }
-
- if ($seen_references) {
- if ($seen_alter && $brackets_level > 0) {
- $foreign[$foreign_key_number]['ref_index_list'][] = $identifier;
- // here, the first bracket level corresponds to the
- // bracket of CREATE TABLE
- // so if we are on level 2, it must be the index list
- // of the foreign key REFERENCES
- } elseif ($brackets_level > 1) {
- $foreign[$foreign_key_number]['ref_index_list'][] = $identifier;
- } elseif ($arr[$i+1]['type'] == 'punct_qualifier') {
- // identifier is `db`.`table`
- // the first pass will pick the db name
- // the next pass will pick the table name
- $foreign[$foreign_key_number]['ref_db_name'] = $identifier;
- } else {
- // identifier is `table`
- $foreign[$foreign_key_number]['ref_table_name'] = $identifier;
- }
- }
- }
- } // end for $i (loop #3)
-
- // Fill the $subresult array
-
- if (isset($create_table_fields)) {
- $subresult['create_table_fields'] = $create_table_fields;
- }
-
- if (isset($foreign)) {
- $subresult['foreign_keys'] = $foreign;
- }
-
- if (isset($select_expr_clause)) {
- $subresult['select_expr_clause'] = $select_expr_clause;
- }
- if (isset($from_clause)) {
- $subresult['from_clause'] = $from_clause;
- }
- if (isset($group_by_clause)) {
- $subresult['group_by_clause'] = $group_by_clause;
- }
- if (isset($order_by_clause)) {
- $subresult['order_by_clause'] = $order_by_clause;
- }
- if (isset($having_clause)) {
- $subresult['having_clause'] = $having_clause;
- }
- if (isset($limit_clause)) {
- $subresult['limit_clause'] = $limit_clause;
- }
- if (isset($where_clause)) {
- $subresult['where_clause'] = $where_clause;
- }
- if (isset($unsorted_query) && !empty($unsorted_query)) {
- $subresult['unsorted_query'] = $unsorted_query;
- }
- if (isset($where_clause_identifiers)) {
- $subresult['where_clause_identifiers'] = $where_clause_identifiers;
- }
-
- if (isset($position_of_first_select)) {
- $subresult['position_of_first_select'] = $position_of_first_select;
- $subresult['section_before_limit'] = $section_before_limit;
- $subresult['section_after_limit'] = $section_after_limit;
- }
-
- // They are naughty and didn't have a trailing semi-colon,
- // then still handle it properly
- if ($subresult['querytype'] != '') {
- $result[] = $subresult;
- }
- return $result;
-} // end of the "PMA_SQP_analyze()" function
-
-
-/**
- * Formats SQL queries
- *
- * @param array $arr The SQL queries
- * @param string $mode formatting mode
- * @param integer $start_token starting token
- * @param integer $number_of_tokens number of tokens to format, -1 = all
- *
- * @return string The formatted SQL queries
- *
- * @access public
- */
-function PMA_SQP_format(
- $arr, $mode='text', $start_token=0,
- $number_of_tokens=-1
-) {
- //DEBUG echo 'in Format<pre>'; print_r($arr); echo '</pre>';
- // then check for an array
- if (! is_array($arr)) {
- return htmlspecialchars($arr);
- }
- // first check for the SQL parser having hit an error
- if (PMA_SQP_isError()) {
- return htmlspecialchars($arr['raw']);
- }
- // else do it properly
- switch ($mode) {
- case 'query_only':
- $str = '';
- $html_line_break = "\n";
- break;
- case 'text':
- $str = '';
- $html_line_break = '<br />';
- break;
- } // end switch
- $indent = 0;
- $bracketlevel = 0;
- $functionlevel = 0;
- $infunction = false;
- $space_punct_listsep = ' ';
- $space_punct_listsep_function_name = ' ';
- // $space_alpha_reserved_word = '<br />'."\n";
- $space_alpha_reserved_word = ' ';
-
- $keywords_with_brackets_1before = array(
- 'INDEX' => 1,
- 'KEY' => 1,
- 'ON' => 1,
- 'USING' => 1
- );
-
- $keywords_with_brackets_2before = array(
- 'IGNORE' => 1,
- 'INDEX' => 1,
- 'INTO' => 1,
- 'KEY' => 1,
- 'PRIMARY' => 1,
- 'PROCEDURE' => 1,
- 'REFERENCES' => 1,
- 'UNIQUE' => 1,
- 'USE' => 1
- );
-
- // These reserved words do NOT get a newline placed near them.
- $keywords_no_newline = array(
- 'AS' => 1,
- 'ASC' => 1,
- 'DESC' => 1,
- 'DISTINCT' => 1,
- 'DUPLICATE' => 1,
- 'HOUR' => 1,
- 'INTERVAL' => 1,
- 'IS' => 1,
- 'LIKE' => 1,
- 'NOT' => 1,
- 'NULL' => 1,
- 'ON' => 1,
- 'REGEXP' => 1
- );
-
- // These reserved words introduce a privilege list
- $keywords_priv_list = array(
- 'GRANT' => 1,
- 'REVOKE' => 1
- );
-
- if ($number_of_tokens == -1) {
- $number_of_tokens = $arr['len'];
- }
- $typearr = array();
- if ($number_of_tokens >= 0) {
- $typearr[0] = '';
- $typearr[1] = '';
- $typearr[2] = '';
- $typearr[3] = $arr[$start_token]['type'];
- }
-
- $in_priv_list = false;
- for ($i = $start_token; $i < $number_of_tokens; $i++) {
- // DEBUG echo "Loop format <strong>" . $arr[$i]['data']
- // . "</strong> " . $arr[$i]['type'] . "<br />";
- $before = '';
- $after = '';
- // array_shift($typearr);
- /*
- 0 prev2
- 1 prev
- 2 current
- 3 next
- */
- if (($i + 1) < $number_of_tokens) {
- $typearr[4] = $arr[$i + 1]['type'];
- } else {
- $typearr[4] = '';
- }
-
- for ($j=0; $j<4; $j++) {
- $typearr[$j] = $typearr[$j + 1];
- }
-
- switch ($typearr[2]) {
- case 'alpha_bitfield_constant_introducer':
- $before = ' ';
- $after = '';
- break;
- case 'white_newline':
- $before = '';
- break;
- case 'punct_bracket_open_round':
- $bracketlevel++;
- $infunction = false;
- $keyword_brackets_2before = isset(
- $keywords_with_brackets_2before[
- /*overload*/mb_strtoupper($arr[$i - 2]['data'])
- ]
- );
- $keyword_brackets_1before = isset(
- $keywords_with_brackets_1before[
- /*overload*/mb_strtoupper($arr[$i - 1]['data'])
- ]
- );
- // Make sure this array is sorted!
- if (($typearr[1] == 'alpha_functionName')
- || ($typearr[1] == 'alpha_columnType') || ($typearr[1] == 'punct')
- || ($typearr[3] == 'digit_integer') || ($typearr[3] == 'digit_hex')
- || ($typearr[3] == 'digit_float')
- || ($typearr[0] == 'alpha_reservedWord' && $keyword_brackets_2before)
- || ($typearr[1] == 'alpha_reservedWord' && $keyword_brackets_1before)
- ) {
- $functionlevel++;
- $infunction = true;
- $after .= ' ';
- } else {
- $indent++;
- if ($mode != 'query_only') {
- $after .= '<div class="syntax_indent' . $indent . '">';
- } else {
- $after .= ' ';
- }
- }
- break;
- case 'alpha_identifier':
- if (($typearr[1] == 'punct_qualifier')
- || ($typearr[3] == 'punct_qualifier')
- ) {
- $after = '';
- $before = '';
- }
- // for example SELECT 1 somealias
- if ($typearr[1] == 'digit_integer') {
- $before = ' ';
- }
- if (($typearr[3] == 'alpha_columnType')
- || ($typearr[3] == 'alpha_identifier')
- ) {
- $after .= ' ';
- }
- break;
- case 'punct_user':
- case 'punct_qualifier':
- $before = '';
- $after = '';
- break;
- case 'punct_listsep':
- if ($infunction == true) {
- $after .= $space_punct_listsep_function_name;
- } else {
- $after .= $space_punct_listsep;
- }
- break;
- case 'punct_queryend':
- if (($typearr[3] != 'comment_mysql')
- && ($typearr[3] != 'comment_ansi')
- && $typearr[3] != 'comment_c'
- ) {
- $after .= $html_line_break;
- $after .= $html_line_break;
- }
- $space_punct_listsep = ' ';
- $space_punct_listsep_function_name = ' ';
- $space_alpha_reserved_word = ' ';
- $in_priv_list = false;
- break;
- case 'comment_mysql':
- case 'comment_ansi':
- $after .= $html_line_break;
- break;
- case 'punct':
- $before .= ' ';
-
- // workaround for
- // select * from mytable limit 0,-1
- // (a side effect of this workaround is that
- // select 20 - 9
- // becomes
- // select 20 -9
- // )
- if ($typearr[3] != 'digit_integer') {
- $after .= ' ';
- }
- break;
- case 'punct_bracket_close_round':
- // only close bracket level when it was opened before
- if ($bracketlevel > 0) {
- $bracketlevel--;
- if ($infunction == true) {
- $functionlevel--;
- $after .= ' ';
- $before .= ' ';
- } else {
- $indent--;
- $before .= ($mode != 'query_only' ? '</div>' : ' ');
- }
- $infunction = ($functionlevel > 0) ? true : false;
- }
- break;
- case 'alpha_columnType':
- if ($typearr[3] == 'alpha_columnAttrib') {
- $after .= ' ';
- }
- if ($typearr[1] == 'alpha_columnType') {
- $before .= ' ';
- }
- break;
- case 'alpha_columnAttrib':
-
- // ALTER TABLE tbl_name AUTO_INCREMENT = 1
- // COLLATE LATIN1_GENERAL_CI DEFAULT
- if ($typearr[1] == 'alpha_identifier'
- || $typearr[1] == 'alpha_charset'
- ) {
- $before .= ' ';
- }
- if (($typearr[3] == 'alpha_columnAttrib')
- || ($typearr[3] == 'quote_single')
- || ($typearr[3] == 'digit_integer')
- ) {
- $after .= ' ';
- }
- // workaround for
- // AUTO_INCREMENT = 31DEFAULT_CHARSET = utf-8
-
- if ($typearr[2] == 'alpha_columnAttrib'
- && $typearr[3] == 'alpha_reservedWord'
- ) {
- $before .= ' ';
- }
- // workaround for
- // select * from mysql.user where binary user="root"
- // binary is marked as alpha_columnAttrib
- // but should be marked as a reserved word
- if (/*overload*/mb_strtoupper($arr[$i]['data']) == 'BINARY'
- && $typearr[3] == 'alpha_identifier'
- ) {
- $after .= ' ';
- }
- break;
- case 'alpha_functionName':
- break;
- case 'alpha_reservedWord':
- // do not uppercase the reserved word if we are calling
- // this function in query_only mode, because we need
- // the original query (otherwise we get problems with
- // semi-reserved words like "storage" which is legal
- // as an identifier name)
-
- if ($mode != 'query_only') {
- $arr[$i]['data'] = /*overload*/mb_strtoupper($arr[$i]['data']);
- }
-
- list($before, $in_priv_list) = PMA_SQP_getBeforeAndInPrivList(
- $arr, $typearr, $keywords_no_newline, $i, $in_priv_list,
- $space_alpha_reserved_word, $before, $keywords_priv_list
- );
-
- list($space_punct_listsep, $space_alpha_reserved_word)
- = PMA_SQP_getListsepAndReservedWord(
- $arr[$i]['data'], $in_priv_list, $html_line_break,
- $space_punct_listsep, $space_alpha_reserved_word
- );
-
- $after .= ' ';
- break;
- case 'digit_integer':
- case 'digit_float':
- case 'digit_hex':
- /**
- * @todo could there be other types preceding a digit?
- */
- if ($typearr[1] == 'alpha_reservedWord') {
- $after .= ' ';
- }
- if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
- $after .= ' ';
- }
- if ($typearr[1] == 'alpha_columnAttrib') {
- $before .= ' ';
- }
- break;
- case 'alpha_variable':
- $after = ' ';
- break;
- case 'quote_double':
- case 'quote_single':
- // workaround: for the query
- // REVOKE SELECT ON `base2\_db`.* FROM 'user'@'%'
- // the @ is incorrectly marked as alpha_variable
- // in the parser, and here, the '%' gets a blank before,
- // which is a syntax error
- if ($typearr[1] != 'punct_user'
- && $typearr[1] != 'alpha_bitfield_constant_introducer'
- ) {
- $before .= ' ';
- }
- if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
- $after .= ' ';
- }
- break;
- case 'quote_backtick':
- // here we check for punct_user to handle correctly
- // DEFINER = `username`@`%`
- // where @ is the punct_user and `%` is the quote_backtick
- if ($typearr[3] != 'punct_qualifier'
- && $typearr[3] != 'alpha_variable'
- && $typearr[3] != 'punct_user'
- ) {
- $after .= ' ';
- }
- if ($typearr[1] != 'punct_qualifier'
- && $typearr[1] != 'alpha_variable'
- && $typearr[1] != 'punct_user'
- ) {
- $before .= ' ';
- }
- break;
- default:
- break;
- } // end switch ($typearr[2])
-
- /*
- if ($typearr[3] != 'punct_qualifier') {
- $after .= ' ';
- }
- $after .= "\n";
- */
- $str .= $before;
- if ($mode == 'text') {
- $str .= htmlspecialchars($arr[$i]['data']);
- } else {
- $str .= $arr[$i]['data'];
- }
- $str .= $after;
- } // end for
- // close unclosed indent levels
- while ($indent > 0) {
- $indent--;
- $str .= ($mode != 'query_only' ? '</div>' : ' ');
- }
-
- return $str;
-} // end of the "PMA_SQP_format()" function
-
-/**
- * Define variables for PMA_SQP_format
- *
- * @param array $arr The SQL queries
- * @param array $typearr Types
- * @param array $keywords_no_newline Reserved words without newline placed
- * near them
- * @param int $index Index in $arr
- * @param boolean $in_priv_list Is in privilege list
- * @param string $space_alpha_reserved_word Reserved word separator
- * @param string $before String before
- * @param array $keywords_priv_list Keywords list of privileges
- *
- * @return array
- */
-function PMA_SQP_getBeforeAndInPrivList(
- $arr, $typearr, $keywords_no_newline, $index, $in_priv_list,
- $space_alpha_reserved_word, $before, $keywords_priv_list
-) {
- if (!((($typearr[1] != 'alpha_reservedWord')
- || (($typearr[1] == 'alpha_reservedWord')
- && isset($keywords_no_newline[/*overload*/mb_strtoupper($arr[$index - 1]['data'])])))
- && ($typearr[1] != 'punct_level_plus')
- && (!isset($keywords_no_newline[$arr[$index]['data']])))
- ) {
- $before .= ' ';
- return array($before, $in_priv_list);
- }
-
- // do not put a space before the first token, because
- // we use a lot of pattern matching checking for the
- // first reserved word at beginning of query
- // so do not put a newline before
- //
- // also we must not be inside a privilege list
- if ($index > 0) {
- // the alpha_identifier exception is there to
- // catch cases like
- // GRANT SELECT ON mydb.mytable TO myuser@localhost
- // (else, we get mydb.mytableTO)
- //
- // the quote_single exception is there to
- // catch cases like
- // GRANT ... TO 'marc'@'domain.com' IDENTIFIED...
- /**
- * @todo fix all cases and find why this happens
- */
-
- if (!$in_priv_list
- || in_array(
- $typearr[1],
- array('alpha_identifier', 'quote_single', 'white_newline')
- )
- ) {
- $before .= $space_alpha_reserved_word;
- }
- return array($before, $in_priv_list);
- }
-
- // on first keyword, check if it introduces a
- // privilege list
- if (isset($keywords_priv_list[$arr[$index]['data']])) {
- $in_priv_list = true;
- }
- return array($before, $in_priv_list);
-}
-
-/**
- * Define variables for PMA_SQP_format
- *
- * @param string $data Data to check
- * @param boolean $in_priv_list In privilege list
- * @param string $html_line_break HTML line break
- * @param string $space_punct_listsep List separator
- * @param string $space_alpha_reserved_word Space between reserved words
- *
- * @todo check definition of $space_punct_listsep and $space_alpha_reserved_word
- *
- * @return array Variables needed by PMA_SQP_format
- */
-function PMA_SQP_getListsepAndReservedWord(
- $data, $in_priv_list, $html_line_break, $space_punct_listsep,
- $space_alpha_reserved_word
-) {
- switch ($data) {
- case 'CREATE':
- case 'ALTER':
- case 'DROP':
- case 'RENAME';
- case 'TRUNCATE':
- case 'ANALYZE':
- case 'ANALYSE':
- case 'OPTIMIZE':
- if (!$in_priv_list) {
- $space_punct_listsep = $html_line_break;
- $space_alpha_reserved_word = ' ';
- }
- break;
- case 'EVENT':
- case 'TABLESPACE':
- case 'TABLE':
- case 'FUNCTION':
- case 'INDEX':
- case 'PROCEDURE':
- case 'SERVER':
- case 'TRIGGER':
- case 'DATABASE':
- case 'VIEW':
- case 'GROUP':
- break;
- case 'SET':
- if (!$in_priv_list) {
- $space_punct_listsep = $html_line_break;
- $space_alpha_reserved_word = ' ';
- }
- break;
- case 'EXPLAIN':
- case 'DESCRIBE':
- case 'DELETE':
- case 'SHOW':
- case 'UPDATE':
- if (!$in_priv_list) {
- $space_punct_listsep = $html_line_break;
- $space_alpha_reserved_word = ' ';
- }
- break;
- case 'INSERT':
- case 'REPLACE':
- if (!$in_priv_list) {
- $space_punct_listsep = $html_line_break;
- $space_alpha_reserved_word = $html_line_break;
- }
- break;
- case 'VALUES':
- $space_punct_listsep = ' ';
- $space_alpha_reserved_word = $html_line_break;
- break;
- case 'SELECT':
- $space_punct_listsep = ' ';
- $space_alpha_reserved_word = $html_line_break;
- break;
- case 'CALL':
- case 'DO':
- case 'HANDLER':
- break;
- default:
- break;
- }
- return array($space_punct_listsep, $space_alpha_reserved_word);
-}
-
-/**
- * Gets SQL queries with no format
- *
- * @param array $arr The SQL queries list
- *
- * @return string The SQL queries with no format
- *
- * @access public
- */
-function PMA_SQP_formatNone($arr)
-{
- $formatted_sql = htmlspecialchars($arr['raw']);
- $formatted_sql = preg_replace(
- "@((\015\012)|(\015)|(\012)){3,}@",
- "\n\n",
- $formatted_sql
- );
-
- return $formatted_sql;
-} // end of the "PMA_SQP_formatNone()" function
-
-/**
- * Checks whether a given name is MySQL reserved word
- *
- * @param string $column The word to be checked
- *
- * @return boolean whether true or false
- */
-function PMA_SQP_isKeyWord($column)
-{
- global $PMA_SQPdata_forbidden_word;
- return in_array(
- /*overload*/mb_strtoupper($column),
- $PMA_SQPdata_forbidden_word
- );
-}
-
-/**
- * Get Parser Data Map from sqlparser.data.php
- *
- * @return Array Parser Data Map from sqlparser.data.php
- */
-function PMA_SQP_getParserDataMap()
-{
- include 'libraries/sqlparser.data.php';
- return array(
- 'PMA_SQPdata_function_name' => $PMA_SQPdata_function_name,
- 'PMA_SQPdata_column_attrib' => $PMA_SQPdata_column_attrib,
- 'PMA_SQPdata_reserved_word' => $PMA_SQPdata_reserved_word,
- 'PMA_SQPdata_forbidden_word' => $PMA_SQPdata_forbidden_word,
- 'PMA_SQPdata_column_type' => $PMA_SQPdata_column_type,
- );
-}
-
-/**
- * Get Parser analyze Map from parse_analyze_inc.php
- *
- * @param array $sql_query The SQL string
- * @param array $db Current DB
- *
- * @return Array analyze Map from parse_analyze_inc.php
- */
-function PMA_SQP_getParserAnalyzeMap($sql_query, $db)
-{
- include 'libraries/parse_analyze.inc.php';
- return $analyzed_sql_results;
-}
-
-/**
- * Get Aliases from select query
- * Note: only useful for select query on single table.
- *
- * @param string $select_query The Select SQL Query
- * @param string $db Current DB
- *
- * @return Array alias information from select query
- */
-function PMA_SQP_getAliasesFromQuery($select_query, $db)
-{
- if (empty($select_query) || empty($db)) {
- return array();
- }
- $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($select_query));
- $aliases = array(
- $db => array(
- 'alias' => null,
- 'tables' => array()
- )
- );
- foreach ($analyzed_sql[0]['table_ref'] as $table) {
- $t_db = !empty($table['db']) ? $table['db'] : $db;
- if (!isset($aliases[$t_db])) {
- $aliases[$t_db] = array(
- 'alias' => null,
- 'tables' => array()
- );
- }
- $aliases[$t_db]['tables'][$table['table_true_name']] = array(
- 'alias' => !empty($table['table_alias'])
- ? $table['table_alias'] : null,
- 'columns' => array()
- );
- }
- foreach ($analyzed_sql[0]['select_expr'] as $cols) {
- if (!empty($cols['alias'])) {
- $t_db = !empty($cols['db']) ? $cols['db'] : $db;
- if (!empty($cols['table_true_name'])) {
- $aliases[$t_db]['tables'][$cols['table_true_name']]
- ['columns'][$cols['column']] = $cols['alias'];
- } else {
- foreach ($aliases[$t_db]['tables'] as $key => $table) {
- $aliases[$t_db]['tables'][$key]
- ['columns'][$cols['column']] = $cols['alias'];
- }
- }
- }
- }
- return $aliases;
-}
-
-?>
diff --git a/libraries/structure.lib.php b/libraries/structure.lib.php
deleted file mode 100644
index bc5a13d17a..0000000000
--- a/libraries/structure.lib.php
+++ /dev/null
@@ -1,3297 +0,0 @@
-<?php
-
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * set of functions for structure section in pma
- *
- * @package PhpMyAdmin
- */
-if (!defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Get the HTML links for action links
- * Actions are, Browse, Search, Browse table label, empty table
- *
- * @param array $current_table current table
- * @param boolean $table_is_view Is table view or not
- * @param string $tbl_url_query table url query
- * @param array $titles titles and icons for action links
- * @param string $truename table name
- * @param boolean $db_is_system_schema is database information schema or not
- * @param string $url_query url query
- *
- * @return array ($browse_table, $search_table, $browse_table_label, $empty_table,
- * $tracking_icon)
- */
-function PMA_getHtmlForActionLinks($current_table, $table_is_view, $tbl_url_query,
- $titles, $truename, $db_is_system_schema, $url_query
-) {
- $empty_table = '';
-
- if ($current_table['TABLE_ROWS'] > 0 || $table_is_view) {
- $may_have_rows = true;
- } else {
- $may_have_rows = false;
- }
-
- $browse_table = '<a href="sql.php' . $tbl_url_query . '&amp;pos=0">';
- if ($may_have_rows) {
- $browse_table .= $titles['Browse'];
- } else {
- $browse_table .= $titles['NoBrowse'];
- }
- $browse_table .= '</a>';
-
- $search_table = '<a href="tbl_select.php' . $tbl_url_query . '">';
- if ($may_have_rows) {
- $search_table .= $titles['Search'];
- } else {
- $search_table .= $titles['NoSearch'];
- }
- $search_table .= '</a>';
-
- $browse_table_label = '<a href="sql.php' . $tbl_url_query
- . '&amp;pos=0" title="'
- . htmlspecialchars($current_table['TABLE_COMMENT']) . '">'
- . $truename . '</a>';
-
- if (!$db_is_system_schema) {
- $empty_table = '<a class="truncate_table_anchor ajax"';
- $empty_table .= ' href="sql.php' . $tbl_url_query
- . '&amp;sql_query=';
- $empty_table .= urlencode(
- 'TRUNCATE ' . PMA_Util::backquote($current_table['TABLE_NAME'])
- );
- $empty_table .= '&amp;message_to_show='
- . urlencode(
- sprintf(
- __('Table %s has been emptied.'),
- htmlspecialchars($current_table['TABLE_NAME'])
- )
- )
- . '">';
- if ($may_have_rows) {
- $empty_table .= $titles['Empty'];
- } else {
- $empty_table .= $titles['NoEmpty'];
- }
- $empty_table .= '</a>';
- // truncating views doesn't work
- if ($table_is_view) {
- $empty_table = '&nbsp;';
- }
- }
-
- $tracking_icon = '';
- if (PMA_Tracker::isActive()) {
- if (PMA_Tracker::isTracked($GLOBALS["db"], $truename)) {
- $tracking_icon = '<a href="tbl_tracking.php' . $url_query
- . '&amp;table=' . $truename . '">'
- . PMA_Util::getImage(
- 'eye.png', __('Tracking is active.')
- )
- . '</a>';
- } elseif (PMA_Tracker::getVersion($GLOBALS["db"], $truename) > 0) {
- $tracking_icon = '<a href="tbl_tracking.php' . $url_query
- . '&amp;table=' . $truename . '">'
- . PMA_Util::getImage(
- 'eye_grey.png', __('Tracking is not active.')
- )
- . '</a>';
- }
- }
-
- return array($browse_table,
- $search_table,
- $browse_table_label,
- $empty_table,
- $tracking_icon
- );
-}
-
-/**
- * Get table drop query and drop message
- *
- * @param boolean $table_is_view Is table view or not
- * @param string $current_table current table
- *
- * @return array ($drop_query, $drop_message)
- */
-function PMA_getTableDropQueryAndMessage($table_is_view, $current_table)
-{
- $drop_query = 'DROP '
- . (($table_is_view || $current_table['ENGINE'] == null) ? 'VIEW' : 'TABLE')
- . ' ' . PMA_Util::backquote(
- $current_table['TABLE_NAME']
- );
- $drop_message = sprintf(
- (($table_is_view || $current_table['ENGINE'] == null)
- ? __('View %s has been dropped.')
- : __('Table %s has been dropped.')),
- str_replace(
- ' ',
- '&nbsp;',
- htmlspecialchars($current_table['TABLE_NAME'])
- )
- );
- return array($drop_query, $drop_message);
-}
-
-/**
- * Get HTML body for table summery
- *
- * @param integer $num_tables number of tables
- * @param boolean $server_slave_status server slave state
- * @param boolean $db_is_system_schema whether database is information schema or not
- * @param integer $sum_entries sum entries
- * @param string $db_collation collation of given db
- * @param boolean $is_show_stats whether stats is show or not
- * @param double $sum_size sum size
- * @param double $overhead_size overhead size
- * @param string $create_time_all create time
- * @param string $update_time_all update time
- * @param string $check_time_all check time
- * @param boolean $approx_rows whether any table has approx row count or not
- *
- * @return string $html_output
- */
-function PMA_getHtmlBodyForTableSummary($num_tables, $server_slave_status,
- $db_is_system_schema, $sum_entries, $db_collation, $is_show_stats,
- $sum_size, $overhead_size, $create_time_all, $update_time_all,
- $check_time_all, $approx_rows
-) {
- $html_output = '<tbody id="tbl_summary_row">'
- . '<tr><th></th>';
- $html_output .= '<th class="tbl_num nowrap">';
- $html_output .= sprintf(
- _ngettext('%s table', '%s tables', $num_tables),
- PMA_Util::formatNumber($num_tables, 0)
- );
- $html_output .= '</th>';
-
- if ($server_slave_status) {
- $html_output .= '<th>' . __('Replication') . '</th>' . "\n";
- }
- $sum_colspan = ($db_is_system_schema ? 4 : 7);
- if ($GLOBALS['cfg']['NumFavoriteTables'] == 0) {
- $sum_colspan--;
- }
- $html_output .= '<th colspan="' . $sum_colspan . '">'
- . __('Sum')
- . '</th>';
-
- $row_count_sum = PMA_Util::formatNumber($sum_entries, 0);
- // If a table shows approximate rows count, display update-all-real-count anchor.
- $row_sum_url = array();
- if (isset($approx_rows)) {
- $row_sum_url = array(
- 'ajax_request' => true,
- 'db' => $GLOBALS['db'],
- 'real_row_count' => 'true',
- 'real_row_count_all' => 'true'
- );
- }
- $cell_text = ($approx_rows)
- ? '<a href="db_structure.php' . PMA_URL_getCommon($row_sum_url)
- . '" class="ajax row_count_sum">' . '~' . $row_count_sum . '</a>'
- : $row_count_sum;
- $html_output .= '<th class="value tbl_rows">'
- . $cell_text
- . '</th>';
-
- if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) {
- $default_engine = $GLOBALS['dbi']->fetchValue(
- 'SHOW VARIABLES LIKE \'storage_engine\';',
- 0,
- 1
- );
- $html_output .= '<th class="center">' . "\n"
- . '<dfn title="'
- . sprintf(
- __('%s is the default storage engine on this MySQL server.'),
- $default_engine
- )
- . '">' . $default_engine . '</dfn></th>' . "\n";
- // we got a case where $db_collation was empty
- $html_output .= '<th>' . "\n";
-
- if (! empty($db_collation)) {
- $html_output .= '<dfn title="'
- . PMA_getCollationDescr($db_collation)
- . ' (' . __('Default') . ')">'
- . $db_collation
- . '</dfn>';
- }
- $html_output .= '</th>';
- }
- if ($is_show_stats) {
- list($sum_formatted, $unit) = PMA_Util::formatByteDown(
- $sum_size, 3, 1
- );
- list($overhead_formatted, $overhead_unit)
- = PMA_Util::formatByteDown($overhead_size, 3, 1);
-
- $html_output .= '<th class="value tbl_size">'
- . $sum_formatted . ' ' . $unit
- . '</th>';
- $html_output .= '<th class="value tbl_overhead">'
- . $overhead_formatted . ' ' . $overhead_unit
- . '</th>';
- }
-
- if ($GLOBALS['cfg']['ShowDbStructureCreation']) {
- $html_output .= '<th class="value tbl_creation">' . "\n"
- . ' '
- . ($create_time_all
- ? PMA_Util::localisedDate(strtotime($create_time_all))
- : '-'
- )
- . '</th>';
- }
-
- if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) {
- $html_output .= '<th class="value tbl_last_update">' . "\n"
- . ' '
- . ($update_time_all
- ? PMA_Util::localisedDate(strtotime($update_time_all))
- : '-'
- )
- . '</th>';
- }
-
- if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) {
- $html_output .= '<th class="value tbl_last_check">' . "\n"
- . ' '
- . ($check_time_all
- ? PMA_Util::localisedDate(strtotime($check_time_all))
- : '-'
- )
- . '</th>';
- }
- $html_output .= '</tr>'
- . '</tbody>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for "check all" check box with "with selected" dropdown
- *
- * @param string $pmaThemeImage pma theme image url
- * @param string $text_dir url for text directory
- * @param string $overhead_check overhead check
- * @param boolean $db_is_system_schema whether database is information schema or not
- * @param array $hidden_fields hidden fields
- *
- * @return string $html_output
- */
-function PMA_getHtmlForCheckAllTables($pmaThemeImage, $text_dir,
- $overhead_check, $db_is_system_schema, $hidden_fields
-) {
- $html_output = '<div class="clearfloat">';
- $html_output .= '<img class="selectallarrow" '
- . 'src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png" '
- . 'width="38" height="22" alt="' . __('With selected:') . '" />';
-
- $html_output .= '<input type="checkbox" id="tablesForm_checkall" '
- . 'class="checkall_box" title="' . __('Check All') . '" />';
- $html_output .= '<label for="tablesForm_checkall">' . __('Check All')
- . '</label>';
-
- if ($overhead_check != '') {
- $html_output .= PMA_getHtmlForCheckTablesHavingOverheadlink(
- $overhead_check
- );
- }
-
- $html_output .= '<select name="submit_mult" class="autosubmit" '
- . 'style="margin: 0 3em 0 3em;">';
-
- $html_output .= '<option value="' . __('With selected:')
- . '" selected="selected">'
- . __('With selected:') . '</option>' . "\n";
- $html_output .= '<option value="show_create" >'
- . __('Show create') . '</option>' . "\n";
- $html_output .= '<option value="export" >'
- . __('Export') . '</option>' . "\n";
- $html_output .= '<option value="print" >'
- . __('Print view') . '</option>' . "\n";
-
- if (!$db_is_system_schema
- && !$GLOBALS['cfg']['DisableMultiTableMaintenance']
- ) {
- $html_output .= '<option value="empty_tbl" >'
- . __('Empty') . '</option>' . "\n";
- $html_output .= '<option value="drop_tbl" >'
- . __('Drop') . '</option>' . "\n";
- $html_output .= '<option value="check_tbl" >'
- . __('Check table') . '</option>' . "\n";
- if (!PMA_DRIZZLE) {
- $html_output .= '<option value="optimize_tbl" >'
- . __('Optimize table') . '</option>' . "\n";
- $html_output .= '<option value="repair_tbl" >'
- . __('Repair table') . '</option>' . "\n";
- }
- $html_output .= '<option value="analyze_tbl" >'
- . __('Analyze table') . '</option>' . "\n";
- $html_output .= '<option value="add_prefix_tbl" >'
- . __('Add prefix to table') . '</option>' . "\n";
- $html_output .= '<option value="replace_prefix_tbl" >'
- . __('Replace table prefix') . '</option>' . "\n";
- $html_output .= '<option value="copy_tbl_change_prefix" >'
- . __('Copy table with prefix') . '</option>' . "\n";
- if (isset($GLOBALS['cfgRelation']['central_columnswork'])
- && $GLOBALS['cfgRelation']['central_columnswork']
- ) {
- $html_output .= '<option value="sync_unique_columns_central_list" >'
- . __('Add columns to central list') . '</option>' . "\n";
- $html_output .= '<option value="delete_unique_columns_central_list" >'
- . __('Remove columns from central list') . '</option>' . "\n";
- $html_output .= '<option value="make_consistent_with_central_list" >'
- . __('Make consistent with central list') . '</option>' . "\n";
- }
- }
- $html_output .= '</select>'
- . implode("\n", $hidden_fields) . "\n";
- $html_output .= '</div>';
-
- return $html_output;
-}
-
-/**
- * Get HTML code for "Check tables having overhead" link
- *
- * @param string $overhead_check overhead check
- *
- * @return string $html_output
- */
-function PMA_getHtmlForCheckTablesHavingOverheadlink($overhead_check)
-{
- return ' / '
- . '<a href="#" onclick="unMarkAllRows(\'tablesForm\');'
- . $overhead_check . 'return false;">'
- . __('Check tables having overhead')
- . '</a>';
-}
-
-
-/**
- * Get HTML links for "Print view" options
- *
- * @param string $url_query url query
- *
- * @return string $html_output
- */
-function PMA_getHtmlForTablePrintViewLink($url_query)
-{
- return '<p>'
- . '<a href="db_printview.php' . $url_query . '" target="print_view">'
- . PMA_Util::getIcon(
- 'b_print.png',
- __('Print view'),
- true
- ) . '</a>';
-}
-
-/**
- * Get HTML links "Data Dictionary" options
- *
- * @param string $url_query url query
- *
- * @return string $html_output
- */
-function PMA_getHtmlForDataDictionaryLink($url_query)
-{
- return '<a href="db_datadict.php' . $url_query . '" target="print_view">'
- . PMA_Util::getIcon(
- 'b_tblanalyse.png',
- __('Data Dictionary'),
- true
- ) . '</a>'
- . '</p>';
-}
-
-/**
- * Get Time for Create time, update time and check time
- *
- * @param array $current_table current table
- * @param string $time_label Create_time, Update_time, Check_time
- * @param integer $time_all time
- *
- * @return array ($time, $time_all)
- */
-function PMA_getTimeForCreateUpdateCheck($current_table, $time_label, $time_all)
-{
- $showtable = PMA_Table::sGetStatusInfo(
- $GLOBALS['db'],
- $current_table['TABLE_NAME'],
- null,
- true
- );
- $time = isset($showtable[$time_label])
- ? $showtable[$time_label]
- : false;
-
- // show oldest creation date in summary row
- if ($time && (!$time_all || $time < $time_all)) {
- $time_all = $time;
- }
- return array($time, $time_all);
-}
-
-/**
- * Get HTML for each table row of the database structure table,
- * And this function returns $odd_row param also
- *
- * @param integer $curr current entry
- * @param boolean $odd_row whether row is odd or not
- * @param boolean $table_is_view whether table is view or not
- * @param array $current_table current table
- * @param string $browse_table_label browse table label action link
- * @param string $tracking_icon tracking icon
- * @param boolean $server_slave_status server slave state
- * @param string $browse_table browse table action link
- * @param string $tbl_url_query table url query
- * @param string $search_table search table action link
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param array $titles titles array
- * @param string $empty_table empty table action link
- * @param string $drop_query table drop query
- * @param string $drop_message table drop message
- * @param string $collation collation
- * @param string $formatted_size formatted size
- * @param string $unit unit
- * @param string $overhead overhead
- * @param string $create_time create time
- * @param string $update_time last update time
- * @param string $check_time last check time
- * @param boolean $is_show_stats whether stats is show or not
- * @param boolean $ignored ignored
- * @param boolean $do do
- * @param integer $colspan_for_structure colspan for structure
- *
- * @return array $html_output, $odd_row, $approx_rows
- */
-function PMA_getHtmlForStructureTableRow(
- $curr, $odd_row, $table_is_view, $current_table,
- $browse_table_label, $tracking_icon,$server_slave_status,
- $browse_table, $tbl_url_query, $search_table,
- $db_is_system_schema,$titles, $empty_table, $drop_query, $drop_message,
- $collation, $formatted_size, $unit, $overhead, $create_time, $update_time,
- $check_time,$is_show_stats, $ignored, $do, $colspan_for_structure
-) {
- global $db;
- $html_output = '<tr class="' . ($odd_row ? 'odd' : 'even');
- $odd_row = ! $odd_row;
- $html_output .= ($table_is_view ? ' is_view' : '')
- . '" id="row_tbl_' . $curr . '">';
-
- $html_output .= '<td class="center">'
- . '<input type="checkbox" name="selected_tbl[]" class="checkall" '
- . 'value="' . htmlspecialchars($current_table['TABLE_NAME']) . '" '
- . 'id="checkbox_tbl_' . $curr . '" /></td>';
-
- $html_output .= '<th>'
- . $browse_table_label
- . (! empty($tracking_icon) ? $tracking_icon : '')
- . '</th>';
-
- if ($server_slave_status) {
- $html_output .= '<td class="center">'
- . ($ignored
- ? PMA_Util::getImage('s_cancel.png', 'NOT REPLICATED')
- : '')
- . ($do
- ? PMA_Util::getImage('s_success.png', 'REPLICATED')
- : '')
- . '</td>';
- }
- //Favorite table anchor.
- if ($GLOBALS['cfg']['NumFavoriteTables'] > 0) {
- $html_output .= '<td class="center">'
- . PMA_getHtmlForFavoriteAnchor($db, $current_table, $titles)
- . '</td>';
- }
-
- $html_output .= '<td class="center">' . $browse_table . '</td>';
- $html_output .= '<td class="center">'
- . '<a href="tbl_structure.php' . $tbl_url_query . '">'
- . $titles['Structure'] . '</a></td>';
- $html_output .= '<td class="center">' . $search_table . '</td>';
-
- if (! $db_is_system_schema) {
- $html_output .= PMA_getHtmlForInsertEmptyDropActionLinks(
- $tbl_url_query, $table_is_view,
- $titles, $empty_table, $current_table, $drop_query, $drop_message
- );
- } // end if (! $db_is_system_schema)
-
- // there is a null value in the ENGINE
- // - when the table needs to be repaired, or
- // - when it's a view
- // so ensure that we'll display "in use" below for a table
- // that needs to be repaired
- $approx_rows = false;
- if (isset($current_table['TABLE_ROWS'])
- && ($current_table['ENGINE'] != null
- || $table_is_view)
- ) {
- list($html_view_table, $approx_rows) = PMA_getHtmlForNotNullEngineViewTable(
- $table_is_view, $current_table, $collation, $is_show_stats,
- $tbl_url_query, $formatted_size, $unit, $overhead, $create_time,
- $update_time, $check_time
- );
- $html_output .= $html_view_table;
- } elseif ($table_is_view) {
- $html_output .= PMA_getHtmlForViewTable($is_show_stats);
- } else {
- $html_output .= PMA_getHtmlForRepairtable(
- $colspan_for_structure,
- $db_is_system_schema
- );
- } // end if (isset($current_table['TABLE_ROWS'])) else
- $html_output .= '</tr>';
-
- return array($html_output, $odd_row, $approx_rows);
-}
-
-/**
- * Get HTML for Insert/Empty/Drop action links
- *
- * @param string $tbl_url_query table url query
- * @param boolean $table_is_view whether table is view or not
- * @param array $titles titles array
- * @param string $empty_table HTML link for empty table
- * @param array $current_table current table
- * @param string $drop_query query for drop table
- * @param string $drop_message table drop message
- *
- * @return string $html_output
- */
-function PMA_getHtmlForInsertEmptyDropActionLinks($tbl_url_query, $table_is_view,
- $titles, $empty_table, $current_table, $drop_query, $drop_message
-) {
- $html_output = '<td class="insert_table center">'
- . '<a href="tbl_change.php' . $tbl_url_query . '">'
- . $titles['Insert']
- . '</a></td>';
- $html_output .= '<td class="center">' . $empty_table . '</td>';
- $html_output .= '<td class="center">';
- $html_output .= '<a ';
- $html_output .= 'class="ajax drop_table_anchor';
- if ($table_is_view || $current_table['ENGINE'] == null) {
- // this class is used in db_structure.js to display the
- // correct confirmation message
- $html_output .= ' view';
- }
- $html_output .= '" ';
- $html_output .= 'href="sql.php' . $tbl_url_query
- . '&amp;reload=1&amp;purge=1&amp;sql_query='
- . urlencode($drop_query) . '&amp;message_to_show='
- . urlencode($drop_message) . '" >'
- . $titles['Drop'] . '</a></td>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for show stats
- *
- * @param string $tbl_url_query table url query
- * @param string $formatted_size formatted size
- * @param string $unit unit
- * @param string $overhead overhead
- *
- * @return string $html_output
- */
-function PMA_getHtmlForShowStats($tbl_url_query, $formatted_size,
- $unit, $overhead
-) {
- $html_output = '<td class="value tbl_size"><a '
- . 'href="tbl_structure.php' . $tbl_url_query . '#showusage" >'
- . '<span>' . $formatted_size . '</span> '
- . '<span class="unit">' . $unit . '</span>'
- . '</a></td>';
- $html_output .= '<td class="value tbl_overhead">' . $overhead . '</td>';
-
- return $html_output;
-}
-
-/**
- * Get HTML to show database structure creation, last update and last checkx time
- *
- * @param string $create_time create time
- * @param string $update_time last update time
- * @param string $check_time last check time
- *
- * @return string $html_output
- */
-function PMA_getHtmlForStructureTimes($create_time, $update_time, $check_time)
-{
- $html_output = '';
- if ($GLOBALS['cfg']['ShowDbStructureCreation']) {
- $html_output .= '<td class="value tbl_creation">'
- . ($create_time
- ? PMA_Util::localisedDate(strtotime($create_time))
- : '-' )
- . '</td>';
- } // end if
- if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) {
- $html_output .= '<td class="value tbl_last_update">'
- . ($update_time
- ? PMA_Util::localisedDate(strtotime($update_time))
- : '-' )
- . '</td>';
- } // end if
- if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) {
- $html_output .= '<td class="value tbl_last_check">'
- . ($check_time
- ? PMA_Util::localisedDate(strtotime($check_time))
- : '-' )
- . '</td>';
- }
- return $html_output;
-}
-
-/**
- * Get HTML for ENGINE value not null or view tables that are not empty tables
- *
- * @param boolean $table_is_view whether table is view
- * @param array $current_table current table
- * @param string $collation collation
- * @param boolean $is_show_stats whether stats show or not
- * @param string $tbl_url_query table url query
- * @param string $formatted_size formatted size
- * @param string $unit unit
- * @param string $overhead overhead
- * @param string $create_time create time
- * @param string $update_time update time
- * @param string $check_time check time
- *
- * @return string $html_output
- */
-function PMA_getHtmlForNotNullEngineViewTable($table_is_view, $current_table,
- $collation, $is_show_stats, $tbl_url_query, $formatted_size, $unit,
- $overhead, $create_time, $update_time, $check_time
-) {
- $html_output = '';
- $row_count_pre = '';
- $show_superscript = '';
- if ($table_is_view) {
- // Drizzle views use FunctionEngine, and the only place where they are
- // available are I_S and D_D schemas, where we do exact counting
- if ($current_table['TABLE_ROWS'] >= $GLOBALS['cfg']['MaxExactCountViews']
- && $current_table['ENGINE'] != 'FunctionEngine'
- ) {
- $row_count_pre = '~';
- $show_superscript = PMA_Util::showHint(
- PMA_sanitize(
- sprintf(
- __('This view has at least this number of rows. Please refer to %sdocumentation%s.'),
- '[doc@cfg_MaxExactCountViews]',
- '[/doc]'
- )
- )
- );
- }
- } elseif ($current_table['ENGINE'] == 'InnoDB'
- && (! $current_table['COUNTED'])
- ) {
- // InnoDB table: we did not get an accurate row count
- $row_count_pre = '~';
- $show_superscript = '';
- }
-
- // Set a flag if there are approximate row counts on page.
- if (! empty($row_count_pre)) {
- $approx_rows = true;
- } else {
- // this happens for information_schema, performance_schema,
- // and in case there is no InnoDB table on this page
- $approx_rows = false;
- }
- // Get the row count.
- $row_count = $row_count_pre
- . PMA_Util::formatNumber($current_table['TABLE_ROWS'], 0);
- // URL parameters to fetch the real row count.
- $real_count_url = array(
- 'ajax_request' => true,
- 'db' => $GLOBALS['db'],
- 'table' => $current_table['TABLE_NAME'],
- 'real_row_count' => 'true'
- );
- // Content to be appended into 'tbl_rows' cell.
- // If row count is approximate, display it as an anchor to get real count.
- $cell_text = (! empty($row_count_pre))
- ? '<a href="db_structure.php' . PMA_URL_getCommon($real_count_url)
- . '" class="ajax real_row_count">' . $row_count . '</a>'
- : $row_count;
- $html_output .= '<td class="value tbl_rows" data-table="'
- . htmlspecialchars($current_table['TABLE_NAME']) . '">'
- . $cell_text
- . $show_superscript
- . '</td>';
-
- if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) {
- $html_output .= '<td class="nowrap">'
- . ( ! empty($current_table['ENGINE'])
- ? $current_table['ENGINE']
- : ($table_is_view ? __('View') : '')
- )
- . '</td>';
- if (/*overload*/mb_strlen($collation)) {
- $html_output .= '<td class="nowrap">' . $collation . '</td>';
- }
- }
-
- if ($is_show_stats) {
- $html_output .= PMA_getHtmlForShowStats(
- $tbl_url_query, $formatted_size, $unit, $overhead
- );
- }
-
- $html_output .= PMA_getHtmlForStructureTimes(
- $create_time, $update_time, $check_time
- );
-
- return array($html_output, $approx_rows);
-}
-
-/**
- * Get HTML snippet view table
- *
- * @param boolean $is_show_stats whether stats show or not
- *
- * @return string $html_output
- */
-function PMA_getHtmlForViewTable($is_show_stats)
-{
- $html_output = '<td class="value">-</td>'
- . '<td>' . __('View') . '</td>'
- . '<td>---</td>';
- if ($is_show_stats) {
- $html_output .= '<td class="value">-</td>'
- . '<td class="value">-</td>';
- }
- return $html_output;
-}
-
-/**
- * display "in use" below for a table that needs to be repaired
- *
- * @param integer $colspan_for_structure colspan for structure
- * @param boolean $db_is_system_schema whether db is information schema or not
- *
- * @return string HTML snippet
- */
-function PMA_getHtmlForRepairtable(
- $colspan_for_structure,
- $db_is_system_schema
-) {
- return '<td colspan="'
- . ($colspan_for_structure - ($db_is_system_schema ? 5 : 8)) . '"'
- . 'class="center">'
- . __('in use')
- . '</td>';
-}
-
-/**
- * display table header (<table><thead>...</thead><tbody>)
- *
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param boolean $replication whether to sho replication status
- *
- * @return string html data
- */
-function PMA_tableHeader($db_is_system_schema = false, $replication = false)
-{
- $cnt = 0; // Let's count the columns...
-
- if ($db_is_system_schema) {
- $action_colspan = 3;
- } else {
- $action_colspan = 6;
- }
- if ($GLOBALS['cfg']['NumFavoriteTables'] > 0) {
- $action_colspan++;
- }
-
- $html_output = '<table class="data">' . "\n"
- . '<thead>' . "\n"
- . '<tr><th></th>' . "\n"
- . '<th>'
- . PMA_sortableTableHeader(__('Table'), 'table')
- . '</th>' . "\n";
- if ($replication) {
- $html_output .= '<th>' . "\n"
- . ' ' . __('Replication') . "\n"
- . '</th>';
- }
- $html_output .= '<th colspan="' . $action_colspan . '">' . "\n"
- . ' ' . __('Action') . "\n"
- . '</th>'
- // larger values are more interesting so default sort order is DESC
- . '<th>' . PMA_sortableTableHeader(__('Rows'), 'records', 'DESC')
- . PMA_Util::showHint(
- PMA_sanitize(
- __(
- 'May be approximate. Click on the number to get the exact'
- . ' count. See [doc@faq3-11]FAQ 3.11[/doc].'
- )
- )
- ) . "\n"
- . '</th>' . "\n";
- if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)) {
- $html_output .= '<th>' . PMA_sortableTableHeader(__('Type'), 'type')
- . '</th>' . "\n";
- $cnt++;
- $html_output .= '<th>'
- . PMA_sortableTableHeader(__('Collation'), 'collation')
- . '</th>' . "\n";
- $cnt++;
- }
- if ($GLOBALS['is_show_stats']) {
- // larger values are more interesting so default sort order is DESC
- $html_output .= '<th>'
- . PMA_sortableTableHeader(__('Size'), 'size', 'DESC')
- . '</th>' . "\n"
- // larger values are more interesting so default sort order is DESC
- . '<th>'
- . PMA_sortableTableHeader(__('Overhead'), 'overhead', 'DESC')
- . '</th>' . "\n";
- $cnt += 2;
- }
- if ($GLOBALS['cfg']['ShowDbStructureCreation']) {
- // larger values are more interesting so default sort order is DESC
- $html_output .= '<th>'
- . PMA_sortableTableHeader(__('Creation'), 'creation', 'DESC')
- . '</th>' . "\n";
- $cnt += 2;
- }
- if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) {
- // larger values are more interesting so default sort order is DESC
- $html_output .= '<th>'
- . PMA_sortableTableHeader(__('Last update'), 'last_update', 'DESC')
- . '</th>' . "\n";
- $cnt += 2;
- }
- if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) {
- // larger values are more interesting so default sort order is DESC
- $html_output .= '<th>'
- . PMA_sortableTableHeader(__('Last check'), 'last_check', 'DESC')
- . '</th>' . "\n";
- $cnt += 2;
- }
- $html_output .= '</tr>' . "\n";
- $html_output .= '</thead>' . "\n";
- $html_output .= '<tbody>' . "\n";
- $GLOBALS['colspan_for_structure'] = $cnt + $action_colspan + 3;
-
- return $html_output;
-}
-
-/**
- * Creates a clickable column header for table information
- *
- * @param string $title title to use for the link
- * @param string $sort corresponds to sortable data name mapped in
- * libraries/db_info.inc.php
- * @param string $initial_sort_order initial sort order
- *
- * @return string link to be displayed in the table header
- */
-function PMA_sortableTableHeader($title, $sort, $initial_sort_order = 'ASC')
-{
- // Set some defaults
- $requested_sort = 'table';
- $requested_sort_order = $future_sort_order = $initial_sort_order;
-
- // If the user requested a sort
- if (isset($_REQUEST['sort'])) {
- $requested_sort = $_REQUEST['sort'];
-
- if (isset($_REQUEST['sort_order'])) {
- $requested_sort_order = $_REQUEST['sort_order'];
- }
- }
-
- $order_img = '';
- $order_link_params = array();
- $order_link_params['title'] = __('Sort');
-
- // If this column was requested to be sorted.
- if ($requested_sort == $sort) {
- if ($requested_sort_order == 'ASC') {
- $future_sort_order = 'DESC';
- // current sort order is ASC
- $order_img = ' ' . PMA_Util::getImage(
- 's_asc.png',
- __('Ascending'),
- array('class' => 'sort_arrow', 'title' => '')
- );
- $order_img .= ' ' . PMA_Util::getImage(
- 's_desc.png',
- __('Descending'),
- array('class' => 'sort_arrow hide', 'title' => '')
- );
- // but on mouse over, show the reverse order (DESC)
- $order_link_params['onmouseover'] = "$('.sort_arrow').toggle();";
- // on mouse out, show current sort order (ASC)
- $order_link_params['onmouseout'] = "$('.sort_arrow').toggle();";
- } else {
- $future_sort_order = 'ASC';
- // current sort order is DESC
- $order_img = ' ' . PMA_Util::getImage(
- 's_asc.png',
- __('Ascending'),
- array('class' => 'sort_arrow hide', 'title' => '')
- );
- $order_img .= ' ' . PMA_Util::getImage(
- 's_desc.png',
- __('Descending'),
- array('class' => 'sort_arrow', 'title' => '')
- );
- // but on mouse over, show the reverse order (ASC)
- $order_link_params['onmouseover'] = "$('.sort_arrow').toggle();";
- // on mouse out, show current sort order (DESC)
- $order_link_params['onmouseout'] = "$('.sort_arrow').toggle();";
- }
- }
-
- $_url_params = array(
- 'db' => $_REQUEST['db'],
- );
-
- $url = 'db_structure.php' . PMA_URL_getCommon($_url_params);
- // We set the position back to 0 every time they sort.
- $url .= "&amp;pos=0&amp;sort=$sort&amp;sort_order=$future_sort_order";
- if (! empty($_REQUEST['tbl_type'])) {
- $url .= "&amp;tbl_type=" . $_REQUEST['tbl_type'];
- }
- if (! empty($_REQUEST['tbl_group'])) {
- $url .= "&amp;tbl_group=" . $_REQUEST['tbl_group'];
- }
-
- return PMA_Util::linkOrButton(
- $url, $title . $order_img, $order_link_params
- );
-}
-
-/**
- * Get the alias ant truname
- *
- * @param string $tooltip_aliasname tooltip alias name
- * @param array $current_table current table
- * @param string $tooltip_truename tooltip true name
- *
- * @return array ($alias, $truename)
- */
-function PMA_getAliasAndTrueName($tooltip_aliasname, $current_table,
- $tooltip_truename
-) {
- $alias = (! empty($tooltip_aliasname)
- && isset($tooltip_aliasname[$current_table['TABLE_NAME']])
- )
- ? str_replace(
- ' ', '&nbsp;',
- htmlspecialchars($tooltip_truename[$current_table['TABLE_NAME']])
- )
- : str_replace(
- ' ', '&nbsp;',
- htmlspecialchars($current_table['TABLE_NAME'])
- );
- $truename = (! empty($tooltip_truename)
- && isset($tooltip_truename[$current_table['TABLE_NAME']])
- )
- ? str_replace(
- ' ', '&nbsp;',
- htmlspecialchars($tooltip_truename[$current_table['TABLE_NAME']])
- )
- : str_replace(
- ' ', '&nbsp;',
- htmlspecialchars($current_table['TABLE_NAME'])
- );
-
- return array($alias, $truename);
-}
-
-/**
- * Get the server slave state
- *
- * @param boolean $server_slave_status server slave state
- * @param string $truename true name
- *
- * @return array ($do, $ignored)
- */
-function PMA_getServerSlaveStatus($server_slave_status, $truename)
-{
- $ignored = false;
- $do = false;
- include_once 'libraries/replication.inc.php';
-
- if (!$server_slave_status) {
- return array($do, $ignored);
- }
-
- $nbServSlaveDoDb = count($GLOBALS['replication_info']['slave']['Do_DB']);
- $nbServSlaveIgnoreDb
- = count($GLOBALS['replication_info']['slave']['Ignore_DB']);
- $searchDoDBInTruename = array_search(
- $truename, $GLOBALS['replication_info']['slave']['Do_DB']
- );
- $searchDoDBInDB = array_search(
- $GLOBALS['db'], $GLOBALS['replication_info']['slave']['Do_DB']
- );
- if (strlen($searchDoDBInTruename) > 0
- || strlen($searchDoDBInDB) > 0
- || ($nbServSlaveDoDb == 1 && $nbServSlaveIgnoreDb == 1)
- ) {
- $do = true;
- }
- foreach ($GLOBALS['replication_info']['slave']['Wild_Do_Table'] as $db_table) {
- $table_part = PMA_extractDbOrTable($db_table, 'table');
- $pattern = "@^"
- . /*overload*/mb_substr($table_part, 0, -1)
- . "@";
- if (($GLOBALS['db'] == PMA_extractDbOrTable($db_table, 'db'))
- && (preg_match($pattern, $truename))
- ) {
- $do = true;
- }
- }
-
- $searchDb = array_search(
- $GLOBALS['db'],
- $GLOBALS['replication_info']['slave']['Ignore_DB']
- );
- $searchTable = array_search(
- $truename,
- $GLOBALS['replication_info']['slave']['Ignore_Table']
- );
- if ((strlen($searchTable) > 0) || strlen($searchDb) > 0) {
- $ignored = true;
- }
- foreach (
- $GLOBALS['replication_info']['slave']['Wild_Ignore_Table'] as $db_table
- ) {
- $table_part = PMA_extractDbOrTable($db_table, 'table');
- $pattern = "@^"
- . /*overload*/mb_substr($table_part, 0, -1)
- . "@";
- if (($GLOBALS['db'] == PMA_extractDbOrTable($db_table))
- && (preg_match($pattern, $truename))
- ) {
- $ignored = true;
- }
- }
-
- return array($do, $ignored);
-}
-
-/**
- * Get the value set for ENGINE table,
- * $current_table, $formatted_size, $unit, $formatted_overhead,
- * $overhead_unit, $overhead_size, $table_is_view
- *
- * @param array $current_table current table
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param boolean $is_show_stats whether stats show or not
- * @param boolean $table_is_view whether table is view or not
- * @param double $sum_size total table size
- * @param double $overhead_size overhead size
- *
- * @return array
- */
-function PMA_getStuffForEngineTypeTable($current_table, $db_is_system_schema,
- $is_show_stats, $table_is_view, $sum_size, $overhead_size
-) {
- $formatted_size = '-';
- $unit = '';
- $formatted_overhead = '';
- $overhead_unit = '';
-
- switch ( $current_table['ENGINE']) {
- // MyISAM, ISAM or Heap table: Row count, data size and index size
- // are accurate; data size is accurate for ARCHIVE
- case 'MyISAM' :
- case 'ISAM' :
- case 'HEAP' :
- case 'MEMORY' :
- case 'ARCHIVE' :
- case 'Aria' :
- case 'Maria' :
- list($current_table, $formatted_size, $unit, $formatted_overhead,
- $overhead_unit, $overhead_size, $sum_size) = PMA_getValuesForAriaTable(
- $db_is_system_schema, $current_table, $is_show_stats,
- $sum_size, $overhead_size, $formatted_size, $unit,
- $formatted_overhead, $overhead_unit
- );
- break;
- case 'InnoDB' :
- case 'PBMS' :
- // InnoDB table: Row count is not accurate but data and index sizes are.
- // PBMS table in Drizzle: TABLE_ROWS is taken from table cache,
- // so it may be unavailable
- list($current_table, $formatted_size, $unit, $sum_size)
- = PMA_getValuesForInnodbTable($current_table, $is_show_stats, $sum_size);
- //$display_rows = ' - ';
- break;
- // Mysql 5.0.x (and lower) uses MRG_MyISAM
- // and MySQL 5.1.x (and higher) uses MRG_MYISAM
- // Both are aliases for MERGE
- case 'MRG_MyISAM' :
- case 'MRG_MYISAM' :
- case 'MERGE' :
- case 'BerkeleyDB' :
- // Merge or BerkleyDB table: Only row count is accurate.
- if ($is_show_stats) {
- $formatted_size = ' - ';
- $unit = '';
- }
- break;
- // for a view, the ENGINE is sometimes reported as null,
- // or on some servers it's reported as "SYSTEM VIEW"
- case null :
- case 'SYSTEM VIEW' :
- case 'FunctionEngine' :
- // possibly a view, do nothing
- break;
- default :
- // Unknown table type.
- if ($is_show_stats) {
- $formatted_size = __('unknown');
- $unit = '';
- }
- } // end switch
-
- if ($current_table['TABLE_TYPE'] == 'VIEW'
- || $current_table['TABLE_TYPE'] == 'SYSTEM VIEW'
- ) {
- // countRecords() takes care of $cfg['MaxExactCountViews']
- $current_table['TABLE_ROWS'] = PMA_Table::countRecords(
- $GLOBALS['db'], $current_table['TABLE_NAME'],
- true, true
- );
- $table_is_view = true;
- }
-
- return array($current_table, $formatted_size, $unit, $formatted_overhead,
- $overhead_unit, $overhead_size, $table_is_view, $sum_size
- );
-}
-
-/**
- * Get values for ARIA/MARIA tables
- * $current_table, $formatted_size, $unit, $formatted_overhead,
- * $overhead_unit, $overhead_size
- *
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param array $current_table current table
- * @param boolean $is_show_stats whether stats show or not
- * @param double $sum_size sum size
- * @param double $overhead_size overhead size
- * @param number $formatted_size formatted size
- * @param string $unit unit
- * @param number $formatted_overhead overhead formatted
- * @param string $overhead_unit overhead unit
- *
- * @return array
- */
-function PMA_getValuesForAriaTable($db_is_system_schema, $current_table,
- $is_show_stats, $sum_size, $overhead_size, $formatted_size, $unit,
- $formatted_overhead, $overhead_unit
-) {
- if ($db_is_system_schema) {
- $current_table['Rows'] = PMA_Table::countRecords(
- $GLOBALS['db'], $current_table['Name']
- );
- }
-
- if ($is_show_stats) {
- $tblsize = doubleval($current_table['Data_length'])
- + doubleval($current_table['Index_length']);
- $sum_size += $tblsize;
- list($formatted_size, $unit) = PMA_Util::formatByteDown(
- $tblsize, 3, ($tblsize > 0) ? 1 : 0
- );
- if (isset($current_table['Data_free']) && $current_table['Data_free'] > 0) {
- // here, the value 4 as the second parameter
- // would transform 6.1MiB into 6,224.6KiB
- list($formatted_overhead, $overhead_unit)
- = PMA_Util::formatByteDown(
- $current_table['Data_free'], 4,
- (($current_table['Data_free'] > 0) ? 1 : 0)
- );
- $overhead_size += $current_table['Data_free'];
- }
- }
- return array($current_table, $formatted_size, $unit, $formatted_overhead,
- $overhead_unit, $overhead_size, $sum_size
- );
-}
-
-/**
- * Get values for InnoDB table
- * $current_table, $formatted_size, $unit, $sum_size
- *
- * @param array $current_table current table
- * @param boolean $is_show_stats whether stats show or not
- * @param double $sum_size sum size
- *
- * @return array
- */
-function PMA_getValuesForInnodbTable($current_table, $is_show_stats, $sum_size)
-{
- $formatted_size = $unit = '';
-
- if (($current_table['ENGINE'] == 'InnoDB'
- && $current_table['TABLE_ROWS'] < $GLOBALS['cfg']['MaxExactCount'])
- || !isset($current_table['TABLE_ROWS'])
- ) {
- $current_table['COUNTED'] = true;
- $current_table['TABLE_ROWS'] = PMA_Table::countRecords(
- $GLOBALS['db'], $current_table['TABLE_NAME'],
- true, false
- );
- } else {
- $current_table['COUNTED'] = false;
- }
-
- // Drizzle doesn't provide data and index length, check for null
- if ($is_show_stats && $current_table['Data_length'] !== null) {
- $tblsize = $current_table['Data_length'] + $current_table['Index_length'];
- $sum_size += $tblsize;
- list($formatted_size, $unit) = PMA_Util::formatByteDown(
- $tblsize, 3, (($tblsize > 0) ? 1 : 0)
- );
- }
-
- return array($current_table, $formatted_size, $unit, $sum_size);
-}
-
-/**
- * table structure
- */
-
-/**
- * Get the HTML snippet for structure table table header
- *
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param boolean $tbl_is_view whether table is view or not
- *
- * @return string $html_output
- */
-function PMA_getHtmlForTableStructureHeader(
- $db_is_system_schema,
- $tbl_is_view
-) {
- $html_output = '<thead>';
- $html_output .= '<tr>';
- $html_output .= '<th></th>'
- . '<th>#</th>'
- . '<th>' . __('Name') . '</th>'
- . '<th>' . __('Type') . '</th>'
- . '<th>' . __('Collation') . '</th>'
- . '<th>' . __('Attributes') . '</th>'
- . '<th>' . __('Null') . '</th>'
- . '<th>' . __('Default') . '</th>'
- . '<th>' . __('Extra') . '</th>';
-
- /* see tbl_structure.js, function moreOptsMenuResize() */
- if (! $db_is_system_schema && ! $tbl_is_view) {
- $colspan = 9;
- if (PMA_DRIZZLE) {
- $colspan -= 2;
- }
- if (PMA_Util::showIcons('ActionLinksMode')) {
- $colspan--;
- }
- $html_output .= '<th colspan="' . $colspan . '" '
- . 'class="action">' . __('Action') . '</th>';
- }
- $html_output .= '</tr>'
- . '</thead>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for structure table's rows and return $odd_row parameter also
- * For "Action" Column, this function contains only HTML code for "Change"
- * and "Drop"
- *
- * @param array $row current row
- * @param string $rownum row number
- * @param string $displayed_field_name displayed field name
- * @param string $type_nowrap type nowrap
- * @param array $extracted_columnspec associative array containing type,
- * spec_in_brackets and possibly
- * enum_set_values (another array)
- * @param string $type_mime mime type
- * @param string $field_charset field charset
- * @param string $attribute attribute (BINARY, UNSIGNED,
- * UNSIGNED ZEROFILL,
- * on update CURRENT_TIMESTAMP)
- * @param boolean $tbl_is_view whether tables is view or not
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param string $url_query url query
- * @param string $field_encoded field encoded
- * @param array $titles titles array
- * @param string $table table
- *
- * @return array ($html_output, $odd_row)
- */
-function PMA_getHtmlTableStructureRow($row, $rownum,
- $displayed_field_name, $type_nowrap, $extracted_columnspec, $type_mime,
- $field_charset, $attribute, $tbl_is_view, $db_is_system_schema,
- $url_query, $field_encoded, $titles, $table
-) {
- $html_output = '<td class="center">'
- . '<input type="checkbox" class="checkall" name="selected_fld[]" '
- . 'value="' . htmlspecialchars($row['Field']) . '" '
- . 'id="checkbox_row_' . $rownum . '"/>'
- . '</td>';
-
- $html_output .= '<td class="right">'
- . $rownum
- . '</td>';
-
- $html_output .= '<th class="nowrap">'
- . '<label for="checkbox_row_' . $rownum . '">'
- . preg_replace(
- '/[\x00-\x1F]/',
- '&#x2051;',
- $displayed_field_name
- ) . '</label>'
- . '</th>';
-
- $html_output .= '<td' . $type_nowrap . '>'
- . '<bdo dir="ltr" lang="en">'
- . $extracted_columnspec['displayed_type'] . $type_mime
- . '</bdo></td>';
-
- $html_output .= '<td>' .
- (empty($field_charset)
- ? ''
- : '<dfn title="' . PMA_getCollationDescr($field_charset) . '">'
- . $field_charset . '</dfn>'
- )
- . '</td>';
-
- $html_output .= '<td class="column_attribute nowrap">'
- . $attribute . '</td>';
- $html_output .= '<td>'
- . (($row['Null'] == 'YES') ? __('Yes') : __('No')) . ' </td>';
-
- $html_output .= '<td class="nowrap">';
- if (isset($row['Default'])) {
- if ($extracted_columnspec['type'] == 'bit') {
- // here, $row['Default'] contains something like b'010'
- $html_output .= PMA_Util::convertBitDefaultValue($row['Default']);
- } else {
- $html_output .= $row['Default'];
- }
- } else {
- $html_output .= '<i>' . _pgettext('None for default', 'None') . '</i>';
- }
- $html_output .= '</td>';
-
- $html_output .= '<td class="nowrap">'
- . /*overload*/mb_strtoupper($row['Extra']) . '</td>';
-
- $html_output .= PMA_getHtmlForDropColumn(
- $tbl_is_view, $db_is_system_schema,
- $url_query, $field_encoded,
- $titles, $table, $row
- );
-
- return $html_output;
-}
-
-/**
- * Get HTML code for "Drop" Action link
- *
- * @param boolean $tbl_is_view whether tables is view or not
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param string $url_query url query
- * @param string $field_encoded field encoded
- * @param array $titles tittles array
- * @param string $table table
- * @param array $row current row
- *
- * @return string $html_output
- */
-function PMA_getHtmlForDropColumn($tbl_is_view, $db_is_system_schema,
- $url_query, $field_encoded, $titles, $table, $row
-) {
- $html_output = '';
-
- if (! $tbl_is_view && ! $db_is_system_schema) {
- $html_output .= '<td class="edit center">'
- . '<a class="change_column_anchor ajax"'
- . ' href="tbl_structure.php'
- . $url_query . '&amp;field=' . $field_encoded
- . '&amp;change_column=1">'
- . $titles['Change'] . '</a>' . '</td>';
- $html_output .= '<td class="drop center">'
- . '<a class="drop_column_anchor ajax"'
- . ' href="sql.php' . $url_query . '&amp;sql_query='
- . urlencode(
- 'ALTER TABLE ' . PMA_Util::backquote($table)
- . ' DROP ' . PMA_Util::backquote($row['Field']) . ';'
- )
- . '&amp;dropped_column=' . urlencode($row['Field'])
- . '&amp;message_to_show=' . urlencode(
- sprintf(
- __('Column %s has been dropped.'),
- htmlspecialchars($row['Field'])
- )
- ) . '" >'
- . $titles['Drop'] . '</a>'
- . '</td>';
- }
-
- return $html_output;
-}
-
-/**
- * Get HTML for "check all" check box with "with selected" actions in table
- * structure
- *
- * @param string $pmaThemeImage pma theme image url
- * @param string $text_dir test directory
- * @param boolean $tbl_is_view whether table is view or not
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param string $tbl_storage_engine table storage engine
- *
- * @return string $html_output
- */
-function PMA_getHtmlForCheckAllTableColumn($pmaThemeImage, $text_dir,
- $tbl_is_view, $db_is_system_schema, $tbl_storage_engine
-) {
- $html_output = PMA_Util::getWithSelected(
- $pmaThemeImage, $text_dir, "fieldsForm"
- );
-
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_browse',
- __('Browse'), 'b_browse.png', 'browse'
- );
-
- if (! $tbl_is_view && ! $db_is_system_schema) {
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit change_columns_anchor ajax',
- 'submit_mult_change', __('Change'), 'b_edit.png', 'change'
- );
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_drop',
- __('Drop'), 'b_drop.png', 'drop'
- );
- if ('ARCHIVE' != $tbl_storage_engine) {
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_primary',
- __('Primary'), 'b_primary.png', 'primary'
- );
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_unique',
- __('Unique'), 'b_unique.png', 'unique'
- );
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_index',
- __('Index'), 'b_index.png', 'index'
- );
- }
-
- if ((! empty($tbl_storage_engine) && $tbl_storage_engine == 'MYISAM')
- || PMA_MYSQL_INT_VERSION >= 50705
- ) {
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_spatial',
- __('Spatial'), 'b_spatial.png', 'spatial'
- );
- }
- if (! empty($tbl_storage_engine)
- && ($tbl_storage_engine == 'MYISAM'
- || $tbl_storage_engine == 'ARIA'
- || $tbl_storage_engine == 'MARIA')
- ) {
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_fulltext',
- __('Fulltext'), 'b_ftext.png', 'ftext'
- );
- }
- if (isset($GLOBALS['cfgRelation']['central_columnswork'])
- && $GLOBALS['cfgRelation']['central_columnswork']
- ) {
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_central_columns_add',
- __('Add to central columns'), 'centralColumns_add.png',
- 'add_to_central_columns'
- );
- $html_output .= PMA_Util::getButtonOrImage(
- 'submit_mult', 'mult_submit', 'submit_mult_central_columns_remove',
- __('Remove from central columns'), 'centralColumns_delete.png',
- 'remove_from_central_columns'
- );
- }
- }
- return $html_output;
-}
-
-/**
- * Get HTML for move columns dialog
- *
- * @return string $html_output
- */
-function PMA_getHtmlDivForMoveColumnsDialog()
-{
- $html_output = '<div id="move_columns_dialog" '
- . 'title="' . __('Move columns') . '" style="display: none">';
-
- $html_output .= '<p>'
- . __('Move the columns by dragging them up and down.') . '</p>';
-
- $html_output .= '<form action="tbl_structure.php">'
- . '<div>'
- . PMA_URL_getHiddenInputs($GLOBALS['db'], $GLOBALS['table'])
- . '<ul></ul>'
- . '</div>'
- . '</form>'
- . '</div>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for edit views'
- *
- * @param string $url_params URL parameters
- *
- * @return string $html_output
- */
-function PMA_getHtmlForEditView($url_params)
-{
- $query = "SELECT `VIEW_DEFINITION`, `CHECK_OPTION`, `DEFINER`, `SECURITY_TYPE`"
- . " FROM `INFORMATION_SCHEMA`.`VIEWS`"
- . " WHERE TABLE_SCHEMA='" . PMA_Util::sqlAddSlashes($GLOBALS['db']) . "'"
- . " AND TABLE_NAME='" . PMA_Util::sqlAddSlashes($GLOBALS['table']) . "';";
- $item = $GLOBALS['dbi']->fetchSingleRow($query);
-
- $query = "SHOW CREATE TABLE " . PMA_Util::backquote($GLOBALS['db'])
- . "." . PMA_Util::backquote($GLOBALS['table']);
- $createView = $GLOBALS['dbi']->fetchValue($query, 0, 'Create View');
- // get algorithm from $createView of the form CREATE ALGORITHM=<ALGORITHM> DE...
- $parts = explode(" ", substr($createView, 17));
- $item['ALGORITHM'] = $parts[0];
-
- $view = array(
- 'operation' => 'alter',
- 'definer' => $item['DEFINER'],
- 'sql_security' => $item['SECURITY_TYPE'],
- 'name' => $GLOBALS['table'],
- 'as' => $item['VIEW_DEFINITION'],
- 'with' => $item['CHECK_OPTION'],
- 'algorithm' => $item['ALGORITHM'],
- );
- $url = 'view_create.php' . PMA_URL_getCommon($url_params) . '&amp;';
- $url .= implode(
- '&amp;',
- array_map(
- function ($key, $val) {
- return 'view[' . urlencode($key) . ']=' . urlencode($val);
- },
- array_keys($view),
- $view
- )
- );
- $html_output = PMA_Util::linkOrButton(
- $url,
- PMA_Util::getIcon('b_edit.png', __('Edit view'), true)
- );
- return $html_output;
-}
-
-/**
- * Get HTML links for 'Print view', 'Relation view', 'Propose table structure',
- * 'Track table' and 'Move columns'
- *
- * @param string $url_query url query
- * @param boolean $tbl_is_view whether table is view or not
- * @param boolean $db_is_system_schema whether db is information schema or not
- *
- * @return string $html_output
- */
-function PMA_getHtmlForOptionalActionLinks($url_query, $tbl_is_view,
- $db_is_system_schema
-) {
- $html_output = '<a href="tbl_printview.php' . $url_query
- . '" target="print_view">'
- . PMA_Util::getIcon('b_print.png', __('Print view'), true)
- . '</a>';
-
- if (! $tbl_is_view && ! $db_is_system_schema) {
- if (!PMA_DRIZZLE) {
- $html_output .= '<a href="sql.php' . $url_query
- . '&amp;session_max_rows=all&amp;sql_query=' . urlencode(
- 'SELECT * FROM ' . PMA_Util::backquote($GLOBALS['table'])
- . ' PROCEDURE ANALYSE()'
- ) . '">'
- . PMA_Util::getIcon(
- 'b_tblanalyse.png',
- __('Propose table structure'),
- true
- )
- . '</a>';
- $html_output .= PMA_Util::showMySQLDocu('procedure_analyse') . "\n";
- }
- if (PMA_Tracker::isActive()) {
- $html_output .= '<a href="tbl_tracking.php' . $url_query . '">'
- . PMA_Util::getIcon('eye.png', __('Track table'), true)
- . '</a>';
- }
- $html_output .= '<a href="#" id="move_columns_anchor">'
- . PMA_Util::getIcon('b_move.png', __('Move columns'), true)
- . '</a>';
- $html_output .= '<a href="normalization.php' . $url_query . '">'
- . PMA_Util::getIcon('normalize.png', __('Improve table structure'), true)
- . '</a>';
- }
-
- if ($tbl_is_view && ! $db_is_system_schema) {
- if (PMA_Tracker::isActive()) {
- $html_output .= '<a href="tbl_tracking.php' . $url_query . '">'
- . PMA_Util::getIcon('eye.png', __('Track view'), true)
- . '</a>';
- }
- }
-
- return $html_output;
-}
-
-/**
- * Get HTML snippet for "Add column" feature in structure table
- *
- * @param array $columns_list column list array
- *
- * @return string $html_output
- */
-function PMA_getHtmlForAddColumn($columns_list)
-{
- $html_output = '<form method="post" action="tbl_addfield.php" '
- . 'id="addColumns" name="addColumns" '
- . 'onsubmit="return checkFormElementInRange('
- . 'this, \'num_fields\', \'' . str_replace(
- '\'',
- '\\\'',
- __('You have to add at least one column.')
- ) . '\', 1)'
- . '">';
-
- $html_output .= PMA_URL_getHiddenInputs(
- $GLOBALS['db'],
- $GLOBALS['table']
- );
- if (PMA_Util::showIcons('ActionLinksMode')) {
- $html_output .=PMA_Util::getImage(
- 'b_insrow.png',
- __('Add column')
- );
- $html_output .= '&nbsp;';
- }
- $num_fields = '<input type="number" name="num_fields" '
- . 'value="1" onfocus="this.select()" '
- . 'min="1" required />';
- $html_output .= sprintf(__('Add %s column(s)'), $num_fields);
-
- // I tried displaying the drop-down inside the label but with Firefox
- // the drop-down was blinking
- $column_selector = '<select name="after_field" '
- . 'onchange="checkFirst()">';
-
- $column_selector .= '<option '
- . 'value="first" data-pos = "first">'
- . __('at beginning of table')
- . '</option>';
- $cols_count = count($columns_list);
- foreach ($columns_list as $one_column_name) {
- //by default select the last column (add column at the end of the table)
- if (--$cols_count == 0) {
- $column_selector .= '<option '
- . 'value="' . htmlspecialchars($one_column_name)
- . '" selected="selected">';
- } else {
- $column_selector .= '<option '
- . 'value="' . htmlspecialchars($one_column_name) . '">';
- }
- $column_selector .= sprintf(
- __('after %s'),
- htmlspecialchars($one_column_name)
- )
- . '</option>';
- }
- $column_selector .= '</select>';
- $html_output .= '<input type="hidden" name="field_where" value="after"/>';
- $html_output .= '&nbsp;';
- $html_output .= $column_selector;
- $html_output .= '<input type="submit" value="' . __('Go') . '" />'
- . '</form>';
-
- return $html_output;
-}
-
-/**
- * Get HTML snippet for table rows in the Information ->Space usage table
- *
- * @param boolean $odd_row whether current row is odd or even
- * @param string $name type of usage
- * @param string $value value of usage
- * @param string $unit unit
- *
- * @return string $html_output
- */
-function PMA_getHtmlForSpaceUsageTableRow($odd_row, $name, $value, $unit)
-{
- $html_output = '<tr class="' . (($odd_row = !$odd_row) ? 'odd' : 'even') . '">';
- $html_output .= '<th class="name">' . $name . '</th>';
- $html_output .= '<td class="value">' . $value . '</td>';
- $html_output .= '<td class="unit">' . $unit . '</td>';
- $html_output .= '</tr>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for Optimize link if overhead in Information fieldset
- *
- * @param string $url_query URL query
- *
- * @return string $html_output
- */
-function PMA_getHtmlForOptimizeLink($url_query)
-{
- $html_output = '<tr class="tblFooters">';
- $html_output .= '<td colspan="3" class="center">';
- $html_output .= '<a href="sql.php' . $url_query
- . '&pos=0&amp;sql_query=' . urlencode(
- 'OPTIMIZE TABLE ' . PMA_Util::backquote($GLOBALS['table'])
- )
- . '">'
- . PMA_Util::getIcon('b_tbloptimize.png', __('Optimize table'))
- . '</a>';
- $html_output .= '</td>';
- $html_output .= '</tr>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for 'Row statistics' table row
- *
- * @param boolean $odd_row whether current row is odd or even
- * @param string $name statement name
- * @param mixed $value value
- *
- * @return string $html_output
- */
-function PMA_getHtmlForRowStatsTableRow($odd_row, $name, $value)
-{
- $html_output = '<tr class="' . (($odd_row = !$odd_row) ? 'odd' : 'even') . '">';
- $html_output .= '<th class="name">' . $name . '</th>';
- $html_output .= '<td class="value">' . $value . '</td>';
- $html_output .= '</tr>';
-
- return $html_output;
-}
-
-/**
- * Get HTML snippet for display Row statistics table
- *
- * @param array $showtable show table array
- * @param string $tbl_collation table collation
- * @param boolean $is_innodb whether table is innob or not
- * @param boolean $mergetable Checks if current table is a merge table
- * @param integer $avg_size average size
- * @param string $avg_unit average unit
- *
- * @return string $html_output
- */
-function getHtmlForRowStatsTable($showtable, $tbl_collation,
- $is_innodb, $mergetable, $avg_size, $avg_unit
-) {
- $odd_row = false;
- $html_output = '<table id="tablerowstats" class="data">';
- $html_output .= '<caption class="tblHeaders">'
- . __('Row statistics') . '</caption>';
- $html_output .= '<tbody>';
-
- if (isset($showtable['Row_format'])) {
- if ($showtable['Row_format'] == 'Fixed') {
- $value = __('static');
- } elseif ($showtable['Row_format'] == 'Dynamic') {
- $value = __('dynamic');
- } else {
- $value = $showtable['Row_format'];
- }
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row, __('Format'), $value
- );
- $odd_row = !$odd_row;
- }
- if (! empty($showtable['Create_options'])) {
- if ($showtable['Create_options'] == 'partitioned') {
- $value = __('partitioned');
- } else {
- $value = $showtable['Create_options'];
- }
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row, __('Options'), $value
- );
- $odd_row = !$odd_row;
- }
- if (!empty($tbl_collation)) {
- $value = '<dfn title="' . PMA_getCollationDescr($tbl_collation) . '">'
- . $tbl_collation . '</dfn>';
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row, __('Collation'), $value
- );
- $odd_row = !$odd_row;
- }
- if (!$is_innodb && isset($showtable['Rows'])) {
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Rows'),
- PMA_Util::formatNumber($showtable['Rows'], 0)
- );
- $odd_row = !$odd_row;
- }
- if (!$is_innodb
- && isset($showtable['Avg_row_length'])
- && $showtable['Avg_row_length'] > 0
- ) {
- list($avg_row_length_value, $avg_row_length_unit)
- = PMA_Util::formatByteDown(
- $showtable['Avg_row_length'],
- 6,
- 1
- );
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Row length'),
- ($avg_row_length_value . ' ' . $avg_row_length_unit)
- );
- unset($avg_row_length_value, $avg_row_length_unit);
- $odd_row = !$odd_row;
- }
- if (!$is_innodb
- && isset($showtable['Data_length'])
- && isset($showtable['Rows'])
- && $showtable['Rows'] > 0
- && $mergetable == false
- ) {
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Row size'),
- ($avg_size . ' ' . $avg_unit)
- );
- $odd_row = !$odd_row;
- }
- if (isset($showtable['Auto_increment'])) {
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Next autoindex'),
- PMA_Util::formatNumber($showtable['Auto_increment'], 0)
- );
- $odd_row = !$odd_row;
- }
- if (isset($showtable['Create_time'])) {
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Creation'),
- PMA_Util::localisedDate(strtotime($showtable['Create_time']))
- );
- $odd_row = !$odd_row;
- }
- if (isset($showtable['Update_time'])) {
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Last update'),
- PMA_Util::localisedDate(strtotime($showtable['Update_time']))
- );
- $odd_row = !$odd_row;
- }
- if (isset($showtable['Check_time'])) {
- $html_output .= PMA_getHtmlForRowStatsTableRow(
- $odd_row,
- __('Last check'),
- PMA_Util::localisedDate(strtotime($showtable['Check_time']))
- );
- }
- $html_output .= '</tbody>'
- . '</table>';
-
- return $html_output;
-}
-
-/**
- * Get HTML snippet for action row in structure table,
- * This function returns common HTML <td> for Primary, Unique, Index,
- * Spatial actions
- *
- * @param string $type column type
- * @param string $tbl_storage_engine table storage engine
- * @param string $class class attribute for <td>
- * @param boolean $hasField has field
- * @param boolean $hasLinkClass has <a> the class attribute
- * @param string $url_query url query
- * @param object|boolean $primary primary if set, false otherwise
- * @param string $syntax Sql syntax
- * @param string $message message to show
- * @param string $action action
- * @param array $titles titles array
- * @param array $row current row
- * @param boolean $isPrimary is primary action
- *
- * @return string $html_output
- */
-function PMA_getHtmlForActionRowInStructureTable($type, $tbl_storage_engine,
- $class, $hasField, $hasLinkClass, $url_query, $primary, $syntax,
- $message, $action, $titles, $row, $isPrimary
-) {
- $html_output = '<li class="' . $class . '">';
-
- if ($type == 'text'
- || $type == 'blob'
- || 'ARCHIVE' == $tbl_storage_engine
- || $hasField
- ) {
- $html_output .= $titles['No' . $action];
- } else {
- $html_output .= '<a rel="samepage" class="ajax add_key';
- if ($hasLinkClass) {
- $html_output .= ' add_primary_key_anchor"';
- } else if ($action=='Index') {
- $html_output .= ' add_index_anchor"';
- } else if ($action=='Unique') {
- $html_output .= ' add_unique_anchor"';
- } else if ($action=='Spatial') {
- $html_output .= ' add_spatial_anchor"';
- } else {
- $html_output .= '"';
- }
- $html_output .= ' href="tbl_structure.php' . $url_query
- . '&amp;add_key=1&amp;sql_query='
- . urlencode(
- 'ALTER TABLE ' . PMA_Util::backquote($GLOBALS['table'])
- . ($isPrimary ? ($primary ? ' DROP PRIMARY KEY,' : '') : '')
- . ' ' . $syntax . '('
- . PMA_Util::backquote($row['Field']) . ');'
- )
- . '&amp;message_to_show=' . urlencode(
- sprintf(
- $message,
- htmlspecialchars($row['Field'])
- )
- ) . '" >'
- . $titles[$action] . '</a>';
- }
- $html_output .= '</li>';
-
- return $html_output;
-}
-
-/**
- * Get HTML for fulltext action
- *
- * @param string $tbl_storage_engine table storage engine
- * @param string $type column type
- * @param string $url_query url query
- * @param array $row current row
- * @param array $titles titles array
- *
- * @return string $html_output
- */
-function PMA_getHtmlForFullTextAction($tbl_storage_engine, $type, $url_query,
- $row, $titles
-) {
- $html_output = '<li class="fulltext nowrap">';
- if (! empty($tbl_storage_engine)
- && ($tbl_storage_engine == 'MYISAM'
- || $tbl_storage_engine == 'ARIA'
- || $tbl_storage_engine == 'MARIA'
- || ($tbl_storage_engine == 'INNODB' && PMA_MYSQL_INT_VERSION >= 50604))
- && (/*overload*/mb_strpos($type, 'text') !== false
- || /*overload*/mb_strpos($type, 'char') !== false)
- ) {
- $html_output .= '<a rel="samepage" class="ajax add_key add_fulltext_anchor" '
- . 'href="tbl_structure.php' . $url_query
- . '&amp;add_key=1&amp;sql_query='
- . urlencode(
- 'ALTER TABLE ' . PMA_Util::backquote($GLOBALS['table'])
- . ' ADD FULLTEXT(' . PMA_Util::backquote($row['Field'])
- . ');'
- )
- . '&amp;message_to_show='
- . urlencode(
- sprintf(
- __('An index has been added on %s.'),
- htmlspecialchars($row['Field'])
- )
- )
- . '">';
- $html_output .= $titles['IdxFulltext'] . '</a>';
- } else {
- $html_output .= $titles['NoIdxFulltext'];
- }
- $html_output .= '</li>';
- return $html_output;
-}
-
-/**
- * Get HTML snippet for "Distinc Value" action
- *
- * @param string $url_query url query
- * @param array $row current row
- * @param array $titles titles array
- *
- * @return string $html_output
- */
-function PMA_getHtmlForDistinctValueAction($url_query, $row, $titles)
-{
- $html_output = '<li class="browse nowrap">';
- $html_output .= '<a href="sql.php' . $url_query . '&amp;sql_query='
- . urlencode(
- 'SELECT COUNT(*) AS ' . PMA_Util::backquote(__('Rows'))
- . ', ' . PMA_Util::backquote($row['Field'])
- . ' FROM ' . PMA_Util::backquote($GLOBALS['table'])
- . ' GROUP BY ' . PMA_Util::backquote($row['Field'])
- . ' ORDER BY ' . PMA_Util::backquote($row['Field'])
- )
- . '&amp;is_browse_distinct=1">'
- . $titles['DistinctValues']
- . '</a>';
- $html_output .= '</li>';
-
- return $html_output;
-}
-
-/**
- * Get HTML snippet for Actions in table structure
- *
- * @param string $type column type
- * @param string $tbl_storage_engine table storage engine
- * @param object|boolean $primary primary if set,
- * false otherwise
- * @param string $field_name column name
- * @param string $url_query url query
- * @param array $titles titles array
- * @param array $row current row
- * @param string $rownum row number
- * @param array $columns_with_unique_index columns with unique index
- * @param boolean $isInCentralColumns set if column in central
- * columns list
- *
- * @return string $html_output;
- */
-function PMA_getHtmlForActionsInTableStructure($type, $tbl_storage_engine,
- $primary, $field_name, $url_query, $titles, $row, $rownum,
- $columns_with_unique_index, $isInCentralColumns
-) {
- $html_output = '<td><ul class="table-structure-actions resizable-menu">';
- $html_output .= PMA_getHtmlForActionRowInStructureTable(
- $type, $tbl_storage_engine,
- 'primary nowrap',
- ($primary && $primary->hasColumn($field_name)),
- true, $url_query, $primary,
- 'ADD PRIMARY KEY',
- __('A primary key has been added on %s.'),
- 'Primary', $titles, $row, true
- );
- $html_output .= PMA_getHtmlForActionRowInStructureTable(
- $type, $tbl_storage_engine,
- 'add_unique unique nowrap',
- isset($columns_with_unique_index[$field_name]),
- false, $url_query, $primary, 'ADD UNIQUE',
- __('An index has been added on %s.'),
- 'Unique', $titles, $row, false
- );
- $html_output .= PMA_getHtmlForActionRowInStructureTable(
- $type, $tbl_storage_engine,
- 'add_index nowrap', false, false, $url_query,
- $primary, 'ADD INDEX', __('An index has been added on %s.'),
- 'Index', $titles, $row, false
- );
- if (!PMA_DRIZZLE) {
- $spatial_types = array(
- 'geometry', 'point', 'linestring', 'polygon', 'multipoint',
- 'multilinestring', 'multipolygon', 'geomtrycollection'
- );
- $html_output .= PMA_getHtmlForActionRowInStructureTable(
- $type, $tbl_storage_engine,
- 'spatial nowrap',
- ! (in_array($type, $spatial_types)
- && ('MYISAM' == $tbl_storage_engine
- || PMA_MYSQL_INT_VERSION >= 50705)
- ),
- false, $url_query, $primary, 'ADD SPATIAL',
- __('An index has been added on %s.'), 'Spatial',
- $titles, $row, false
- );
-
- // FULLTEXT is possible on TEXT, CHAR and VARCHAR
- $html_output .= PMA_getHtmlForFullTextAction(
- $tbl_storage_engine, $type, $url_query, $row, $titles
- );
- }
- $html_output .= PMA_getHtmlForDistinctValueAction($url_query, $row, $titles);
- if (isset($GLOBALS['cfgRelation']['central_columnswork'])
- && $GLOBALS['cfgRelation']['central_columnswork']
- ) {
- $html_output .= '<li class="browse nowrap">';
- if ($isInCentralColumns) {
- $html_output .=
- '<a href="#" onclick=$("input:checkbox").prop("checked",false);'
- . '$("#checkbox_row_' . $rownum . '").prop("checked",true);'
- . '$("button[value=remove_from_central_columns]").click();>'
- . PMA_Util::getIcon(
- 'centralColumns_delete.png',
- __('Remove from central columns')
- )
- . '</a>';
- } else {
- $html_output .=
- '<a href="#" onclick=$("input:checkbox").prop("checked",false);'
- . '$("#checkbox_row_' . $rownum . '").prop("checked",true);'
- . '$("button[value=add_to_central_columns]").click();>'
- . PMA_Util::getIcon(
- 'centralColumns_add.png',
- __('Add to central columns')
- )
- . '</a>';
- }
- $html_output .= '</li>';
- }
- $html_output .= '</ul></td>';
- return $html_output;
-}
-
-/**
- * Get hidden action titles (image and string)
- *
- * @return array $hidden_titles
- */
-function PMA_getHiddenTitlesArray()
-{
- $hidden_titles = array();
- $hidden_titles['DistinctValues'] = PMA_Util::getIcon(
- 'b_browse.png', __('Distinct values'), true
- );
- $hidden_titles['Primary'] = PMA_Util::getIcon(
- 'b_primary.png', __('Add primary key'), true
- );
- $hidden_titles['NoPrimary'] = PMA_Util::getIcon(
- 'bd_primary.png', __('Add primary key'), true
- );
- $hidden_titles['Index'] = PMA_Util::getIcon(
- 'b_index.png', __('Add index'), true
- );
- $hidden_titles['NoIndex'] = PMA_Util::getIcon(
- 'bd_index.png', __('Add index'), true
- );
- $hidden_titles['Unique'] = PMA_Util::getIcon(
- 'b_unique.png', __('Add unique index'), true
- );
- $hidden_titles['NoUnique'] = PMA_Util::getIcon(
- 'bd_unique.png', __('Add unique index'), true
- );
- $hidden_titles['Spatial'] = PMA_Util::getIcon(
- 'b_spatial.png', __('Add SPATIAL index'), true
- );
- $hidden_titles['NoSpatial'] = PMA_Util::getIcon(
- 'bd_spatial.png', __('Add SPATIAL index'), true
- );
- $hidden_titles['IdxFulltext'] = PMA_Util::getIcon(
- 'b_ftext.png', __('Add FULLTEXT index'), true
- );
- $hidden_titles['NoIdxFulltext'] = PMA_Util::getIcon(
- 'bd_ftext.png', __('Add FULLTEXT index'), true
- );
-
- return $hidden_titles;
-}
-
-/**
- * Get action titles (image or string array
- *
- * @return array $titles
- */
-function PMA_getActionTitlesArray()
-{
- $titles = array();
- $titles['Change']
- = PMA_Util::getIcon('b_edit.png', __('Change'));
- $titles['Drop']
- = PMA_Util::getIcon('b_drop.png', __('Drop'));
- $titles['NoDrop']
- = PMA_Util::getIcon('b_drop.png', __('Drop'));
- $titles['Primary']
- = PMA_Util::getIcon('b_primary.png', __('Primary'));
- $titles['Index']
- = PMA_Util::getIcon('b_index.png', __('Index'));
- $titles['Unique']
- = PMA_Util::getIcon('b_unique.png', __('Unique'));
- $titles['Spatial']
- = PMA_Util::getIcon('b_spatial.png', __('Spatial'));
- $titles['IdxFulltext']
- = PMA_Util::getIcon('b_ftext.png', __('Fulltext'));
- $titles['NoPrimary']
- = PMA_Util::getIcon('bd_primary.png', __('Primary'));
- $titles['NoIndex']
- = PMA_Util::getIcon('bd_index.png', __('Index'));
- $titles['NoUnique']
- = PMA_Util::getIcon('bd_unique.png', __('Unique'));
- $titles['NoSpatial']
- = PMA_Util::getIcon('bd_spatial.png', __('Spatial'));
- $titles['NoIdxFulltext']
- = PMA_Util::getIcon('bd_ftext.png', __('Fulltext'));
- $titles['DistinctValues']
- = PMA_Util::getIcon('b_browse.png', __('Distinct values'));
-
- return $titles;
-}
-
-/**
- * Get HTML snippet for display table statistics
- *
- * @param array $showtable full table status info
- * @param integer $table_info_num_rows table info number of rows
- * @param boolean $tbl_is_view whether table is view or not
- * @param boolean $db_is_system_schema whether db is information schema or not
- * @param string $tbl_storage_engine table storage engine
- * @param string $url_query url query
- * @param string $tbl_collation table collation
- *
- * @return string $html_output
- */
-function PMA_getHtmlForDisplayTableStats($showtable, $table_info_num_rows,
- $tbl_is_view, $db_is_system_schema, $tbl_storage_engine, $url_query,
- $tbl_collation
-) {
- $html_output = '<div id="tablestatistics">';
- if (empty($showtable)) {
- $showtable = PMA_Table::sGetStatusInfo(
- $GLOBALS['db'], $GLOBALS['table'], null, true
- );
- }
-
- if (empty($showtable['Data_length'])) {
- $showtable['Data_length'] = 0;
- }
- if (empty($showtable['Index_length'])) {
- $showtable['Index_length'] = 0;
- }
-
- $is_innodb = (isset($showtable['Type']) && $showtable['Type'] == 'InnoDB');
-
- // Gets some sizes
-
- $mergetable = PMA_Table::isMerge($GLOBALS['db'], $GLOBALS['table']);
-
- // this is to display for example 261.2 MiB instead of 268k KiB
- $max_digits = 3;
- $decimals = 1;
- list($data_size, $data_unit) = PMA_Util::formatByteDown(
- $showtable['Data_length'], $max_digits, $decimals
- );
- if ($mergetable == false) {
- list($index_size, $index_unit) = PMA_Util::formatByteDown(
- $showtable['Index_length'], $max_digits, $decimals
- );
- }
- // InnoDB returns a huge value in Data_free, do not use it
- if (! $is_innodb
- && isset($showtable['Data_free'])
- && $showtable['Data_free'] > 0
- ) {
- list($free_size, $free_unit) = PMA_Util::formatByteDown(
- $showtable['Data_free'], $max_digits, $decimals
- );
- list($effect_size, $effect_unit) = PMA_Util::formatByteDown(
- $showtable['Data_length'] + $showtable['Index_length']
- - $showtable['Data_free'],
- $max_digits, $decimals
- );
- } else {
- list($effect_size, $effect_unit) = PMA_Util::formatByteDown(
- $showtable['Data_length'] + $showtable['Index_length'],
- $max_digits, $decimals
- );
- }
- list($tot_size, $tot_unit) = PMA_Util::formatByteDown(
- $showtable['Data_length'] + $showtable['Index_length'],
- $max_digits, $decimals
- );
- if ($table_info_num_rows > 0) {
- list($avg_size, $avg_unit) = PMA_Util::formatByteDown(
- ($showtable['Data_length'] + $showtable['Index_length'])
- / $showtable['Rows'],
- 6, 1
- );
- }
-
- // Displays them
- $odd_row = false;
-
- $html_output .= '<fieldset>'
- . '<legend>' . __('Information') . '</legend>'
- . '<a id="showusage"></a>';
-
- if (! $tbl_is_view && ! $db_is_system_schema) {
- $html_output .= '<table id="tablespaceusage" class="data">'
- . '<caption class="tblHeaders">' . __('Space usage') . '</caption>'
- . '<tbody>';
-
- $html_output .= PMA_getHtmlForSpaceUsageTableRow(
- $odd_row, __('Data'), $data_size, $data_unit
- );
- $odd_row = !$odd_row;
-
- if (isset($index_size)) {
- $html_output .= PMA_getHtmlForSpaceUsageTableRow(
- $odd_row, __('Index'), $index_size, $index_unit
- );
- $odd_row = !$odd_row;
- }
-
- if (isset($free_size)) {
- $html_output .= PMA_getHtmlForSpaceUsageTableRow(
- $odd_row, __('Overhead'), $free_size, $free_unit
- );
- $html_output .= PMA_getHtmlForSpaceUsageTableRow(
- $odd_row, __('Effective'), $effect_size, $effect_unit
- );
- $odd_row = !$odd_row;
- }
- if (isset($tot_size) && $mergetable == false) {
- $html_output .= PMA_getHtmlForSpaceUsageTableRow(
- $odd_row, __('Total'), $tot_size, $tot_unit
- );
- }
- // Optimize link if overhead
- if (isset($free_size) && !PMA_DRIZZLE
- && ($tbl_storage_engine == 'MYISAM'
- || $tbl_storage_engine == 'ARIA'
- || $tbl_storage_engine == 'MARIA'
- || $tbl_storage_engine == 'BDB')
- ) {
- $html_output .= PMA_getHtmlForOptimizeLink($url_query);
- }
- $html_output .= '</tbody>'
- . '</table>';
- }
-
- $html_output .= getHtmlForRowStatsTable(
- $showtable, $tbl_collation,
- $is_innodb, $mergetable,
- (isset ($avg_size) ? $avg_size : ''),
- (isset ($avg_unit) ? $avg_unit : '')
- );
-
- $html_output .= '</fieldset>'
- . '</div>';
-
- return $html_output;
-}
-
-/**
- * Displays HTML for changing one or more columns
- *
- * @param string $db database name
- * @param string $table table name
- * @param array $selected the selected columns
- * @param string $action target script to call
- *
- * @return boolean $regenerate true if error occurred
- *
- */
-function PMA_displayHtmlForColumnChange($db, $table, $selected, $action)
-{
- // $selected comes from mult_submits.inc.php
- if (empty($selected)) {
- $selected[] = $_REQUEST['field'];
- $selected_cnt = 1;
- } else { // from a multiple submit
- $selected_cnt = count($selected);
- }
-
- /**
- * @todo optimize in case of multiple fields to modify
- */
- $fields_meta = array();
- for ($i = 0; $i < $selected_cnt; $i++) {
- $fields_meta[] = $GLOBALS['dbi']->getColumns(
- $db, $table, $selected[$i], true
- );
- }
- $num_fields = count($fields_meta);
- // set these globals because tbl_columns_definition_form.inc.php
- // verifies them
- // @todo: refactor tbl_columns_definition_form.inc.php so that it uses
- // function params
- $GLOBALS['action'] = 'tbl_structure.php';
- $GLOBALS['num_fields'] = $num_fields;
-
- // Get more complete field information.
- // For now, this is done to obtain MySQL 4.1.2+ new TIMESTAMP options
- // and to know when there is an empty DEFAULT value.
- // Later, if the analyser returns more information, it
- // could be executed to replace the info given by SHOW FULL COLUMNS FROM.
- /**
- * @todo put this code into a require()
- * or maybe make it part of $GLOBALS['dbi']->getColumns();
- */
-
- // We also need this to correctly learn if a TIMESTAMP is NOT NULL, since
- // SHOW FULL COLUMNS says NULL and SHOW CREATE TABLE says NOT NULL (tested
- // in MySQL 4.0.25).
-
- $show_create_table = $GLOBALS['dbi']->fetchValue(
- 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($table),
- 0, 1
- );
- $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table));
- unset($show_create_table);
- /**
- * Form for changing properties.
- */
- include 'libraries/tbl_columns_definition_form.inc.php';
-}
-
-/**
- * Verifies if some elements of a column have changed
- *
- * @param integer $i column index in the request
- *
- * @return boolean $alterTableNeeded true if we need to generate ALTER TABLE
- *
- */
-function PMA_columnNeedsAlterTable($i)
-{
- // these two fields are checkboxes so might not be part of the
- // request; therefore we define them to avoid notices below
- if (! isset($_REQUEST['field_null'][$i])) {
- $_REQUEST['field_null'][$i] = 'NO';
- }
- if (! isset($_REQUEST['field_extra'][$i])) {
- $_REQUEST['field_extra'][$i] = '';
- }
-
- // field_name does not follow the convention (corresponds to field_orig)
- if ($_REQUEST['field_attribute'][$i] != $_REQUEST['field_attribute_orig'][$i]
- || $_REQUEST['field_collation'][$i] != $_REQUEST['field_collation_orig'][$i]
- || $_REQUEST['field_comments'][$i] != $_REQUEST['field_comments_orig'][$i]
- || $_REQUEST['field_default_value'][$i] != $_REQUEST['field_default_value_orig'][$i]
- || $_REQUEST['field_default_type'][$i] != $_REQUEST['field_default_type_orig'][$i]
- || $_REQUEST['field_extra'][$i] != $_REQUEST['field_extra_orig'][$i]
- || $_REQUEST['field_length'][$i] != $_REQUEST['field_length_orig'][$i]
- || $_REQUEST['field_name'][$i] != $_REQUEST['field_orig'][$i]
- || $_REQUEST['field_null'][$i] != $_REQUEST['field_null_orig'][$i]
- || $_REQUEST['field_type'][$i] != $_REQUEST['field_type_orig'][$i]
- || ! empty($_REQUEST['field_move_to'][$i])
- ) {
- return true;
- } else {
- return false;
- }
-}
-
-/**
- * Update the table's structure based on $_REQUEST
- *
- * @param string $db database name
- * @param string $table table name
- *
- * @return boolean $regenerate true if error occurred
- *
- */
-function PMA_updateColumns($db, $table)
-{
- $err_url = 'tbl_structure.php' . PMA_URL_getCommon(
- array(
- 'db' => $db, 'table' => $table
- )
- );
- $regenerate = false;
- $field_cnt = count($_REQUEST['field_name']);
- $changes = array();
- $pmatable = new PMA_Table($table, $db);
-
- for ($i = 0; $i < $field_cnt; $i++) {
- if (PMA_columnNeedsAlterTable($i)) {
- $changes[] = 'CHANGE ' . PMA_Table::generateAlter(
- isset($_REQUEST['field_orig'][$i])
- ? $_REQUEST['field_orig'][$i]
- : '',
- $_REQUEST['field_name'][$i],
- $_REQUEST['field_type'][$i],
- $_REQUEST['field_length'][$i],
- $_REQUEST['field_attribute'][$i],
- isset($_REQUEST['field_collation'][$i])
- ? $_REQUEST['field_collation'][$i]
- : '',
- isset($_REQUEST['field_null'][$i])
- ? $_REQUEST['field_null'][$i]
- : 'NOT NULL',
- $_REQUEST['field_default_type'][$i],
- $_REQUEST['field_default_value'][$i],
- isset($_REQUEST['field_extra'][$i])
- ? $_REQUEST['field_extra'][$i]
- : false,
- isset($_REQUEST['field_comments'][$i])
- ? $_REQUEST['field_comments'][$i]
- : '',
- isset($_REQUEST['field_move_to'][$i])
- ? $_REQUEST['field_move_to'][$i]
- : ''
- );
-
- // find the remembered sort expression
- $sorted_col = $pmatable->getUiProp(PMA_Table::PROP_SORTED_COLUMN);
- // if the old column name is part of the remembered sort expression
- if (/*overload*/mb_strpos(
- $sorted_col,
- PMA_Util::backquote($_REQUEST['field_orig'][$i])
- ) !== false) {
- // delete the whole remembered sort expression
- $pmatable->removeUiProp(PMA_Table::PROP_SORTED_COLUMN);
- }
-
- }
- } // end for
-
- $response = PMA_Response::getInstance();
-
- if (count($changes) > 0 || isset($_REQUEST['preview_sql'])) {
- // Builds the primary keys statements and updates the table
- $key_query = '';
- /**
- * this is a little bit more complex
- *
- * @todo if someone selects A_I when altering a column we need to check:
- * - no other column with A_I
- * - the column has an index, if not create one
- *
- */
-
- // To allow replication, we first select the db to use
- // and then run queries on this db.
- if (! $GLOBALS['dbi']->selectDb($db)) {
- PMA_Util::mysqlDie(
- $GLOBALS['dbi']->getError(),
- 'USE ' . PMA_Util::backquote($db) . ';',
- false,
- $err_url
- );
- }
- $sql_query = 'ALTER TABLE ' . PMA_Util::backquote($table) . ' ';
- $sql_query .= implode(', ', $changes) . $key_query;
- $sql_query .= ';';
-
- // If there is a request for SQL previewing.
- if (isset($_REQUEST['preview_sql'])) {
- PMA_previewSQL(count($changes) > 0 ? $sql_query : '');
- }
-
- $result = $GLOBALS['dbi']->tryQuery($sql_query);
-
- if ($result !== false) {
- $message = PMA_Message::success(
- __('Table %1$s has been altered successfully.')
- );
- $message->addParam($table);
-
- $response->addHTML(
- PMA_Util::getMessage($message, $sql_query, 'success')
- );
- } else {
- // An error happened while inserting/updating a table definition
- $response->isSuccess(false);
- $response->addJSON(
- 'message',
- PMA_Message::rawError(
- __('Query error') . ':<br />' . $GLOBALS['dbi']->getError()
- )
- );
- $regenerate = true;
- }
- }
-
- include_once 'libraries/transformations.lib.php';
-
- // update field names in relation
- if (isset($_REQUEST['field_orig']) && is_array($_REQUEST['field_orig'])) {
- foreach ($_REQUEST['field_orig'] as $fieldindex => $fieldcontent) {
- if ($_REQUEST['field_name'][$fieldindex] != $fieldcontent) {
- PMA_REL_renameField(
- $db, $table, $fieldcontent,
- $_REQUEST['field_name'][$fieldindex]
- );
- }
- }
- }
-
- // update mime types
- if (isset($_REQUEST['field_mimetype'])
- && is_array($_REQUEST['field_mimetype'])
- && $GLOBALS['cfg']['BrowseMIME']
- ) {
- foreach ($_REQUEST['field_mimetype'] as $fieldindex => $mimetype) {
- if (isset($_REQUEST['field_name'][$fieldindex])
- && /*overload*/mb_strlen(
- $_REQUEST['field_name'][$fieldindex]
- )
- ) {
- PMA_setMIME(
- $db, $table, $_REQUEST['field_name'][$fieldindex],
- $mimetype,
- $_REQUEST['field_transformation'][$fieldindex],
- $_REQUEST['field_transformation_options'][$fieldindex],
- $_REQUEST['field_input_transformation'][$fieldindex],
- $_REQUEST['field_input_transformation_options'][$fieldindex]
- );
- }
- }
- }
- return $regenerate;
-}
-
-/**
- * Moves columns in the table's structure based on $_REQUEST
- *
- * @param string $db database name
- * @param string $table table name
- *
- * @return void
- */
-function PMA_moveColumns($db, $table)
-{
- $GLOBALS['dbi']->selectDb($db);
-
- /*
- * load the definitions for all columns
- */
- $columns = $GLOBALS['dbi']->getColumnsFull($db, $table);
- $column_names = array_keys($columns);
- $changes = array();
-
- // move columns from first to last
- for ($i = 0, $l = count($_REQUEST['move_columns']); $i < $l; $i++) {
- $column = $_REQUEST['move_columns'][$i];
- // is this column already correctly placed?
- if ($column_names[$i] == $column) {
- continue;
- }
-
- // it is not, let's move it to index $i
- $data = $columns[$column];
- $extracted_columnspec = PMA_Util::extractColumnSpec($data['Type']);
- if (isset($data['Extra'])
- && $data['Extra'] == 'on update CURRENT_TIMESTAMP'
- ) {
- $extracted_columnspec['attribute'] = $data['Extra'];
- unset($data['Extra']);
- }
- $current_timestamp = false;
- if (($data['Type'] == 'timestamp' || $data['Type'] == 'datetime')
- && $data['Default'] == 'CURRENT_TIMESTAMP'
- ) {
- $current_timestamp = true;
- }
- $default_type
- = $data['Null'] === 'YES' && $data['Default'] === null
- ? 'NULL'
- : ($current_timestamp
- ? 'CURRENT_TIMESTAMP'
- : ($data['Default'] === null
- ? 'NONE'
- : 'USER_DEFINED'));
-
- $changes[] = 'CHANGE ' . PMA_Table::generateAlter(
- $column,
- $column,
- /*overload*/mb_strtoupper($extracted_columnspec['type']),
- $extracted_columnspec['spec_in_brackets'],
- $extracted_columnspec['attribute'],
- isset($data['Collation']) ? $data['Collation'] : '',
- $data['Null'] === 'YES' ? 'NULL' : 'NOT NULL',
- $default_type,
- $current_timestamp ? '' : $data['Default'],
- isset($data['Extra']) && $data['Extra'] !== '' ? $data['Extra'] : false,
- isset($data['COLUMN_COMMENT']) && $data['COLUMN_COMMENT'] !== ''
- ? $data['COLUMN_COMMENT'] : false,
- $i === 0 ? '-first' : $column_names[$i - 1]
- );
- // update current column_names array, first delete old position
- for ($j = 0, $ll = count($column_names); $j < $ll; $j++) {
- if ($column_names[$j] == $column) {
- unset($column_names[$j]);
- }
- }
- // insert moved column
- array_splice($column_names, $i, 0, $column);
- }
- $response = PMA_Response::getInstance();
- if (empty($changes)) { // should never happen
- $response->isSuccess(false);
- exit;
- }
- $move_query = 'ALTER TABLE ' . PMA_Util::backquote($table) . ' ';
- $move_query .= implode(', ', $changes);
- // move columns
- $GLOBALS['dbi']->tryQuery($move_query);
- $tmp_error = $GLOBALS['dbi']->getError();
- if ($tmp_error) {
- $response->isSuccess(false);
- $response->addJSON('message', PMA_Message::error($tmp_error));
- } else {
- $message = PMA_Message::success(
- __('The columns have been moved successfully.')
- );
- $response->addJSON('message', $message);
- $response->addJSON('columns', $column_names);
- }
- exit;
-}
-
-/**
- * Get columns with unique index
- *
- * @param string $db database name
- * @param string $table tablename
- *
- * @return array $columns_with_unique_index An array of columns with unique index,
- * with $column name as the array key
- */
-function PMA_getColumnsWithUniqueIndex($db ,$table)
-{
- $columns_with_unique_index = array();
- foreach (PMA_Index::getFromTable($table, $db) as $index) {
- if ($index->isUnique() && $index->getChoice() == 'UNIQUE') {
- $columns = $index->getColumns();
- foreach ($columns as $column_name => $dummy) {
- $columns_with_unique_index[$column_name] = 1;
- }
- }
- }
- return $columns_with_unique_index;
-}
-
-/**
- * Function to get the type of command for multiple field handling
- *
- * @return string
- */
-function PMA_getMultipleFieldCommandType()
-{
- $submit_mult = null;
-
- if (isset($_REQUEST['submit_mult_change_x'])) {
- $submit_mult = 'change';
- } elseif (isset($_REQUEST['submit_mult_drop_x'])) {
- $submit_mult = 'drop';
- } elseif (isset($_REQUEST['submit_mult_primary_x'])) {
- $submit_mult = 'primary';
- } elseif (isset($_REQUEST['submit_mult_index_x'])) {
- $submit_mult = 'index';
- } elseif (isset($_REQUEST['submit_mult_unique_x'])) {
- $submit_mult = 'unique';
- } elseif (isset($_REQUEST['submit_mult_spatial_x'])) {
- $submit_mult = 'spatial';
- } elseif (isset($_REQUEST['submit_mult_fulltext_x'])) {
- $submit_mult = 'ftext';
- } elseif (isset($_REQUEST['submit_mult_browse_x'])) {
- $submit_mult = 'browse';
- } elseif (isset($_REQUEST['submit_mult'])) {
- $submit_mult = $_REQUEST['submit_mult'];
- } elseif (isset($_REQUEST['mult_btn']) && $_REQUEST['mult_btn'] == __('Yes')) {
- $submit_mult = 'row_delete';
- if (isset($_REQUEST['selected'])) {
- $_REQUEST['selected_fld'] = $_REQUEST['selected'];
- }
- }
-
- return $submit_mult;
-}
-
-/**
- * Function to display table browse for selected columns
- *
- * @param string $db current database
- * @param string $table current table
- * @param string $goto goto page url
- * @param string $pmaThemeImage URI of the pma theme image
- *
- * @return void
- */
-function PMA_displayTableBrowseForSelectedColumns($db, $table, $goto,
- $pmaThemeImage
-) {
- $GLOBALS['active_page'] = 'sql.php';
- $sql_query = '';
- foreach ($_REQUEST['selected_fld'] as $sval) {
- if ($sql_query == '') {
- $sql_query .= 'SELECT ' . PMA_Util::backquote($sval);
- } else {
- $sql_query .= ', ' . PMA_Util::backquote($sval);
- }
- }
- $sql_query .= ' FROM ' . PMA_Util::backquote($db)
- . '.' . PMA_Util::backquote($table);
-
- // Parse and analyze the query
- include_once 'libraries/parse_analyze.inc.php';
-
- include_once 'libraries/sql.lib.php';
-
- PMA_executeQueryAndSendQueryResponse(
- $analyzed_sql_results, false, $db, $table, null, null, null, false,
- null, null, null, $goto, $pmaThemeImage, null, null,
- null, $sql_query, null, null
- );
-}
-
-/**
- * Function to check if a table is already in favorite list.
- *
- * @param string $db current database
- * @param string $current_table current table
- *
- * @return true|false
- */
-function PMA_checkFavoriteTable($db, $current_table)
-{
- foreach (
- $_SESSION['tmpval']['favorite_tables'][$GLOBALS['server']] as $key => $value
- ) {
- if ($value['db'] == $db && $value['table'] == $current_table) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Get HTML for favorite anchor.
- *
- * @param string $db current database
- * @param array $current_table current table
- * @param array $titles titles
- *
- * @return string The html output
- */
-function PMA_getHtmlForFavoriteAnchor($db, $current_table, $titles)
-{
- $html_output = '<a ';
- $html_output .= 'id="' . md5($current_table['TABLE_NAME'])
- . '_favorite_anchor" ';
- $html_output .= 'class="ajax favorite_table_anchor';
-
- // Check if current table is already in favorite list.
- $already_favorite = PMA_checkFavoriteTable($db, $current_table['TABLE_NAME']);
- $fav_params = array('db' => $db,
- 'ajax_request' => true,
- 'favorite_table' => $current_table['TABLE_NAME'],
- (($already_favorite?'remove':'add') . '_favorite') => true
- );
- $fav_url = 'db_structure.php' . PMA_URL_getCommon($fav_params);
- $html_output .= '" ';
- $html_output .= 'href="' . $fav_url
- . '" title="' . ($already_favorite ? __("Remove from Favorites")
- : __("Add to Favorites"))
- . '" data-favtargets="'
- . md5($db . "." . $current_table['TABLE_NAME'])
- . '" >'
- . (!$already_favorite ? $titles['NoFavorite']
- : $titles['Favorite']) . '</a>';
-
- return $html_output;
-}
-
-/**
- * Add or remove favorite tables
- *
- * @param string $db current database
- *
- * @return void
- */
-function PMA_addRemoveFavoriteTables($db)
-{
- $fav_instance = PMA_RecentFavoriteTable::getInstance('favorite');
- if (isset($_REQUEST['favorite_tables'])) {
- $favorite_tables = json_decode($_REQUEST['favorite_tables'], true);
- } else {
- $favorite_tables = array();
- }
- // Required to keep each user's preferences separate.
- $user = sha1($GLOBALS['cfg']['Server']['user']);
-
- // Request for Synchronization of favorite tables.
- if (isset($_REQUEST['sync_favorite_tables'])) {
- PMA_synchronizeFavoriteTables($fav_instance, $user, $favorite_tables);
- exit;
- }
- $changes = true;
- $msg = '';
- $titles = PMA_Util::buildActionTitles();
- $favorite_table = $_REQUEST['favorite_table'];
- $already_favorite = PMA_checkFavoriteTable($db, $favorite_table);
-
- if (isset($_REQUEST['remove_favorite'])) {
- if ($already_favorite) {
- // If already in favorite list, remove it.
- $fav_instance->remove($db, $favorite_table);
- }
- } elseif (isset($_REQUEST['add_favorite'])) {
- if (!$already_favorite) {
- if (count($fav_instance->getTables()) == $GLOBALS['cfg']['NumFavoriteTables']) {
- $changes = false;
- $msg = '<div class="error"><img src="themes/dot.gif" '
- . 'title="" alt="" class="icon ic_s_error" />'
- . __("Favorite List is full!")
- . '</div>';
- } else {
- // Otherwise add to favorite list.
- $fav_instance->add($db, $favorite_table);
- }
- }
- }
-
- $favorite_tables[$user] = $fav_instance->getTables();
- $ajax_response = PMA_Response::getInstance();
- $ajax_response->addJSON(
- 'changes',
- $changes
- );
- if ($changes) {
- $ajax_response->addJSON(
- 'user',
- $user
- );
- $ajax_response->addJSON(
- 'favorite_tables',
- json_encode($favorite_tables)
- );
- $ajax_response->addJSON(
- 'list',
- $fav_instance->getHtmlList()
- );
- $ajax_response->addJSON(
- 'anchor',
- PMA_getHtmlForFavoriteAnchor(
- $db, array('TABLE_NAME' => $favorite_table), $titles
- )
- );
- } else {
- $ajax_response->addJSON(
- 'message',
- $msg
- );
- }
-}
-
-/**
- * Synchronize favorite tables
- *
- * @param PMA_RecentFavoriteTable $fav_instance Instance of this class
- * @param string $user The user hash
- * @param array $favorite_tables Existing favorites
- *
- * @return void
- */
-function PMA_synchronizeFavoriteTables($fav_instance, $user, $favorite_tables)
-{
- $fav_instance_tables = $fav_instance->getTables();
-
- if (empty($fav_instance_tables)
- && isset($favorite_tables[$user])
- ) {
- foreach ($favorite_tables[$user] as $key => $value) {
- $fav_instance->add($value['db'], $value['table']);
- }
- }
- $favorite_tables[$user] = $fav_instance->getTables();
-
- $ajax_response = PMA_Response::getInstance();
- $ajax_response->addJSON(
- 'favorite_tables',
- json_encode($favorite_tables)
- );
- $ajax_response->addJSON(
- 'list',
- $fav_instance->getHtmlList()
- );
- $server_id = $GLOBALS['server'];
- // Set flag when localStorage and pmadb(if present) are in sync.
- $_SESSION['tmpval']['favorites_synced'][$server_id] = true;
-}
-
-/**
- * Returns Html for show create.
- *
- * @param string $db Database name
- * @param array $db_objects Array containing DB objects
- *
- * @return string Html
- */
-function PMA_getHtmlShowCreate($db, $db_objects)
-{
- // Main outer container.
- $html_output = '<div class="show_create_results">'
- . '<h2>' . __('Showing create queries') . '</h2>';
- // Table header.
- $output_table = '<fieldset>'
- . '<legend>%s</legend>'
- . '<table class="show_create">'
- . '<thead>'
- . '<tr>'
- . '<th>%s</th>'
- . '<th>Create %s</th>'
- . '</tr>'
- . '</thead>'
- . '<tbody>';
- // Holds rows html for views.
- $views = '';
- // Holds rows html for tables.
- $tables = '';
- // Handles odd, even classes for rows.
- // for 'Views'
- $odd1 = true;
- // for 'Tables'
- $odd2 = true;
- // Iterate through each object.
- foreach ($db_objects as $key => $object) {
- // Check if current object is a View or Table.
- $isView = PMA_Table::isView($db, $object);
- if ($isView) {
- $row_class = ($odd1) ? 'odd' : 'even';
- $create_data = PMA_getShowCreate($db, $object, 'view');
- $views .= '<tr class="' . $row_class . '">'
- . '<td><strong>'
- . PMA_mimeDefaultFunction($create_data['View'])
- . '</strong></td>'
- . '<td>'
- . PMA_mimeDefaultFunction($create_data['Create View'])
- . '</td>'
- . '</tr>';
- $odd1 = ! $odd1;
- } else {
- $row_class = ($odd2) ? 'odd' : 'even';
- $create_data = PMA_getShowCreate($db, $object, 'table');
- $tables .= '<tr class="' . $row_class . '">'
- . '<td><strong>'
- . PMA_mimeDefaultFunction($create_data['Table'])
- . '</strong></td>'
- . '<td>'
- . PMA_mimeDefaultFunction($create_data['Create Table'])
- . '</td>'
- . '</tr>';
- $odd2 = ! $odd2;
- }
- }
- // Prepare table header for each type of object.
- if (! empty($tables)) {
- $title = __('Tables');
- $tables = sprintf($output_table, $title, 'Table', 'Table')
- . $tables
- . '</tbody></table></fieldset>';
- }
- if (! empty($views)) {
- $title = __('Views');
- $views = sprintf($output_table, $title, 'View', 'View')
- . $views
- . '</tbody></table></fieldset>';
- }
- // Compile the final html.
- $html_output .= $tables . $views . '</div>';
-
- return $html_output;
-}
-
-/**
- * Return 'SHOW CREATE' query for a DB object
- *
- * @param string $db Database name
- * @param string $db_object Database object name
- * @param string $type Type of object (table or view)
- *
- * @return mysqli_result collection | boolean(false)
- */
-function PMA_getShowCreate($db, $db_object, $type = 'table')
-{
- // 'SHOW CREATE' SQL query for specific type of DB object.
- switch ($type) {
- case 'table':
- $sql_query = 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($db_object);
- break;
- case 'view':
- $sql_query = 'SHOW CREATE VIEW ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($db_object);
- break;
- default:
- $sql_query = '';
- }
- // Execute the query.
- $result = $GLOBALS['dbi']->fetchSingleRow($sql_query);
-
- return $result;
-}
-
-/**
- * Returns the real row count for a table
- *
- * @param string $db Database name
- * @param string $table Table name
- *
- * @return number
- */
-function PMA_getRealRowCountTable($db, $table)
-{
- // SQL query to get row count for a table.
- $sql_query = 'SELECT COUNT(*) AS ' . PMA_Util::backquote('row_count')
- . ' FROM ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($table);
- $result = $GLOBALS['dbi']->fetchSingleRow($sql_query);
- $row_count = $result['row_count'];
-
- return $row_count;
-}
-
-/**
- * Returns the real row count for all tables of a DB
- *
- * @param string $db Database name
- * @param array $tables Array containing table names.
- *
- * @return array
- */
-function PMA_getRealRowCountDb($db, $tables)
-{
- // Array to store the results.
- $row_count_all = array();
- // Iterate over each table and fetch real row count.
- foreach ($tables as $key => $table) {
- $row_count = PMA_getRealRowCountTable($db, $table['TABLE_NAME']);
- array_push(
- $row_count_all,
- array('table' => $table['TABLE_NAME'], 'row_count' => $row_count)
- );
- }
-
- return $row_count_all;
-}
-
-/**
- * Handles request for real row count on database level view page.
- *
- * @return boolean true
- */
-function PMA_handleRealRowCountRequest()
-{
- $ajax_response = PMA_Response::getInstance();
- // If there is a request to update all table's row count.
- if (isset($_REQUEST['real_row_count_all'])) {
- $real_row_count_all = PMA_getRealRowCountDb(
- $GLOBALS['db'],
- $GLOBALS['tables']
- );
- $ajax_response->addJSON(
- 'real_row_count_all',
- json_encode($real_row_count_all)
- );
- return true;
- }
- // Get the real row count for the table.
- $real_row_count = PMA_getRealRowCountTable(
- $GLOBALS['db'],
- $_REQUEST['table']
- );
- // Format the number.
- $real_row_count = PMA_Util::formatNumber($real_row_count, 0);
- $ajax_response->addJSON('real_row_count', $real_row_count);
- return true;
-}
-
-/**
- * Possibly show the table creation dialog
- *
- * @param string $db Current database name
- * @param bool $db_is_system_schema Whether this db is a system schema
- * @param PMA_Response $response PMA_Response instance
- *
- * @return void
- */
-function PMA_possiblyShowCreateTableDialog($db, $db_is_system_schema, $response)
-{
- if (empty($db_is_system_schema)) {
- ob_start();
- include 'libraries/display_create_table.lib.php';
- $content = ob_get_contents();
- ob_end_clean();
- $response->addHTML($content);
- } // end if (Create Table dialog)
-}
-
-/**
- * Returns the HTML for secondary levels tabs of the table structure page
- *
- * @return string HTML for secondary levels tabs
- */
-function PMA_getStructureSecondaryTabs($tbl_storage_engine)
-{
- $html_output = '';
-
- $cfgRelation = PMA_getRelationsParam();
- if ($cfgRelation['relwork']
- || PMA_Util::isForeignKeySupported(strtoupper($tbl_storage_engine))
- ) {
- $url_params = array();
- $url_params['db'] = $GLOBALS['db'];
- $url_params['table'] = $GLOBALS['table'];
-
- $html_output .= '<ul id="topmenu2">';
- foreach (PMA_getStructureSubTabs() as $tab) {
- $html_output .= PMA_Util::getHtmlTab($tab, $url_params);
- }
- $html_output .= '</ul>';
- $html_output .= '<div class="clearfloat"></div>';
- }
- return $html_output;
-}
-
-/**
- * Returns an array with necessary configurations to create
- * sub-tabs in the Structure page at table level
- *
- * @return array Array containing configuration (icon, text, link, id)
- * of sub-tabs
- */
-function PMA_getStructureSubTabs()
-{
- $subtabs = array();
-
- $subtabs['structure']['icon'] = 'b_props';
- $subtabs['structure']['link'] = 'tbl_structure.php';
- $subtabs['structure']['text'] = __('Table structure');
- $subtabs['structure']['id'] = 'table_strucuture_id';
-
- $subtabs['relation']['icon'] = 'b_relations';
- $subtabs['relation']['link'] = 'tbl_relation.php';
- $subtabs['relation']['text'] = __('Relation view');
- $subtabs['relation']['id'] = 'table_relation_id';
-
- return $subtabs;
-}
-?>
diff --git a/libraries/sysinfo.lib.php b/libraries/sysinfo.lib.php
index 602485172b..6602beed3d 100644
--- a/libraries/sysinfo.lib.php
+++ b/libraries/sysinfo.lib.php
@@ -50,6 +50,7 @@ function PMA_getSysInfo()
if (in_array($php_os, $supported)) {
$class_name = 'PMA_SysInfo' . $php_os;
+ /** @var PMA_SysInfo $ret */
$ret = new $class_name();
if ($ret->supported()) {
return $ret;
@@ -176,7 +177,7 @@ class PMA_SysInfoWinnt extends PMA_SysInfo
$arrInstance = array();
foreach ($arrProp as $propItem) {
$name = $propItem->Name;
- if ( empty($strValue) || in_array($name, $strValue)) {
+ if (empty($strValue) || in_array($name, $strValue)) {
$value = $objItem->$name;
$arrInstance[$name] = trim($value);
}
diff --git a/libraries/tbl_chart.lib.php b/libraries/tbl_chart.lib.php
deleted file mode 100644
index ffd692bc8a..0000000000
--- a/libraries/tbl_chart.lib.php
+++ /dev/null
@@ -1,384 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-
-/**
- * functions for displaying chart
- *
- * @usedby tbl_chart.php
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Function to get html for pma_token and url_query
- *
- * @param string $url_query url query
- *
- * @return string
- */
-function PMA_getHtmlForPmaTokenAndUrlQuery($url_query)
-{
- $htmlString = '<script type="text/javascript">'
- . "pma_token = '" . $_SESSION[' PMA_token '] . "';"
- . "url_query = '" . $url_query . "';"
- . '</script>';
- return $htmlString;
-}
-
-/**
- * Function to get html for the chart type options
- *
- * @return string
- */
-function PMA_getHtmlForChartTypeOptions()
-{
- $html = '<input type="radio" name="chartType" value="bar" id="radio_bar" />'
- . '<label for ="radio_bar">' . _pgettext('Chart type', 'Bar') . '</label>'
- . '<input type="radio" name="chartType" value="column" id="radio_column" />'
- . '<label for ="radio_column">' . _pgettext('Chart type', 'Column')
- . '</label>'
- . '<input type="radio" name="chartType" value="line" id="radio_line"'
- . ' checked="checked" />'
- . '<label for ="radio_line">' . _pgettext('Chart type', 'Line') . '</label>'
- . '<input type="radio" name="chartType" value="spline" id="radio_spline" />'
- . '<label for ="radio_spline">' . _pgettext('Chart type', 'Spline')
- . '</label>'
- . '<input type="radio" name="chartType" value="area" id="radio_area" />'
- . '<label for ="radio_area">' . _pgettext('Chart type', 'Area') . '</label>'
- . '<span class="span_pie" style="display:none;">'
- . '<input type="radio" name="chartType" value="pie" id="radio_pie" />'
- . '<label for ="radio_pie">' . _pgettext('Chart type', 'Pie') . '</label>'
- . '</span>'
- . '<span class="span_timeline" style="display:none;">'
- . '<input type="radio" name="chartType" '
- . 'value="timeline" id="radio_timeline" />'
- . '<label for ="radio_timeline">' . _pgettext('Chart type', 'Timeline')
- . '</label>'
- . '</span>'
- . '<span class="span_scatter" style="display:none;">'
- . '<input type="radio" name="chartType" '
- . 'value="scatter" id="radio_scatter" />'
- . '<label for ="radio_scatter">' . _pgettext('Chart type', 'Scatter')
- . '</label>'
- . '</span>'
- . '<br /><br />';
-
- return $html;
-}
-
-/**
- * Function to get html for the bar stacked option
- *
- * @return string
- */
-function PMA_getHtmlForStackedOption()
-{
- $html = '<span class="barStacked" style="display:none;">'
- . '<input type="checkbox" name="barStacked" value="1"'
- . ' id="checkbox_barStacked" />'
- . '<label for ="checkbox_barStacked">' . __('Stacked') . '</label>'
- . '</span>'
- . '<br /><br />';
-
- return $html;
-}
-
-/**
- * Function to get html for the chart x axis options
- *
- * @param array $keys keys
- * @param int &$xaxis x axis
- *
- * @return string
- */
-function PMA_getHtmlForChartXAxisOptions($keys, &$xaxis)
-{
- $htmlString = '<div style="float:left; padding-left:40px;">'
- . '<label for="select_chartXAxis">' . __('X-Axis:') . '</label>'
- . '<select name="chartXAxis" id="select_chartXAxis">';
-
- foreach ($keys as $idx => $key) {
- if ($xaxis === null) {
- $htmlString .= '<option value="' . htmlspecialchars($idx)
- . '" selected="selected">' . htmlspecialchars($key) . '</option>';
- $xaxis = $idx;
- } else {
- $htmlString .= '<option value="' . htmlspecialchars($idx) . '">'
- . htmlspecialchars($key) . '</option>';
- }
- }
- $htmlString .= '</select>';
-
- return $htmlString;
-}
-
-/**
- * Function to get html for chart series options
- *
- * @param array $keys keys
- * @param array $fields_meta fields meta
- * @param array $numeric_types numeric types
- * @param int $xaxis x axis
- * @param int $numeric_column_count numeric column count
- *
- * @return string
- */
-function PMA_getHtmlForChartSeriesOptions($keys, $fields_meta, $numeric_types,
- $xaxis, $numeric_column_count
-) {
- $htmlString = '<br />'
- . '<label for="select_chartSeries">' . __('Series:') . '</label>'
- . '<select name="chartSeries" id="select_chartSeries" multiple="multiple">';
-
- foreach ($keys as $idx => $key) {
- if (in_array($fields_meta[$idx]->type, $numeric_types)) {
- if ($idx == $xaxis && $numeric_column_count > 1) {
- $htmlString .= '<option value="' . htmlspecialchars($idx) . '">'
- . htmlspecialchars($key) . '</option>';
- } else {
- $htmlString .= '<option value="' . htmlspecialchars($idx)
- . '" selected="selected">' . htmlspecialchars($key)
- . '</option>';
- }
- }
- }
- $htmlString .= '</select>';
- return $htmlString;
-}
-
-/**
- * Function to get html for date time columns
- *
- * @param array $keys keys
- * @param array $fields_meta fields meta
- *
- * @return string
- */
-function PMA_getHtmlForDateTimeCols($keys, $fields_meta)
-{
- $htmlString = '<input type="hidden" name="dateTimeCols" value="';
-
- $date_time_types = array('date', 'datetime', 'timestamp');
- foreach ($keys as $idx => $key) {
- if (in_array($fields_meta[$idx]->type, $date_time_types)) {
- $htmlString .= $idx . " ";
- }
- }
- $htmlString .= '" />';
-
- return $htmlString;
-}
-
-/**
- * Function to get html for date time columns
- *
- * @param array $keys keys
- * @param array $fields_meta fields meta
- * @param array $numeric_types numeric types
- *
- * @return string
- */
-function PMA_getHtmlForNumericCols($keys, $fields_meta, $numeric_types)
-{
- $htmlString = '<input type="hidden" name="numericCols" value="';
- foreach ($keys as $idx => $key) {
- if (in_array($fields_meta[$idx]->type, $numeric_types)) {
- $htmlString .= $idx . " ";
- }
- }
- $htmlString .= '" />';
-
- return $htmlString;
-}
-
-/**
- * Function to get html for the table axis label options
- *
- * @param int $xaxis x axis
- * @param array $keys keys
- *
- * @return string
- */
-function PMA_getHtmlForTableAxisLabelOptions($xaxis, $keys)
-{
- $htmlString = '<div style="float:left; padding-left:40px;">'
- . '<label for="xaxis_label">' . __('X-Axis label:') . '</label>'
- . '<input style="margin-top:0;" type="text" name="xaxis_label" id="xaxis_label"'
- . ' value="'
- . (($xaxis == -1) ? __('X Values') : htmlspecialchars($keys[$xaxis]))
- . '" /><br />'
- . '<label for="yaxis_label">' . __('Y-Axis label:') . '</label>'
- . '<input type="text" name="yaxis_label" id="yaxis_label" value="'
- . __('Y Values') . '" /><br />'
- . '</div>';
-
- return $htmlString;
-}
-
-/**
- * Function to get html for switching to alternative data format
- *
- * @param array $keys keys
- * @param array $fields_meta fields meta
- * @param array $numeric_types numeric types
- * @param int $xaxis x axis
- *
- * @return string
- */
-function PMA_getHtmlForAlternativeDataFormat($keys, $fields_meta, $numeric_types,
- $xaxis
-) {
- $htmlString = '<p style="clear:both;">&nbsp;</p>'
- . '<div><input type="checkbox" id="chkAlternative" '
- . 'name="chkAlternative" value="alternativeFormat">'
- . __('Series names are in a column') . '</input>';
-
- $htmlString .= '<br />'
- . '<label for="select_seriesColumn">' . __('Series column:') . '</label>'
- . '<select name="chartSeriesColumn" id="select_seriesColumn" disabled>';
- foreach ($keys as $idx => $key) {
- $htmlString .= '<option value="' . htmlspecialchars($idx) . '"';
- if ($idx == 1) {
- $htmlString .= ' selected="selected"';
- $seriesColumn = $idx;
- }
- $htmlString .= '>' . htmlspecialchars($key) . '</option>';
- }
- $htmlString .= '</select>';
-
- $htmlString .= '<label for="select_valueColumn">'
- . __('Value column:') . '</label>'
- . '<select name="chartValueColumn" id="select_valueColumn" disabled>';
-
- $selected = false;
- foreach ($keys as $idx => $key) {
- if (in_array($fields_meta[$idx]->type, $numeric_types)) {
- if (! $selected && $idx != $xaxis && $idx != $seriesColumn) {
- $htmlString .= '<option value="' . htmlspecialchars($idx)
- . '" selected="selected">' . htmlspecialchars($key)
- . '</option>';
- $selected = true;
- } else {
- $htmlString .= '<option value="' . htmlspecialchars($idx) . '">'
- . htmlspecialchars($key) . '</option>';
- }
- }
- }
- $htmlString .= '</select></div>';
- return $htmlString;
-}
-
-/**
- * Function to get html for the start row and number of rows options
- *
- * @param string $sql_query sql query
- *
- * @return string
- */
-function PMA_getHtmlForStartAndNumberOfRowsOptions($sql_query)
-{
- $htmlString = '<p style="clear:both;">&nbsp;</p>'
- . '<fieldset>'
- . '<div>'
- . '<label for="pos">' . __('Start row:') . '</label>'
- . '<input type="text" name="pos" size="3" value="'
- . $_SESSION['tmpval']['pos'] . '" />'
- . '<label for="session_max_rows">'
- . __('Number of rows:') . '</label>'
- . '<input type="text" name="session_max_rows" size="3" value="'
- . (($_SESSION['tmpval']['max_rows'] != 'all')
- ? $_SESSION['tmpval']['max_rows']
- : $GLOBALS['cfg']['MaxRows'])
- . '" />'
- . '<input type="submit" name="submit" class="Go" value="' . __('Go')
- . '" />'
- . '<input type="hidden" name="sql_query" value="'
- . htmlspecialchars($sql_query) . '" />'
- . '</div>'
- . '</fieldset>';
-
- return $htmlString;
-}
-
-/**
- * Function to get html for the chart area div
- *
- * @return string
- */
-function PMA_getHtmlForChartAreaDiv()
-{
- $htmlString = '<p style="clear:both;">&nbsp;</p>'
- . '<div id="resizer" style="width:600px; height:400px;">'
- . '<div style="position: absolute; right: 10px;'
- . ' top: 10px; cursor: pointer; z-index: 1000;">'
- . '<a class="disableAjax" id="saveChart" href="#" download="chart.png">'
- . PMA_Util::getImage('b_saveimage', __('Save chart as image'))
- . '</a>'
- . '</div>'
- . '<div id="querychart">'
- . '</div>'
- . '</div>';
-
- return $htmlString;
-}
-
-/**
- * Function to get html for displaying table chart
- *
- * @param string $url_query url query
- * @param array $url_params url parameters
- * @param array $keys keys
- * @param array $fields_meta fields meta
- * @param array $numeric_types numeric types
- * @param int $numeric_column_count numeric column count
- * @param string $sql_query sql query
- *
- * @return string
- */
-function PMA_getHtmlForTableChartDisplay($url_query, $url_params, $keys,
- $fields_meta, $numeric_types, $numeric_column_count, $sql_query
-) {
- // pma_token/url_query needed for chart export
- $htmlString = PMA_getHtmlForPmaTokenAndUrlQuery($url_query);
- $htmlString .= '<!-- Display Chart options -->'
- . '<div id="div_view_options">'
- . '<form method="post" id="tblchartform" action="tbl_chart.php" '
- . 'class="ajax">'
- . PMA_URL_getHiddenInputs($url_params)
- . '<fieldset>'
- . '<legend>' . __('Display chart') . '</legend>'
- . '<div style="float:left; width:420px;">';
- $htmlString .= PMA_getHtmlForChartTypeOptions();
- $htmlString .= PMA_getHtmlForStackedOption();
-
- $htmlString .= '<input type="text" name="chartTitle" value="'
- . __('Chart title')
- . '">'
- . '</div>';
- $xaxis = null;
- $htmlString .= PMA_getHtmlForChartXAxisOptions($keys, $xaxis);
- $htmlString .= PMA_getHtmlForChartSeriesOptions(
- $keys, $fields_meta, $numeric_types, $xaxis, $numeric_column_count
- );
- $htmlString .= PMA_getHtmlForDateTimeCols($keys, $fields_meta);
- $htmlString .= PMA_getHtmlForNumericCols($keys, $fields_meta, $numeric_types);
- $htmlString .= '</div>';
-
- $htmlString .= PMA_getHtmlForTableAxisLabelOptions($xaxis, $keys);
- $htmlString .= PMA_getHtmlForAlternativeDataFormat(
- $keys, $fields_meta, $numeric_types, $xaxis
- );
- $htmlString .= PMA_getHtmlForStartAndNumberOfRowsOptions($sql_query);
-
- $htmlString .= PMA_getHtmlForChartAreaDiv();
-
- $htmlString .= '</fieldset>'
- . '</form>'
- . '</div>';
-
- return $htmlString;
-}
-?>
diff --git a/libraries/tbl_columns_definition_form.inc.php b/libraries/tbl_columns_definition_form.inc.php
index 8f3cafb4e4..9dd8a34677 100644
--- a/libraries/tbl_columns_definition_form.inc.php
+++ b/libraries/tbl_columns_definition_form.inc.php
@@ -6,33 +6,37 @@
*
* @package PhpMyAdmin
*/
-if (! defined('PHPMYADMIN')) {
+if (!defined('PHPMYADMIN')) {
exit;
}
/**
* Check parameters
*/
-require_once './libraries/Util.class.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/Util.class.php';
+require_once 'libraries/Template.class.php';
+require_once 'libraries/util.lib.php';
+
+use PMA\Util;
PMA_Util::checkParameters(array('server', 'db', 'table', 'action', 'num_fields'));
+global $db, $table;
+
/**
* Initialize to avoid code execution path warnings
*/
-if (! isset($num_fields)) {
+if (!isset($num_fields)) {
$num_fields = 0;
}
-if (! isset($mime_map)) {
+if (!isset($mime_map)) {
$mime_map = null;
}
-if (! isset($columnMeta)) {
+if (!isset($columnMeta)) {
$columnMeta = array();
}
-if (! isset($content_cells)) {
- $content_cells = array();
-}
// Get available character sets and storage engines
@@ -44,40 +48,71 @@ require_once './libraries/StorageEngine.class.php';
*/
require_once './libraries/Partition.class.php';
-require_once './libraries/tbl_columns_definition_form.lib.php';
-
/** @var PMA_String $pmaString */
$pmaString = $GLOBALS['PMA_String'];
$length_values_input_size = 8;
-$_form_params = PMA_getFormsParameters(
- $db, $table, $action, isset($num_fields) ? $num_fields : null,
- isset($selected) ? $selected : null
+$content_cells = array();
+
+/** @var string $db */
+$form_params = array(
+ 'db' => $db
);
+if ($action == 'tbl_create.php') {
+ $form_params['reload'] = 1;
+} else {
+ if ($action == 'tbl_addfield.php') {
+ $form_params = array_merge(
+ $form_params, array(
+ 'field_where' => Util\get($_REQUEST, 'field_where'))
+ );
+ if (isset($_REQUEST['field_where'])) {
+ $form_params['after_field'] = $_REQUEST['after_field'];
+ }
+ }
+ $form_params['table'] = $table;
+}
+
+if (isset($num_fields)) {
+ $form_params['orig_num_fields'] = $num_fields;
+}
+
+$form_params = array_merge(
+ $form_params,
+ array(
+ 'orig_field_where' => Util\get($_REQUEST, 'field_where'),
+ 'orig_after_field' => Util\get($_REQUEST, 'after_field'),
+ )
+);
+
+if (isset($selected) && is_array($selected)) {
+ foreach ($selected as $o_fld_nr => $o_fld_val) {
+ $form_params['selected[' . $o_fld_nr . ']'] = $o_fld_val;
+ }
+}
+
$is_backup = ($action != 'tbl_create.php' && $action != 'tbl_addfield.php');
require_once './libraries/transformations.lib.php';
$cfgRelation = PMA_getRelationsParam();
-
$comments_map = PMA_getComments($db, $table);
+$move_columns = array();
if (isset($fields_meta)) {
- $move_columns = PMA_getMoveColumns($db, $table);
+ /** @var PMA_DatabaseInterface $dbi */
+ $dbi = \PMA\DI\Container::getDefaultContainer()->get('dbi');
+ $move_columns = $dbi->getTable($db, $table)->getColumnsMeta();
}
+$available_mime = array();
if ($cfgRelation['mimework'] && $GLOBALS['cfg']['BrowseMIME']) {
$mime_map = PMA_getMIME($db, $table);
$available_mime = PMA_getAvailableMIMEtypes();
}
-$header_cells = PMA_getHeaderCells(
- $is_backup, isset($fields_meta) ? $fields_meta : null,
- $cfgRelation['mimework'], $db, $table
-);
-
// workaround for field_fulltext, because its submitted indices contain
// the index as a value, not a key. Inserted here for easier maintenance
// and less code to change in existing files.
@@ -98,21 +133,142 @@ $child_references = null;
if (PMA_MYSQL_INT_VERSION < 50606) {
$child_references = PMA_getChildReferences($db, $table);
}
+
for ($columnNumber = 0; $columnNumber < $num_fields; $columnNumber++) {
- if (! empty($regenerate)) {
- list($columnMeta, $submit_length, $submit_attribute,
- $submit_default_current_timestamp, $comments_map, $mime_map)
- = PMA_handleRegeneration(
- $columnNumber,
- isset($available_mime) ? $mime_map : null,
- $comments_map, $mime_map
- );
+
+ $type = '';
+ $length = '';
+ $columnMeta = array();
+ $submit_attribute = null;
+ $extracted_columnspec = array();
+
+ if (!empty($regenerate)) {
+
+ $columnMeta = array_merge(
+ $columnMeta,
+ array(
+ 'Field' => Util\get(
+ $_REQUEST, "field_name.${columnNumber}", false
+ ),
+ 'Type' => Util\get(
+ $_REQUEST, "field_type.${columnNumber}", false
+ ),
+ 'Collation' => Util\get(
+ $_REQUEST, "field_collation.${columnNumber}", ''
+ ),
+ 'Null' => Util\get(
+ $_REQUEST, "field_null.${columnNumber}", ''
+ ),
+ 'DefaultType' => Util\get(
+ $_REQUEST, "field_default_type.${columnNumber}", 'NONE'
+ ),
+ 'DefaultValue' => Util\get(
+ $_REQUEST, "field_default_value.${columnNumber}", ''
+ ),
+ 'Extra' => Util\get(
+ $_REQUEST, "field_extra.${columnNumber}", false
+ ),
+ 'Virtuality' => Util\get(
+ $_REQUEST, "field_virtuality.${columnNumber}", ''
+ ),
+ 'Expression' => Util\get(
+ $_REQUEST, "field_expression.${columnNumber}", ''
+ ),
+ )
+ );
+
+ $columnMeta['Key'] = '';
+ $parts = explode(
+ '_', Util\get($_REQUEST, "field_key.${columnNumber}", ''), 2
+ );
+ if (count($parts) == 2 && $parts[1] == $columnNumber) {
+ $columnMeta['Key'] = Util\get(
+ array(
+ 'primary' => 'PRI',
+ 'index' => 'MUL',
+ 'unique' => 'UNI',
+ 'fulltext' => 'FULLTEXT',
+ 'spatial' => 'SPATIAL'
+ ),
+ $parts[0], ''
+ );
+ }
+
+ $columnMeta['Comment']
+ = isset($submit_fulltext[$columnNumber])
+ && ($submit_fulltext[$columnNumber] == $columnNumber)
+ ? 'FULLTEXT' : false;
+
+ switch ($columnMeta['DefaultType']) {
+ case 'NONE':
+ $columnMeta['Default'] = null;
+ break;
+ case 'USER_DEFINED':
+ $columnMeta['Default'] = $columnMeta['DefaultValue'];
+ break;
+ case 'NULL':
+ case 'CURRENT_TIMESTAMP':
+ $columnMeta['Default'] = $columnMeta['DefaultType'];
+ break;
+ }
+
+ $length = Util\get($_REQUEST, "field_length.${columnNumber}", $length);
+ $submit_attribute = Util\get(
+ $_REQUEST, "field_attribute.${columnNumber}", false
+ );
+ $comments_map[$columnMeta['Field']] = Util\get(
+ $_REQUEST, "field_comments.${columnNumber}"
+ );
+
+ $mime_map[$columnMeta['Field']] = array_merge(
+ $mime_map[$columnMeta['Field']],
+ array(
+ 'mimetype' => Util\get($_REQUEST, "field_mimetype.${$columnNumber}"),
+ 'transformation' => Util\get(
+ $_REQUEST, "field_transformation.${$columnNumber}"
+ ),
+ 'transformation_options' => Util\get(
+ $_REQUEST, "field_transformation_options.${$columnNumber}"
+ ),
+ )
+ );
+
} elseif (isset($fields_meta[$columnNumber])) {
- $columnMeta = PMA_getColumnMetaForDefault(
- $fields_meta[$columnNumber],
- isset($analyzed_sql[0]['create_table_fields']
- [$fields_meta[$columnNumber]['Field']]['default_value'])
+ $columnMeta = $fields_meta[$columnNumber];
+ $virtual = array(
+ 'VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED'
);
+ if (in_array($columnMeta['Extra'], $virtual)) {
+ $tableObj = new PMA_Table($GLOBALS['table'], $GLOBALS['db']);
+ $expressions = $tableObj->getColumnGenerationExpression(
+ $columnMeta['Field']
+ );
+ $columnMeta['Expression'] = $expressions[$columnMeta['Field']];
+ }
+ switch ($columnMeta['Default']) {
+ case null:
+ if (is_null($columnMeta['Default'])) { // null
+ if ($columnMeta['Null'] == 'YES') {
+ $columnMeta['DefaultType'] = 'NULL';
+ $columnMeta['DefaultValue'] = '';
+ } else {
+ $columnMeta['DefaultType'] = 'NONE';
+ $columnMeta['DefaultValue'] = '';
+ }
+ } else { // empty
+ $columnMeta['DefaultType'] = 'USER_DEFINED';
+ $columnMeta['DefaultValue'] = $columnMeta['Default'];
+ }
+ break;
+ case 'CURRENT_TIMESTAMP':
+ $columnMeta['DefaultType'] = 'CURRENT_TIMESTAMP';
+ $columnMeta['DefaultValue'] = '';
+ break;
+ default:
+ $columnMeta['DefaultType'] = 'USER_DEFINED';
+ $columnMeta['DefaultValue'] = $columnMeta['Default'];
+ break;
+ }
}
if (isset($columnMeta['Type'])) {
@@ -122,74 +278,147 @@ for ($columnNumber = 0; $columnNumber < $num_fields; $columnNumber++) {
= PMA_Util::convertBitDefaultValue($columnMeta['Default']);
}
$type = $extracted_columnspec['type'];
- $length = $extracted_columnspec['spec_in_brackets'];
+ if ($length == '') {
+ $length = $extracted_columnspec['spec_in_brackets'];
+ }
} else {
// creating a column
$columnMeta['Type'] = '';
- $type = '';
- $length = '';
- $extracted_columnspec = array();
- }
-
- // some types, for example longtext, are reported as
- // "longtext character set latin7" when their charset and / or collation
- // differs from the ones of the corresponding database.
- $tmp = /*overload*/mb_strpos($type, 'character set');
- if ($tmp) {
- $type = /*overload*/mb_substr($type, 0, $tmp - 1);
- }
- // rtrim the type, for cases like "float unsigned"
- $type = rtrim($type);
-
-
- if (isset($submit_length) && $submit_length != false) {
- $length = $submit_length;
}
// Variable tell if current column is bound in a foreign key constraint or not.
// MySQL version from 5.6.6 allow renaming columns with foreign keys
if (isset($columnMeta['Field'])
- && isset($_form_params['table'])
+ && isset($form_params['table'])
&& PMA_MYSQL_INT_VERSION < 50606
) {
$columnMeta['column_status'] = PMA_checkChildForeignReferences(
- $_form_params['db'],
- $_form_params['table'],
+ $form_params['db'],
+ $form_params['table'],
$columnMeta['Field'],
$foreigners,
$child_references
);
}
- // old column attributes
+
+ // some types, for example longtext, are reported as
+ // "longtext character set latin7" when their charset and / or collation
+ // differs from the ones of the corresponding database.
+ // rtrim the type, for cases like "float unsigned"
+ $type = rtrim(
+ mb_ereg_replace('[\w\W]character set[\w\W]*', '', $type)
+ );
+
+ /**
+ * old column attributes
+ */
if ($is_backup) {
- $_form_params = PMA_getFormParamsForOldColumn(
- $columnMeta, $length, $_form_params, $columnNumber, $type,
- $extracted_columnspec
+
+ // old column name
+ if (isset($columnMeta['Field'])) {
+ $form_params['field_orig[' . $columnNumber . ']']
+ = $columnMeta['Field'];
+ if (isset($columnMeta['column_status'])
+ && !$columnMeta['column_status']['isEditable']
+ ) {
+ $form_params['field_name[' . $columnNumber . ']']
+ = $columnMeta['Field'];
+ }
+ } else {
+ $form_params['field_orig[' . $columnNumber . ']'] = '';
+ }
+
+ // old column type
+ if (isset($columnMeta['Type'])) {
+ // keep in uppercase because the new type will be in uppercase
+ $form_params['field_type_orig[' . $columnNumber . ']']
+ = /*overload*/
+ mb_strtoupper($type);
+ if (isset($columnMeta['column_status'])
+ && !$columnMeta['column_status']['isEditable']
+ ) {
+ $form_params['field_type[' . $columnNumber . ']']
+ = /*overload*/
+ mb_strtoupper($type);
+ }
+ } else {
+ $form_params['field_type_orig[' . $columnNumber . ']'] = '';
+ }
+
+ // old column length
+ $form_params['field_length_orig[' . $columnNumber . ']'] = $length;
+
+ // old column default
+ $form_params = array_merge(
+ $form_params,
+ array(
+ "field_default_value_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Default', ''
+ ),
+ "field_default_type_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'DefaultType', ''
+ ),
+ "field_collation_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Collation', ''
+ ),
+ "field_attribute_orig[${columnNumber}]" => trim(
+ Util\get($extracted_columnspec, 'attribute', '')
+ ),
+ "field_null_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Null', ''
+ ),
+ "field_extra_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Extra', ''
+ ),
+ "field_comments_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Comment', ''
+ ),
+ "field_virtuality_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Virtuality', ''
+ ),
+ "field_expression_orig[${columnNumber}]" => Util\get(
+ $columnMeta, 'Expression', ''
+ ),
+ )
);
}
- $content_cells[$columnNumber] = PMA_getHtmlForColumnAttributes(
- $columnNumber, isset($columnMeta) ? $columnMeta : array(),
- /*overload*/mb_strtoupper($type), $length_values_input_size, $length,
- isset($default_current_timestamp) ? $default_current_timestamp : null,
- isset($extracted_columnspec) ? $extracted_columnspec : null,
- isset($submit_attribute) ? $submit_attribute : null,
- isset($analyzed_sql) ? $analyzed_sql : null,
- $comments_map, isset($fields_meta) ? $fields_meta : null, $is_backup,
- isset($move_columns) ? $move_columns : array(), $cfgRelation,
- isset($available_mime) ? $available_mime : array(),
- isset($mime_map) ? $mime_map : array()
+ $content_cells[$columnNumber] = array(
+ 'columnNumber' => $columnNumber,
+ 'columnMeta' => $columnMeta,
+ 'type_upper' => /*overload*/mb_strtoupper($type),
+ 'length_values_input_size' => $length_values_input_size,
+ 'length' => $length,
+ 'extracted_columnspec' => $extracted_columnspec,
+ 'submit_attribute' => $submit_attribute,
+ 'comments_map' => $comments_map,
+ 'fields_meta' => isset($fields_meta) ? $fields_meta : null,
+ 'is_backup' => $is_backup,
+ 'move_columns' => $move_columns,
+ 'cfgRelation' => $cfgRelation,
+ 'available_mime' => $available_mime,
+ 'mime_map' => isset($mime_map) ? $mime_map : array()
);
} // end for
-$html = PMA_getHtmlForTableCreateOrAddField(
- $action, $_form_params, $content_cells, $header_cells
+
+$html = PMA\Template::get('columns_definitions/column_definitions_form')->render(
+ array(
+ 'is_backup' => $is_backup,
+ 'fields_meta' => isset($fields_meta) ? $fields_meta : null,
+ 'mimework' => $cfgRelation['mimework'],
+ 'action' => $action,
+ 'form_params' => $form_params,
+ 'content_cells' => $content_cells,
+ )
);
-unset($_form_params);
+unset($form_params);
+
$response = PMA_Response::getInstance();
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('jquery/jquery.uitablefilter.js');
-$scripts->addFile('indexes.js');
+$response->getHeader()->getScripts()->addFiles(
+ array(
+ 'jquery/jquery.uitablefilter.js',
+ 'indexes.js'
+ )
+);
$response->addHTML($html);
-?>
diff --git a/libraries/tbl_columns_definition_form.lib.php b/libraries/tbl_columns_definition_form.lib.php
deleted file mode 100644
index 9626ac6eb7..0000000000
--- a/libraries/tbl_columns_definition_form.lib.php
+++ /dev/null
@@ -1,1458 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * set of functions used by tbl_columns_definitions_form.inc.php
- *
- * @package PhpMyAdmin
- */
-if (!defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Function to get form parameters
- *
- * @param string $db database
- * @param string $table table
- * @param string $action action
- * @param int $num_fields number of fields
- * @param bool $selected selected
- *
- * @return array $form_params form parameters
- */
-function PMA_getFormsParameters(
- $db, $table, $action, $num_fields, $selected
-) {
- $form_params = array(
- 'db' => $db
- );
-
- if ($action == 'tbl_create.php') {
- $form_params['reload'] = 1;
- } elseif ($action == 'tbl_addfield.php') {
- $form_params['field_where'] = $_REQUEST['field_where'];
- $form_params['after_field'] = $_REQUEST['after_field'];
- $form_params['table'] = $table;
- } else {
- $form_params['table'] = $table;
- }
-
- if (isset($num_fields)) {
- $form_params['orig_num_fields'] = $num_fields;
- }
-
- if (isset($_REQUEST['field_where'])) {
- $form_params['orig_field_where'] = $_REQUEST['field_where'];
- }
-
- if (isset($_REQUEST['after_field'])) {
- $form_params['orig_after_field'] = $_REQUEST['after_field'];
- }
-
- if (isset($selected) && is_array($selected)) {
- foreach ($selected as $o_fld_nr => $o_fld_val) {
- $form_params['selected[' . $o_fld_nr . ']'] = $o_fld_val;
- }
- }
-
- return $form_params;
-}
-
-/**
- * Function to get html for table comments, storage engine, collation and
- * partition definition
- *
- * @return string
- */
-function PMA_getHtmlForTableConfigurations()
-{
- $html = '<table>';
- $html .= '<tr class="vtop">'
- . '<th>' . __('Table comments:') . '</th>'
- . '<td width="25">&nbsp;</td>'
- . '<th>' . __('Collation:') . '</th>'
- . '<td width="25">&nbsp;</td>'
- . '<th>'
- . __('Storage Engine:')
- . PMA_Util::showMySQLDocu('Storage_engines')
- . '</th>'
- . '<td width="25">&nbsp;</td>'
- . '<th>'
- . __('Connection:')
- . PMA_Util::showMySQLDocu('federated-create-connection')
- . '</th>'
- . '</tr>';
-
- $commentLength = PMA_MYSQL_INT_VERSION >= 50503 ? 2048 : 60;
- $html .= '<tr>'
- . '<td><input type="text" name="comment"'
- . ' size="40" maxlength="' . $commentLength . '"'
- . ' value="'
- . (isset($_REQUEST['comment'])
- ? htmlspecialchars($_REQUEST['comment'])
- : '')
- . '" class="textfield" />'
- . '</td>'
- . '<td width="25">&nbsp;</td>'
- . '<td>'
- . PMA_generateCharsetDropdownBox(
- PMA_CSDROPDOWN_COLLATION, 'tbl_collation', null,
- (isset($_REQUEST['tbl_collation'])
- ? $_REQUEST['tbl_collation']
- : null
- ),
- false
- )
- . '</td>'
- . '<td width="25">&nbsp;</td>'
- . '<td>'
- . PMA_StorageEngine::getHtmlSelect(
- 'tbl_storage_engine', null,
- (isset($_REQUEST['tbl_storage_engine'])
- ? $_REQUEST['tbl_storage_engine']
- : null
- )
- )
- . '</td>'
- . '<td width="25">&nbsp;</td>'
- . '<td><input type="text" name="connection" size="40"'
- . ' value="' . (isset($_REQUEST['connection'])
- ? htmlspecialchars($_REQUEST['connection'])
- : '') . '"'
- . ' placeholder="scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name"'
- . ' class="textfield" required="required" />'
- . '</td>'
- . '</tr>';
-
- if (PMA_Partition::havePartitioning()) {
- $html .= '<tr class="vtop">'
- . '<th>' . __('PARTITION definition:') . '&nbsp;'
- . PMA_Util::showMySQLDocu('Partitioning')
- . '</th>'
- . '</tr>'
- . '<tr>'
- . '<td>'
- . '<textarea name="partition_definition" id="partitiondefinition"'
- . ' cols="' . $GLOBALS['cfg']['TextareaCols'] . '"'
- . ' rows="' . $GLOBALS['cfg']['TextareaRows'] . '"'
- . ' dir="' . $GLOBALS['text_dir'] . '">'
- . (isset($_REQUEST['partition_definition'])
- ? htmlspecialchars($_REQUEST['partition_definition'])
- : '')
- . '</textarea>'
- . '</td>'
- . '</tr>';
- }
- $html .= '</table>'
- . '<br />';
-
- return $html;
-}
-
-/**
- * Function to get html for the footer
- *
- * @return string
- */
-function PMA_getHtmlForFooter()
-{
- $html = '<fieldset class="tblFooters">'
- . '<input type="button" class="preview_sql" value="'
- . __('Preview SQL') . '" />'
- . '<input type="submit" name="do_save_data" value="' . __('Save') . '" />'
- . '</fieldset>'
- . '<div id="properties_message"></div>'
- . '</form>';
-
- $html .= '<div id="popup_background"></div>';
-
- return $html;
-}
-
-/**
- * Function to get html for table create table name and number of fields
- *
- * @return string
- */
-function PMA_getHtmlForTableNameAndNoOfColumns()
-{
- $html = '<table>'
- . '<tr class="vmiddle">'
- . '<td>' . __('Table name')
- . ':&nbsp;<input type="text" name="table" size="40" maxlength="80"'
- . ' value="'
- . (isset($_REQUEST['table']) ? htmlspecialchars($_REQUEST['table']) : '')
- . '" class="textfield" autofocus required />'
- . '</td>'
- . '<td>';
- $html .= sprintf(
- __('Add %s column(s)'), '<input type="text" id="added_fields" '
- . 'name="added_fields" size="2" value="1" onfocus="this.select'
- . '()" />'
- );
-
- $html .= '<input type="button" name="submit_num_fields"'
- . 'value="' . __('Go') . '" />';
-
- $html .= '</td>'
- . '</tr>'
- . '</table>';
-
- return $html;
-}
-
-/**
- * Function to get html for table field definitions
- *
- * @param array $header_cells header cells
- * @param array $content_cells content cells
- *
- * @return string
- */
-function PMA_getHtmlForTableFieldDefinitions($header_cells, $content_cells)
-{
- $html = '<table id="table_columns" class="noclick">';
- $html .= '<caption class="tblHeaders">' . __('Structure')
- . PMA_Util::showMySQLDocu('CREATE_TABLE') . '</caption>';
-
- $html .= '<tr>';
- foreach ($header_cells as $header_val) {
- $html .= '<th>' . $header_val . '</th>';
- }
- $html .= '</tr>';
-
- $odd_row = true;
- foreach ($content_cells as $content_row) {
- $html .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">';
- $odd_row = ! $odd_row;
-
- if (is_array($content_row)) {
- foreach ($content_row as $content_row_val) {
- $html .= '<td class="center">' . $content_row_val . '</td>';
- }
- }
- $html .= '</tr>';
- }
- $html .= '</table>'
- . '<br />';
-
- return $html;
-}
-
-/**
- * Function to get html for the hidden fields containing index creation info
- *
- * @param string $index_type the index type
- *
- * @return string
- */
-function PMA_getHtmlForHiddenIndexInfo($index_type)
-{
- $html = '<input type="hidden" name="' . $index_type . '" value="';
- if (! empty($_REQUEST[$index_type])) {
- // happens when an index has been set on a column,
- // and a column is added to the table creation dialog
- //
- // this contains a JSON-encoded string
- $html .= htmlspecialchars($_REQUEST[$index_type]);
- } else {
- $html .= '[]';
- }
- $html .= '">';
-
- return $html;
-}
-
-/**
- * Function to get html for the create table or field add view
- *
- * @param string $action action
- * @param array $form_params forms parameters
- * @param array $content_cells content cells
- * @param array $header_cells header cells
- *
- * @return string
- */
-function PMA_getHtmlForTableCreateOrAddField($action, $form_params, $content_cells,
- $header_cells
-) {
- $html = '<form method="post" action="' . $action . '" class="'
- . ($action == 'tbl_create.php' ? 'create_table' : 'append_fields')
- . '_form ajax lock-page">';
- $html .= PMA_URL_getHiddenInputs($form_params);
-
- $html .= PMA_getHtmlForHiddenIndexInfo('primary_indexes');
- $html .= PMA_getHtmlForHiddenIndexInfo('unique_indexes');
- $html .= PMA_getHtmlForHiddenIndexInfo('indexes');
- $html .= PMA_getHtmlForHiddenIndexInfo('fulltext_indexes');
-
- if ($action == 'tbl_create.php') {
- $html .= PMA_getHtmlForTableNameAndNoOfColumns();
- }
-
- if (is_array($content_cells) && is_array($header_cells)) {
- $html .= PMA_getHtmlForTableFieldDefinitions($header_cells, $content_cells);
- }
-
- if ($action == 'tbl_create.php') {
- $html .= PMA_getHtmlForTableConfigurations();
- }
-
- $html .= PMA_getHtmlForFooter();
-
- return $html;
-}
-
-/**
- * Function to get header cells
- *
- * @param bool $is_backup whether backup or not
- * @param array|null $columnMeta column meta data
- * @param bool $mimework whether mimework or not
- * @param string $db current database
- * @param string $table current table
- *
- * @return array
- */
-function PMA_getHeaderCells($is_backup, $columnMeta, $mimework, $db, $table)
-{
- $header_cells = array();
- $header_cells[] = __('Name');
- $header_cells[] = __('Type')
- . PMA_Util::showMySQLDocu('data-types');
- $header_cells[] = __('Length/Values')
- . PMA_Util::showHint(
- __(
- 'If column type is "enum" or "set", please enter the values using'
- . ' this format: \'a\',\'b\',\'c\'…<br />If you ever need to put'
- . ' a backslash ("\") or a single quote ("\'") amongst those'
- . ' values, precede it with a backslash (for example \'\\\\xyz\''
- . ' or \'a\\\'b\').'
- )
- );
- $header_cells[] = __('Default')
- . PMA_Util::showHint(
- __(
- 'For default values, please enter just a single value,'
- . ' without backslash escaping or quotes, using this format: a'
- )
- );
- $header_cells[] = __('Collation');
- $header_cells[] = __('Attributes');
- $header_cells[] = __('Null');
-
- // We could remove this 'if' and let the key information be shown and
- // editable. However, for this to work, structure.lib.php must be modified
- // to use the key fields, as tbl_addfield does.
- if (! $is_backup) {
- $header_cells[] = __('Index');
- }
-
- $header_cells[] = '<abbr title="AUTO_INCREMENT">A_I</abbr>';
- $header_cells[] = __('Comments');
-
- if (isset($columnMeta)) {
- $header_cells[] = __('Move column');
- }
-
- if ($mimework && $GLOBALS['cfg']['BrowseMIME']) {
- $header_cells[] = __('MIME type');
- $header_link = '<a href="transformation_overview.php'
- . PMA_URL_getCommon()
- . '#%s" title="' . __(
- 'List of available transformations and their options'
- )
- . '" target="_blank">%s</a>';
- $transformations_hint = PMA_Util::showHint(
- __(
- 'Please enter the values for transformation options using this'
- . ' format: \'a\', 100, b,\'c\'…<br />If you ever need to put'
- . ' a backslash ("\") or a single quote ("\'") amongst those'
- . ' values, precede it with a backslash (for example \'\\\\xyz\''
- . ' or \'a\\\'b\').'
- )
- );
- $header_cells[] = sprintf(
- $header_link, 'transformation', __('Browser display transformation')
- );
- $header_cells[] = __('Browser display transformation options')
- . $transformations_hint;
- $header_cells[] = sprintf(
- $header_link, 'input_transformation', __('Input transformation')
- );
- $header_cells[] = __('Input transformation options')
- . $transformations_hint;
- }
-
- return $header_cells;
-}
-
-/**
- * Function for moving, load all available column names
- *
- * @param string $db current database
- * @param string $table current table
- *
- * @return array
- */
-function PMA_getMoveColumns($db, $table)
-{
- $move_columns_sql_query = 'SELECT * FROM '
- . PMA_Util::backquote($db)
- . '.'
- . PMA_Util::backquote($table)
- . ' LIMIT 1';
- $move_columns_sql_result = $GLOBALS['dbi']->tryQuery($move_columns_sql_query);
- $move_columns = $GLOBALS['dbi']->getFieldsMeta($move_columns_sql_result);
-
- return $move_columns;
-}
-
-/**
- * Function to get row data for regenerating previous when error occurred.
- *
- * @param int $columnNumber column number
- * @param array $submit_fulltext submit full text
- *
- * @return array
- */
-function PMA_getRowDataForRegeneration($columnNumber, $submit_fulltext)
-{
- $columnMeta = array();
- $columnMeta['Field'] = isset($_REQUEST['field_name'][$columnNumber])
- ? $_REQUEST['field_name'][$columnNumber]
- : false;
- $columnMeta['Type'] = isset($_REQUEST['field_type'][$columnNumber])
- ? $_REQUEST['field_type'][$columnNumber]
- : false;
- $columnMeta['Collation'] = isset($_REQUEST['field_collation'][$columnNumber])
- ? $_REQUEST['field_collation'][$columnNumber]
- : '';
- $columnMeta['Null'] = isset($_REQUEST['field_null'][$columnNumber])
- ? $_REQUEST['field_null'][$columnNumber]
- : '';
-
- $columnMeta['Key'] = '';
- if (isset($_REQUEST['field_key'][$columnNumber])) {
- $parts = explode('_', $_REQUEST['field_key'][$columnNumber], 2);
- if (count($parts) == 2 && $parts[1] == $columnNumber) {
- switch ($parts[0]) {
- case 'primary':
- $columnMeta['Key'] = 'PRI';
- break;
- case 'index':
- $columnMeta['Key'] = 'MUL';
- break;
- case 'unique':
- $columnMeta['Key'] = 'UNI';
- break;
- case 'fulltext':
- $columnMeta['Key'] = 'FULLTEXT';
- break;
- }
- }
- }
-
- // put None in the drop-down for Default, when someone adds a field
- $columnMeta['DefaultType']
- = isset($_REQUEST['field_default_type'][$columnNumber])
- ? $_REQUEST['field_default_type'][$columnNumber]
- : 'NONE';
- $columnMeta['DefaultValue']
- = isset($_REQUEST['field_default_value'][$columnNumber])
- ? $_REQUEST['field_default_value'][$columnNumber]
- : '';
-
- switch ($columnMeta['DefaultType']) {
- case 'NONE' :
- $columnMeta['Default'] = null;
- break;
- case 'USER_DEFINED' :
- $columnMeta['Default'] = $columnMeta['DefaultValue'];
- break;
- case 'NULL' :
- case 'CURRENT_TIMESTAMP' :
- $columnMeta['Default'] = $columnMeta['DefaultType'];
- break;
- }
-
- $columnMeta['Extra']
- = (isset($_REQUEST['field_extra'][$columnNumber])
- ? $_REQUEST['field_extra'][$columnNumber]
- : false);
- $columnMeta['Comment']
- = (isset($submit_fulltext[$columnNumber])
- && ($submit_fulltext[$columnNumber] == $columnNumber)
- ? 'FULLTEXT'
- : false);
-
- return $columnMeta;
-}
-
-/**
- * Function to get submit properties for regenerating previous when error occurred.
- *
- * @param int $columnNumber column number
- *
- * @return array
- */
-function PMA_getSubmitPropertiesForRegeneration($columnNumber)
-{
- $submit_length
- = (isset($_REQUEST['field_length'][$columnNumber])
- ? $_REQUEST['field_length'][$columnNumber]
- : false);
- $submit_attribute
- = (isset($_REQUEST['field_attribute'][$columnNumber])
- ? $_REQUEST['field_attribute'][$columnNumber]
- : false);
-
- $submit_default_current_timestamp
- = (isset($_REQUEST['field_default_current_timestamp'][$columnNumber])
- ? true
- : false);
-
- return array(
- $submit_length, $submit_attribute, $submit_default_current_timestamp
- );
-}
-
-/**
- * An error happened with previous inputs, so we will restore the data
- * to embed it once again in this form.
- *
- * @param int $columnNumber column number
- * @param array $submit_fulltext submit full text
- * @param array $comments_map comments map
- * @param array $mime_map mime map
- *
- * @return array
- */
-function PMA_handleRegeneration($columnNumber, $submit_fulltext, $comments_map,
- $mime_map
-) {
- $columnMeta = PMA_getRowDataForRegeneration(
- $columnNumber, isset($submit_fulltext) ? $submit_fulltext : null
- );
-
- list($submit_length, $submit_attribute, $submit_default_current_timestamp)
- = PMA_getSubmitPropertiesForRegeneration($columnNumber);
-
- if (isset($_REQUEST['field_comments'][$columnNumber])) {
- $comments_map[$columnMeta['Field']]
- = $_REQUEST['field_comments'][$columnNumber];
- }
-
- if (isset($_REQUEST['field_mimetype'][$columnNumber])) {
- $mime_map[$columnMeta['Field']]['mimetype']
- = $_REQUEST['field_mimetype'][$columnNumber];
- }
-
- if (isset($_REQUEST['field_transformation'][$columnNumber])) {
- $mime_map[$columnMeta['Field']]['transformation']
- = $_REQUEST['field_transformation'][$columnNumber];
- }
-
- if (isset($_REQUEST['field_transformation_options'][$columnNumber])) {
- $mime_map[$columnMeta['Field']]['transformation_options']
- = $_REQUEST['field_transformation_options'][$columnNumber];
- }
-
- return array(
- $columnMeta, $submit_length, $submit_attribute,
- $submit_default_current_timestamp, $comments_map, $mime_map
- );
-}
-
-/**
- * Function to update default value info in $columnMeta and get this array
- *
- * @param array $columnMeta column meta
- * @param bool $isDefault whether the row value is default
- *
- * @return array
- */
-function PMA_getColumnMetaForDefault($columnMeta, $isDefault)
-{
- switch ($columnMeta['Default']) {
- case null:
- if ($columnMeta['Null'] == 'YES') {
- $columnMeta['DefaultType'] = 'NULL';
- $columnMeta['DefaultValue'] = '';
- // SHOW FULL COLUMNS does not report the case
- // when there is a DEFAULT value which is empty so we need to use the
- // results of SHOW CREATE TABLE
- } elseif ($isDefault) {
- $columnMeta['DefaultType'] = 'USER_DEFINED';
- $columnMeta['DefaultValue'] = $columnMeta['Default'];
- } else {
- $columnMeta['DefaultType'] = 'NONE';
- $columnMeta['DefaultValue'] = '';
- }
- break;
- case 'CURRENT_TIMESTAMP':
- $columnMeta['DefaultType'] = 'CURRENT_TIMESTAMP';
- $columnMeta['DefaultValue'] = '';
- break;
- default:
- $columnMeta['DefaultType'] = 'USER_DEFINED';
- $columnMeta['DefaultValue'] = $columnMeta['Default'];
- break;
- }
-
- return $columnMeta;
-}
-
-/**
- * Function to get html for the column name
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array|null $columnMeta column meta
- * @param array $cfgRelation configuration relation
- *
- * @return string
- */
-function PMA_getHtmlForColumnName(
- $columnNumber, $ci, $ci_offset, $columnMeta, $cfgRelation
-) {
- $title = '';
- if (isset($columnMeta['column_status'])) {
- if ($columnMeta['column_status']['isReferenced']) {
- $title .= sprintf(
- __('Referenced by %s.'),
- implode(",", $columnMeta['column_status']['references'])
- );
- }
- if ($columnMeta['column_status']['isForeignKey']) {
- if (!empty($title)) {
- $title .= "\n";
- }
- $title .= __('Is a foreign key.');
- }
- }
- if (empty($title)) {
- $title = __('Column');
- }
- $html = '<input' . (isset($columnMeta['column_status'])
- && !$columnMeta['column_status']['isEditable']?' disabled="disabled" ':' ')
- . 'id="field_' . $columnNumber . '_' . ($ci - $ci_offset)
- . '"' . ' type="text" name="field_name[' . $columnNumber . ']"'
- . ' maxlength="64" class="textfield" title="' . $title . '"'
- . ' size="10"'
- . ' value="'
- . (isset($columnMeta['Field'])
- ? htmlspecialchars($columnMeta['Field']) : '')
- . '"' . ' />';
- if (isset($cfgRelation['central_columnswork'])
- && $cfgRelation['central_columnswork']
- && !(isset($columnMeta['column_status'])
- && !$columnMeta['column_status']['isEditable'])
- ) {
- $html .= '<p style="font-size:80%;margin:5px 2px" '
- . 'id="central_columns_' . $columnNumber . '_'
- . ($ci - $ci_offset)
- . '">';
- $html .= '<a data-maxrows="' . $GLOBALS['cfg']['MaxRows'] . '" '
- . 'href="#" class="central_columns_dialog"> '
- . __('Pick from Central Columns') . '</a>'
- . '</p>';
- }
- return $html;
-}
-
-/**
- * Function to get html for the column type
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param string $type_upper type inuppercase
- * @param array $columnMeta meta data
- *
- * @return string
- */
-function PMA_getHtmlForColumnType($columnNumber, $ci, $ci_offset,
- $type_upper, $columnMeta
-) {
- $select_id = 'field_' . $columnNumber . '_' . ($ci - $ci_offset);
- $html = '<select' . (isset($columnMeta['column_status'])
- && !$columnMeta['column_status']['isEditable']?' disabled="disabled" ':' ')
- . 'class="column_type" name="field_type['
- . $columnNumber . ']"' . ' id="' . $select_id . '">';
- $html .= PMA_Util::getSupportedDatatypes(true, $type_upper);
- $html .= ' </select>';
-
- return $html;
-}
-
-/**
- * Function to get html for transformation option
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array|null $columnMeta column meta
- * @param array $mime_map mime map
- * @param string $type_prefix prefix for type of transformation
- * '' or 'input'
- *
- * @return string
- */
-function PMA_getHtmlForTransformationOption($columnNumber, $ci, $ci_offset,
- $columnMeta, $mime_map, $type_prefix
-) {
- $options_key = $type_prefix . 'transformation_options';
- $val = isset($columnMeta['Field'])
- && isset($mime_map[$columnMeta['Field']][$options_key])
- ? htmlspecialchars(
- $mime_map[$columnMeta['Field']]
- [$options_key]
- )
- : '';
-
- $html = '<input id="field_' . $columnNumber . '_'
- . ($ci - $ci_offset) . '"' . ' type="text" '
- . 'name="field_' . $options_key . '[' . $columnNumber . ']"'
- . ' size="16" class="textfield"'
- . ' value="' . $val . '"'
- . ' />';
-
- return $html;
-}
-
-/**
- * Function to get html for mime type
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $available_mime available mime
- * @param array $columnMeta column meta
- * @param array $mime_map mime map
- *
- * @return string
- */
-function PMA_getHtmlForMimeType($columnNumber, $ci, $ci_offset,
- $available_mime, $columnMeta, $mime_map
-) {
- $html = '<select id="field_' . $columnNumber . '_'
- . ($ci - $ci_offset)
- . '" size="1" name="field_mimetype[' . $columnNumber . ']">';
- $html .= ' <option value="">&nbsp;</option>';
-
- if (isset($available_mime['mimetype'])
- && is_array($available_mime['mimetype'])
- ) {
- foreach ($available_mime['mimetype'] as $mimetype) {
- $checked = (isset($columnMeta['Field'])
- && isset($mime_map[$columnMeta['Field']]['mimetype'])
- && ($mime_map[$columnMeta['Field']]['mimetype']
- == str_replace('/', '_', $mimetype))
- ? 'selected '
- : '');
- $html .= ' <option value="'
- . str_replace('/', '_', $mimetype) . '" ' . $checked . '>'
- . htmlspecialchars($mimetype) . '</option>';
- }
- }
-
- $html .= '</select>';
-
- return $html;
-}
-
-/**
- * Function to get html for transformations
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $available_mime available mime
- * @param array|null $columnMeta column meta
- * @param array $mime_map mime map
- * @param string $type_prefix prefix for type of transformation
- * '' or 'input'
- *
- * @return string
- */
-function PMA_getHtmlForTransformation($columnNumber, $ci, $ci_offset,
- $available_mime, $columnMeta, $mime_map, $type_prefix
-) {
- $type = $type_prefix . 'transformation';
- $html = '<select id="field_' . $columnNumber . '_'
- . ($ci - $ci_offset) . '" size="1" name="field_' . $type
- . '[' . $columnNumber . ']">';
- $html .= ' <option value="" title="' . __('None')
- . '"></option>';
- if (isset($available_mime[$type]) && is_array($available_mime[$type])) {
- foreach ($available_mime[$type] as $mimekey => $transform) {
- $checked = isset($columnMeta['Field'])
- && isset($mime_map[$columnMeta['Field']][$type])
- && preg_match(
- '@' . preg_quote(
- $available_mime[$type . '_file'][$mimekey]
- ) . '3?@i',
- $mime_map[$columnMeta['Field']][$type]
- )
- ? 'selected '
- : '';
- $tooltip = PMA_getTransformationDescription(
- $available_mime[$type . '_file'][$mimekey], false
- );
- $html .= '<option value="'
- . $available_mime[$type . '_file'][$mimekey] . '" '
- . $checked . ' title="' . htmlspecialchars($tooltip) . '">'
- . htmlspecialchars($transform) . '</option>';
- }
- }
-
- $html .= '</select>';
-
- return $html;
-}
-
-/**
- * Function to get html for move column
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $move_columns move columns
- * @param array $columnMeta column meta
- *
- * @return string
- */
-function PMA_getHtmlForMoveColumn($columnNumber, $ci, $ci_offset, $move_columns,
- $columnMeta
-) {
- $html = '<select id="field_' . $columnNumber . '_'
- . ($ci - $ci_offset) . '"' . ' name="field_move_to[' . $columnNumber
- . ']" size="1" width="5em">'
- . '<option value="" selected="selected">&nbsp;</option>';
- // find index of current column
- $current_index = 0;
- for ($mi = 0, $cols = count($move_columns); $mi < $cols; $mi++) {
- if ($move_columns[$mi]->name == $columnMeta['Field']) {
- $current_index = $mi;
- break;
- }
- }
-
- $html .= '<option value="-first"'
- . ($current_index == 0 ? ' disabled="disabled"' : '')
- . '>' . __('first') . '</option>';
- for ($mi = 0, $cols = count($move_columns); $mi < $cols; $mi++) {
- $html .=
- '<option value="' . htmlspecialchars($move_columns[$mi]->name) . '"'
- . (($current_index == $mi || $current_index == $mi + 1)
- ? ' disabled="disabled"'
- : '')
- . '>'
- . sprintf(
- __('after %s'),
- PMA_Util::backquote(
- htmlspecialchars(
- $move_columns[$mi]->name
- )
- )
- )
- . '</option>';
- }
-
- $html .= '</select>';
-
- return $html;
-}
-
-/**
- * Function to get html for column comment
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $columnMeta column meta
- * @param array $comments_map comments map
- *
- * @return string
- */
-function PMA_getHtmlForColumnComment($columnNumber, $ci, $ci_offset, $columnMeta,
- $comments_map
-) {
- $html = '<input id="field_' . $columnNumber . '_' . ($ci - $ci_offset)
- . '"' . ' type="text" name="field_comments[' . $columnNumber
- . ']" size="12"'
- . ' value="' . (isset($columnMeta['Field'])
- && is_array($comments_map)
- && isset($comments_map[$columnMeta['Field']])
- ? htmlspecialchars($comments_map[$columnMeta['Field']])
- : '') . '"'
- . ' class="textfield" />';
-
- return $html;
-}
-
-/**
- * Function get html for column auto increment
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $columnMeta column meta
- *
- * @return string
- */
-function PMA_getHtmlForColumnAutoIncrement($columnNumber, $ci, $ci_offset,
- $columnMeta
-) {
- $html = '<input name="field_extra[' . $columnNumber . ']"'
- . ' id="field_' . $columnNumber . '_' . ($ci - $ci_offset) . '"';
- if (isset($columnMeta['Extra'])
- && /*overload*/mb_strtolower($columnMeta['Extra']) == 'auto_increment'
- ) {
- $html .= ' checked="checked"';
- }
-
- $html .= ' type="checkbox" value="AUTO_INCREMENT" />';
-
- return $html;
-}
-
-/**
- * Function to get html for the column indexes
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $columnMeta column meta
- *
- * @return string
- */
-function PMA_getHtmlForColumnIndexes($columnNumber, $ci, $ci_offset, $columnMeta)
-{
- $html = '<select name="field_key[' . $columnNumber . ']"'
- . ' id="field_' . $columnNumber . '_' . ($ci - $ci_offset)
- . '" data-index="">';
- $html .= '<option value="none_' . $columnNumber . '">---</option>';
-
- $html .= PMA_getHtmlForIndexTypeOption(
- $columnNumber, $columnMeta, 'Primary', 'PRI'
- );
- $html .= PMA_getHtmlForIndexTypeOption(
- $columnNumber, $columnMeta, 'Unique', 'UNI'
- );
- $html .= PMA_getHtmlForIndexTypeOption(
- $columnNumber, $columnMeta, 'Index', 'MUL'
- );
- if (!PMA_DRIZZLE) {
- $html .= PMA_getHtmlForIndexTypeOption(
- $columnNumber, $columnMeta, 'Fulltext', 'FULLTEXT'
- );
- }
-
- $html .= '</select>';
-
- return $html;
-}
-
-/**
- * Function to get html for the index options
- *
- * @param int $columnNumber column number
- * @param array $columnMeta column meta
- * @param string $type index type
- * @param string $key column meta key
- *
- * @return string
- */
-
-function PMA_getHtmlForIndexTypeOption($columnNumber, $columnMeta, $type, $key)
-{
- $typeToLower = /*overload*/mb_strtolower($type);
- $typeToUpper = /*overload*/mb_strtoupper($type);
- $html = '<option value="' . $typeToLower . '_' . $columnNumber
- . '" title="' . __($type) . '"';
- if (isset($columnMeta['Key']) && $columnMeta['Key'] == $key) {
- $html .= ' selected="selected"';
- }
- $html .= '>' . $typeToUpper . '</option>';
-
- return $html;
-}
-
-
-/**
- * Function to get html for column null
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $columnMeta column meta
- *
- * @return string
- */
-function PMA_getHtmlForColumnNull($columnNumber, $ci, $ci_offset, $columnMeta)
-{
- $html = '<input name="field_null[' . $columnNumber . ']"'
- . ' id="field_' . $columnNumber . '_' . ($ci - $ci_offset) . '"';
- if (! empty($columnMeta['Null'])
- && $columnMeta['Null'] != 'NO'
- && $columnMeta['Null'] != 'NOT NULL'
- ) {
- $html .= ' checked="checked"';
- }
-
- $html .= ' type="checkbox" value="NULL" class="allow_null"/>';
-
- return $html;
-}
-
-/**
- * Function to get html for column attribute
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $extracted_columnspec extracted column
- * @param array $columnMeta column meta
- * @param bool $submit_attribute submit attribute
- * @param array $analyzed_sql analyzed sql
- *
- * @return string
- */
-function PMA_getHtmlForColumnAttribute($columnNumber, $ci, $ci_offset,
- $extracted_columnspec, $columnMeta, $submit_attribute, $analyzed_sql
-) {
- $html = '<select style="width: 7em;"'
- . ' name="field_attribute[' . $columnNumber . ']"'
- . ' id="field_' . $columnNumber . '_' . ($ci - $ci_offset) . '">';
-
- $attribute = '';
- if (isset($extracted_columnspec['attribute'])) {
- $attribute = $extracted_columnspec['attribute'];
- }
-
- if (isset($columnMeta['Extra'])
- && $columnMeta['Extra'] == 'on update CURRENT_TIMESTAMP'
- ) {
- $attribute = 'on update CURRENT_TIMESTAMP';
- }
-
- if (isset($submit_attribute) && $submit_attribute != false) {
- $attribute = $submit_attribute;
- }
-
- // here, we have a TIMESTAMP that SHOW FULL COLUMNS reports as having the
- // NULL attribute, but SHOW CREATE TABLE says the contrary. Believe
- // the latter.
- $create_table_fields = $analyzed_sql[0]['create_table_fields'];
-
- // MySQL 4.1.2+ TIMESTAMP options
- // (if on_update_current_timestamp is set, then it's TRUE)
- if (isset($columnMeta['Field'])) {
- $field = $create_table_fields[$columnMeta['Field']];
- }
-
- if (isset($field)
- && isset($field['on_update_current_timestamp'])
- ) {
- $attribute = 'on update CURRENT_TIMESTAMP';
- }
-
- $attribute_types = $GLOBALS['PMA_Types']->getAttributes();
- $cnt_attribute_types = count($attribute_types);
- for ($j = 0; $j < $cnt_attribute_types; $j++) {
- $html .= ' <option value="' . $attribute_types[$j] . '"';
- $attrUpper = /*overload*/mb_strtoupper($attribute);
- if ($attrUpper == /*overload*/mb_strtoupper($attribute_types[$j])) {
- $html .= ' selected="selected"';
- }
- $html .= '>' . $attribute_types[$j] . '</option>';
- }
-
- $html .= '</select>';
-
- return $html;
-}
-
-/**
- * Function to get html for column collation
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param array $columnMeta column meta
- *
- * @return string
- */
-function PMA_getHtmlForColumnCollation($columnNumber, $ci, $ci_offset, $columnMeta)
-{
- $tmp_collation
- = empty($columnMeta['Collation']) ? null : $columnMeta['Collation'];
- $html = PMA_generateCharsetDropdownBox(
- PMA_CSDROPDOWN_COLLATION, 'field_collation[' . $columnNumber . ']',
- 'field_' . $columnNumber . '_' . ($ci - $ci_offset), $tmp_collation, false
- );
-
- return $html;
-}
-
-/**
- * Function get html for column length
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param int $length_values_input_size length values input size
- * @param int $length_to_display length to display
- *
- * @return string
- */
-function PMA_getHtmlForColumnLength($columnNumber, $ci, $ci_offset,
- $length_values_input_size, $length_to_display
-) {
- $html = '<input id="field_' . $columnNumber . '_' . ($ci - $ci_offset)
- . '"' . ' type="text" name="field_length[' . $columnNumber . ']" size="'
- . $length_values_input_size . '"' . ' value="' . htmlspecialchars(
- $length_to_display
- )
- . '"'
- . ' class="textfield" />'
- . '<p class="enum_notice" id="enum_notice_' . $columnNumber . '_'
- . ($ci - $ci_offset)
- . '">';
- $html .= '<a href="#" class="open_enum_editor"> '
- . __('Edit ENUM/SET values') . '</a>'
- . '</p>';
-
- return $html;
-}
-
-/**
- * Function to get html for the default column
- *
- * @param int $columnNumber column number
- * @param int $ci cell index
- * @param int $ci_offset cell index offset
- * @param string $type_upper type upper
- * @param string $default_current_timestamp default current timestamp
- * @param array $columnMeta column meta
- *
- * @return string
- */
-function PMA_getHtmlForColumnDefault($columnNumber, $ci, $ci_offset, $type_upper,
- $default_current_timestamp, $columnMeta
-) {
- // here we put 'NONE' as the default value of drop-down; otherwise
- // users would have problems if they forget to enter the default
- // value (example, for an INT)
- $default_options = array(
- 'NONE' => _pgettext('for default', 'None'),
- 'USER_DEFINED' => __('As defined:'),
- 'NULL' => 'NULL',
- 'CURRENT_TIMESTAMP' => 'CURRENT_TIMESTAMP',
- );
-
- // for a TIMESTAMP, do not show the string "CURRENT_TIMESTAMP" as a default
- // value
- if ($type_upper == 'TIMESTAMP'
- && ! empty($default_current_timestamp)
- && isset($columnMeta['Default'])
- ) {
- $columnMeta['Default'] = '';
- } elseif ($type_upper == 'BIT') {
- $columnMeta['DefaultValue']
- = PMA_Util::convertBitDefaultValue($columnMeta['DefaultValue']);
- } elseif ($type_upper == 'BINARY' || $type_upper == 'VARBINARY') {
- $columnMeta['DefaultValue'] = bin2hex($columnMeta['DefaultValue']);
- }
-
- $html = '<select name="field_default_type[' . $columnNumber
- . ']" id="field_' . $columnNumber . '_' . ($ci - $ci_offset)
- . '" class="default_type">';
- foreach ($default_options as $key => $value) {
- $html .= '<option value="' . $key . '"';
- // is only set when we go back to edit a field's structure
- if (isset($columnMeta['DefaultType'])
- && $columnMeta['DefaultType'] == $key
- ) {
- $html .= ' selected="selected"';
- }
- $html .= ' >' . $value . '</option>';
- }
- $html .= '</select>';
- $html .= '<br />';
-
- $value = isset($columnMeta['DefaultValue'])
- ? htmlspecialchars($columnMeta['DefaultValue'])
- : '';
- if ($GLOBALS['cfg']['CharEditing'] == 'textarea') {
- $html .= '<textarea'
- . ' name="field_default_value[' . $columnNumber . ']" cols="15"'
- . ' class="textfield default_value">'
- . $value
- . '</textarea>';
- } else {
- $html .= '<input type="text"'
- . ' name="field_default_value[' . $columnNumber . ']" size="12"'
- . ' value="' . $value . '"'
- . ' class="textfield default_value" />';
- }
-
- return $html;
-}
-
-/**
- * Function to get html for column attributes
- *
- * @param int $columnNumber column number
- * @param array $columnMeta column meta
- * @param string $type_upper type upper
- * @param int $length_values_input_size length values input size
- * @param int $length length
- * @param string $default_current_timestamp default current time stamp
- * @param array|null $extracted_columnspec extracted column spec
- * @param string $submit_attribute submit attribute
- * @param array|null $analyzed_sql analyzed sql
- * @param array $comments_map comments map
- * @param array|null $fields_meta fields map
- * @param bool $is_backup is backup
- * @param array $move_columns move columns
- * @param array $cfgRelation configuration relation
- * @param array $available_mime available mime
- * @param array $mime_map mime map
- *
- * @return array
- */
-function PMA_getHtmlForColumnAttributes($columnNumber, $columnMeta, $type_upper,
- $length_values_input_size, $length, $default_current_timestamp,
- $extracted_columnspec, $submit_attribute, $analyzed_sql,
- $comments_map, $fields_meta, $is_backup,
- $move_columns, $cfgRelation, $available_mime, $mime_map
-) {
- // Cell index: If certain fields get left out, the counter shouldn't change.
- $ci = 0;
- // Every time a cell shall be left out the STRG-jumping feature, $ci_offset
- // has to be incremented ($ci_offset++)
- $ci_offset = -1;
-
- $content_cell = array();
-
- // column name
- $content_cell[$ci] = PMA_getHtmlForColumnName(
- $columnNumber, $ci, $ci_offset, isset($columnMeta) ? $columnMeta : null,
- $cfgRelation
- );
- $ci++;
-
- // column type
- $content_cell[$ci] = PMA_getHtmlForColumnType(
- $columnNumber, $ci, $ci_offset, $type_upper,
- isset($columnMeta) ? $columnMeta : null
- );
- $ci++;
-
- // column length
- $content_cell[$ci] = PMA_getHtmlForColumnLength(
- $columnNumber, $ci, $ci_offset, $length_values_input_size, $length
- );
- $ci++;
-
- // column default
- $content_cell[$ci] = PMA_getHtmlForColumnDefault(
- $columnNumber, $ci, $ci_offset,
- isset($type_upper) ? $type_upper : null,
- isset($default_current_timestamp) ? $default_current_timestamp : null,
- isset($columnMeta) ? $columnMeta : null
- );
- $ci++;
-
- // column collation
- $content_cell[$ci] = PMA_getHtmlForColumnCollation(
- $columnNumber, $ci, $ci_offset, $columnMeta
- );
- $ci++;
-
- // column attribute
- $content_cell[$ci] = PMA_getHtmlForColumnAttribute(
- $columnNumber, $ci, $ci_offset,
- isset($extracted_columnspec) ? $extracted_columnspec : null,
- isset($columnMeta) ? $columnMeta : null,
- isset($submit_attribute) ? $submit_attribute : null,
- isset($analyzed_sql) ? $analyzed_sql : null
- );
- $ci++;
-
- // column NULL
- $content_cell[$ci] = PMA_getHtmlForColumnNull(
- $columnNumber, $ci, $ci_offset, isset($columnMeta) ? $columnMeta : null
- );
- $ci++;
-
- // column indexes
- // See my other comment about this 'if'.
- if (!$is_backup) {
- $content_cell[$ci] = PMA_getHtmlForColumnIndexes(
- $columnNumber, $ci, $ci_offset, $columnMeta
- );
- $ci++;
- } // end if ($action ==...)
-
- // column auto_increment
- $content_cell[$ci] = PMA_getHtmlForColumnAutoIncrement(
- $columnNumber, $ci, $ci_offset, $columnMeta
- );
- $ci++;
-
- // column comments
- $content_cell[$ci] = PMA_getHtmlForColumnComment(
- $columnNumber, $ci, $ci_offset, isset($columnMeta) ? $columnMeta : null,
- $comments_map
- );
- $ci++;
-
- // move column
- if (isset($fields_meta)) {
- $content_cell[$ci] = PMA_getHtmlForMoveColumn(
- $columnNumber, $ci, $ci_offset, $move_columns, $columnMeta
- );
- $ci++;
- }
-
- if ($cfgRelation['mimework']
- && $GLOBALS['cfg']['BrowseMIME']
- && $cfgRelation['commwork']
- ) {
- // Column Mime-type
- $content_cell[$ci] = PMA_getHtmlForMimeType(
- $columnNumber, $ci, $ci_offset, $available_mime, $columnMeta, $mime_map
- );
- $ci++;
-
- // Column Browser transformation
- $content_cell[$ci] = PMA_getHtmlForTransformation(
- $columnNumber, $ci, $ci_offset, $available_mime,
- $columnMeta, $mime_map, ''
- );
- $ci++;
-
- // column Transformation options
- $content_cell[$ci] = PMA_getHtmlForTransformationOption(
- $columnNumber, $ci, $ci_offset, $columnMeta, $mime_map, ''
- );
- $ci++;
-
- // Column Input transformation
- $content_cell[$ci] = PMA_getHtmlForTransformation(
- $columnNumber, $ci, $ci_offset, $available_mime,
- $columnMeta, $mime_map, 'input_'
- );
- $ci++;
-
- // column Input transformation options
- $content_cell[$ci] = PMA_getHtmlForTransformationOption(
- $columnNumber, $ci, $ci_offset, $columnMeta, $mime_map, 'input_'
- );
- }
-
- return $content_cell;
-}
-
-/**
- * Function to get form parameters for old column
- *
- * @param array $columnMeta column meta
- * @param int $length length
- * @param array $form_params form parameters
- * @param int $columnNumber column/field number
- * @param string $type type in lowercase without the length
- * @param array $extracted_columnspec details about the column spec
- *
- * @return array
- */
-function PMA_getFormParamsForOldColumn(
- $columnMeta, $length, $form_params, $columnNumber, $type,
- $extracted_columnspec
-) {
- // old column name
- if (isset($columnMeta['Field'])) {
- $form_params['field_orig[' . $columnNumber . ']']
- = $columnMeta['Field'];
- if (isset($columnMeta['column_status'])
- && !$columnMeta['column_status']['isEditable']
- ) {
- $form_params['field_name[' . $columnNumber . ']']
- = $columnMeta['Field'];
- }
- } else {
- $form_params['field_orig[' . $columnNumber . ']'] = '';
- }
-
- // old column type
- if (isset($columnMeta['Type'])) {
- // keep in uppercase because the new type will be in uppercase
- $form_params['field_type_orig[' . $columnNumber . ']']
- = /*overload*/mb_strtoupper($type);
- if (isset($columnMeta['column_status'])
- && !$columnMeta['column_status']['isEditable']
- ) {
- $form_params['field_type[' . $columnNumber . ']']
- = /*overload*/mb_strtoupper($type);
- }
- } else {
- $form_params['field_type_orig[' . $columnNumber . ']'] = '';
- }
-
- // old column length
- $form_params['field_length_orig[' . $columnNumber . ']'] = $length;
-
- // old column default
- $form_params['field_default_value_orig[' . $columnNumber . ']']
- = (isset($columnMeta['Default']) ? $columnMeta['Default'] : '');
- $form_params['field_default_type_orig[' . $columnNumber . ']']
- = (isset($columnMeta['DefaultType']) ? $columnMeta['DefaultType'] : '');
-
- // old column collation
- if (isset($columnMeta['Collation'])) {
- $form_params['field_collation_orig[' . $columnNumber . ']']
- = $columnMeta['Collation'];
- } else {
- $form_params['field_collation_orig[' . $columnNumber . ']'] = '';
- }
-
- // old column attribute
- if (isset($extracted_columnspec['attribute'])) {
- $form_params['field_attribute_orig[' . $columnNumber . ']']
- = trim($extracted_columnspec['attribute']);
- } else {
- $form_params['field_attribute_orig[' . $columnNumber . ']'] = '';
- }
-
- // old column null
- if (isset($columnMeta['Null'])) {
- $form_params['field_null_orig[' . $columnNumber . ']']
- = $columnMeta['Null'];
- } else {
- $form_params['field_null_orig[' . $columnNumber . ']'] = '';
- }
-
- // old column extra (for auto_increment)
- if (isset($columnMeta['Extra'])) {
- $form_params['field_extra_orig[' . $columnNumber . ']']
- = $columnMeta['Extra'];
- } else {
- $form_params['field_extra_orig[' . $columnNumber . ']'] = '';
- }
-
- // old column comment
- if (isset($columnMeta['Comment'])) {
- $form_params['field_comments_orig[' . $columnNumber . ']']
- = $columnMeta['Comment'];
- } else {
- $form_params['field_comment_orig[' . $columnNumber . ']'] = '';
- }
-
- return $form_params;
-}
-?>
diff --git a/libraries/tbl_common.inc.php b/libraries/tbl_common.inc.php
index a2e7b260b2..4eec0c2c2a 100644
--- a/libraries/tbl_common.inc.php
+++ b/libraries/tbl_common.inc.php
@@ -35,9 +35,15 @@ $url_params['table'] = $table;
/**
* Defines the urls to return to in case of error in a sql statement
*/
-$err_url_0 = $cfg['DefaultTabDatabase']
+$err_url_0 = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+)
. PMA_URL_getCommon(array('db' => $db));
-$err_url = $cfg['DefaultTabTable'] . PMA_URL_getCommon($url_params);
+
+$err_url = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+)
+ . PMA_URL_getCommon($url_params);
/**
@@ -45,4 +51,3 @@ $err_url = $cfg['DefaultTabTable'] . PMA_URL_getCommon($url_params);
*/
require_once './libraries/db_table_exists.lib.php';
-?>
diff --git a/libraries/tbl_gis_visualization.lib.php b/libraries/tbl_gis_visualization.lib.php
deleted file mode 100644
index 4e1c9c96bc..0000000000
--- a/libraries/tbl_gis_visualization.lib.php
+++ /dev/null
@@ -1,281 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Functions used to generate GIS visualizations.
- *
- * @package PhpMyAdmin
- */
-if (!defined('PHPMYADMIN')) {
- exit;
-}
-
-require_once 'libraries/sql.lib.php';
-
-/**
- * Returns a modified sql query with only the label column
- * and spatial column(wrapped with 'ASTEXT()' function).
- *
- * @param string $sql_query original sql query
- * @param array $visualizationSettings settings for the visualization
- *
- * @return string the modified sql query.
- */
-function PMA_GIS_modifyQuery($sql_query, $visualizationSettings)
-{
- $modified_query = 'SELECT ';
- // If label column is chosen add it to the query
- if (! empty($visualizationSettings['labelColumn'])) {
- $modified_query .= PMA_Util::backquote($visualizationSettings['labelColumn'])
- . ', ';
- }
- // Wrap the spatial column with 'ASTEXT()' function and add it
- $modified_query .= 'ASTEXT('
- . PMA_Util::backquote($visualizationSettings['spatialColumn'])
- . ') AS ' . PMA_Util::backquote($visualizationSettings['spatialColumn'])
- . ', ';
-
- // Get the SRID
- $modified_query .= 'SRID('
- . PMA_Util::backquote($visualizationSettings['spatialColumn'])
- . ') AS ' . PMA_Util::backquote('srid') . ' ';
-
- // Append the original query as the inner query
- $modified_query .= 'FROM (' . $sql_query . ') AS '
- . PMA_Util::backquote('temp_gis');
-
- return $modified_query;
-}
-
-/**
- * Formats a visualization for the GIS query results.
- *
- * @param array $data Data for the status chart
- * @param array &$visualizationSettings Settings used to generate the chart
- * @param string $format Format of the visualization
- *
- * @return string|bool HTML and JS code for the GIS visualization or false on failure
- */
-function PMA_GIS_visualizationResults($data, &$visualizationSettings, $format)
-{
- include_once './libraries/gis/GIS_Visualization.class.php';
- include_once './libraries/gis/GIS_Factory.class.php';
-
- if (! isset($data[0])) {
- // empty data
- return __('No data found for GIS visualization.');
- }
-
- $visualization = new PMA_GIS_Visualization($data, $visualizationSettings);
- if ($visualizationSettings != null) {
- foreach ($visualization->getSettings() as $setting => $val) {
- if (! isset($visualizationSettings[$setting])) {
- $visualizationSettings[$setting] = $val;
- }
- }
- }
-
- if ($format == 'svg') {
- return $visualization->asSvg();
- } elseif ($format == 'png') {
- return $visualization->asPng();
- } elseif ($format == 'ol') {
- return $visualization->asOl();
- }
-
- return false;
-}
-
-/**
- * Generate visualization for the GIS query results and save it to a file.
- *
- * @param array $data data for the status chart
- * @param array $visualizationSettings settings used to generate the chart
- * @param string $format format of the visualization
- * @param string $fileName file name
- *
- * @return file File containing the visualization
- */
-function PMA_GIS_saveToFile($data, $visualizationSettings, $format, $fileName)
-{
- include_once './libraries/gis/GIS_Visualization.class.php';
- include_once './libraries/gis/GIS_Factory.class.php';
-
- if (isset($data[0])) {
- $visualization = new PMA_GIS_Visualization($data, $visualizationSettings);
-
- if ($format == 'svg') {
- $visualization->toFileAsSvg($fileName);
- } elseif ($format == 'png') {
- $visualization->toFileAsPng($fileName);
- } elseif ($format == 'pdf') {
- $visualization->toFileAsPdf($fileName);
- }
- }
-}
-
-/**
- * Function to get html for the label column and spatial column
- *
- * @param string $column the column type. i.e either "labelColumn"
- * or "spatialColumn"
- * @param array $columnCandidates the list of select options
- * @param array $visualizationSettings visualization settings
- *
- * @return string $html
- */
-function PMA_getHtmlForSelect($column, $columnCandidates, $visualizationSettings)
-{
- $html = '<label for="' . $column . '">';
- $html .= ($column=="labelColumn") ? __("Label column") : __("Spatial column");
- $html .= '</label>';
-
- $html .= '<select name="visualizationSettings[' . $column . ']" id="'
- . $column . '" class="autosubmit">';
-
- if ($column == "labelColumn") {
- $html .= '<option value="">' . __("-- None --") . '</option>';
- }
-
- $html .= PMA_getHtmlForOptionsList(
- $columnCandidates, array($visualizationSettings[$column])
- );
-
- $html .= '</select>';
-
- return $html;
-}
-
-/**
- * Function to get HTML for the option of using open street maps
- *
- * @param boolean $isSelected the default value
- *
- * @return string HTML string
- */
-function PMA_getHtmlForUseOpenStreetMaps($isSelected)
-{
- $html = '<tr><td class="choice" colspan="2">';
- $html .= '<input type="checkbox" name="visualizationSettings[choice]"'
- . 'id="choice" value="useBaseLayer"';
- if ($isSelected) {
- $html .= ' checked="checked"';
- }
- $html .= '/>';
- $html .= '<label for="choice">';
- $html .= __("Use OpenStreetMaps as Base Layer");
- $html .= '</label>';
- $html .= '</td></tr>';
-
- return $html;
-}
-
-/**
- * Get the link for downloading GIS visualization in a particular format.
- *
- * @param string $url base url
- * @param string $name format name
- * @param string $label format label
- *
- * @return string HTML for download link
- */
-function PMA_getHtmlForGisDownloadLink($url, $name, $label)
-{
- $html = '<li class="warp_link">';
- $html .= '<a href="' . $url . '&fileFormat=' . $name . '"'
- . ' class="disableAjax">' . $label . '</a>';
- $html .= '</li>';
-
- return $html;
-}
-
-/**
- * Function to generate HTML for the GIS visualization page
- *
- * @param array $url_params url parameters
- * @param array $labelCandidates list of candidates for the label
- * @param array $spatialCandidates list of candidates for the spatial column
- * @param array $visualizationSettings visualization settings
- * @param String $sql_query the sql query
- * @param String $visualization HTML and js code for the visualization
- * @param boolean $svg_support whether svg download format is supported
- * @param array $data array of visualizing data
- *
- * @return string HTML code for the GIS visualization
- */
-function PMA_getHtmlForGisVisualization(
- $url_params, $labelCandidates, $spatialCandidates, $visualizationSettings,
- $sql_query, $visualization, $svg_support, $data
-) {
- $html = '<div id="div_view_options">';
- $html .= '<fieldset>';
- $html .= '<legend>' . __('Display GIS Visualization') . '</legend>';
-
- $html .= '<div id="gis_div" style="position:relative;">';
- $html .= '<form method="post" action="tbl_gis_visualization.php">';
- $html .= PMA_URL_getHiddenInputs($url_params);
-
- $html .= PMA_getHtmlForSelect(
- "labelColumn", $labelCandidates, $visualizationSettings
- );
- $html .= PMA_getHtmlForSelect(
- "spatialColumn", $spatialCandidates, $visualizationSettings
- );
-
- $html .= '<input type="hidden" name="displayVisualization" value="redraw">';
- $html .= '<input type="hidden" name="sql_query" value="';
- $html .= htmlspecialchars($sql_query) . '" />';
- $html .= '</form>';
-
- if (! $GLOBALS['PMA_Config']->isHttps()) {
- $isSelected = isset($visualizationSettings['choice']) ? true : false;
- $html .= PMA_getHtmlForUseOpenStreetMaps($isSelected);
- }
-
- $html .= '<div class="pma_quick_warp" style="width: 50px; position: absolute;'
- . ' right: 0; top: 0; cursor: pointer;">';
- $html .= '<div class="drop_list">';
- $html .= '<span class="drop_button" style="padding: 0; border: 0;">';
- $html .= PMA_Util::getImage('b_saveimage', __('Save'));
- $html .= '</span>';
-
- $url_params['sql_query'] = $sql_query;
- $url_params['saveToFile'] = 'download';
- $url = 'tbl_gis_visualization.php' . PMA_URL_getCommon($url_params);
-
- $html .= '<ul>';
- $html .= PMA_getHtmlForGisDownloadLink($url, 'png', 'PNG');
- $html .= PMA_getHtmlForGisDownloadLink($url, 'pdf', 'PDF');
- if ($svg_support) {
- $html .= PMA_getHtmlForGisDownloadLink($url, 'svg', 'SVG');
- }
- $html .= '</ul>';
- $html .= '</div></div>';
-
- $html .= '</div>';
-
- $html .= '<div style="clear:both;">&nbsp;</div>';
-
- $html .= '<div id="placeholder" style="width:';
- $html .= htmlspecialchars($visualizationSettings['width']) . 'px;height:';
- $html .= htmlspecialchars($visualizationSettings['height']) . 'px;">';
- $html .= $visualization;
- $html .= '</div>';
-
- $html .= '<div id="openlayersmap"></div>';
- $html .= '<input type="hidden" id="pmaThemeImage" value="';
- $html .= $GLOBALS['pmaThemeImage'] . '" />';
- $html .= '<script language="javascript" type="text/javascript">';
- $html .= 'function drawOpenLayers()';
- $html .= '{';
-
- if (! $GLOBALS['PMA_Config']->isHttps()) {
- $html .= PMA_GIS_visualizationResults($data, $visualizationSettings, 'ol');
- }
- $html .= '}';
- $html .= '</script>';
- $html .= '</fieldset>';
- $html .= '</div>';
-
- return $html;
-}
-?>
diff --git a/libraries/tbl_indexes.lib.php b/libraries/tbl_indexes.lib.php
deleted file mode 100644
index fc03e4c6bd..0000000000
--- a/libraries/tbl_indexes.lib.php
+++ /dev/null
@@ -1,480 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Set of functions related to table indexes
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * Function to get the name and type of the columns of a table
- *
- * @param string $db current database
- * @param string $table current table
- *
- * @return array
- */
-function PMA_getNameAndTypeOfTheColumns($db, $table)
-{
- $columns = array();
- foreach ($GLOBALS['dbi']->getColumnsFull($db, $table) as $row) {
- if (preg_match('@^(set|enum)\((.+)\)$@i', $row['Type'], $tmp)) {
- $tmp[2] = /*overload*/mb_substr(
- preg_replace('@([^,])\'\'@', '\\1\\\'', ',' . $tmp[2]), 1
- );
- $columns[$row['Field']] = $tmp[1] . '('
- . str_replace(',', ', ', $tmp[2]) . ')';
- } else {
- $columns[$row['Field']] = $row['Type'];
- }
- } // end while
-
- return $columns;
-}
-
-/**
- * Function to handle the creation or edit of an index
- *
- * @param string $db current db
- * @param string $table current table
- * @param PMA_Index $index current index
- *
- * @return void
- */
-function PMA_handleCreateOrEditIndex($db, $table, $index)
-{
- $error = false;
-
- $sql_query = PMA_getSqlQueryForIndexCreateOrEdit($db, $table, $index, $error);
-
- // If there is a request for SQL previewing.
- if (isset($_REQUEST['preview_sql'])) {
- PMA_previewSQL($sql_query);
- }
-
- if (! $error) {
- $GLOBALS['dbi']->query($sql_query);
- $message = PMA_Message::success(
- __('Table %1$s has been altered successfully.')
- );
- $message->addParam($table);
-
- if ($GLOBALS['is_ajax_request'] == true) {
- $response = PMA_Response::getInstance();
- $response->addJSON(
- 'message', PMA_Util::getMessage($message, $sql_query, 'success')
- );
- $response->addJSON('index_table', PMA_Index::getView($table, $db));
- } else {
- include 'tbl_structure.php';
- }
- exit;
- } else {
- $response = PMA_Response::getInstance();
- $response->isSuccess(false);
- $response->addJSON('message', $error);
- exit;
- }
-}
-
-/**
- * Function to get the sql query for index creation or edit
- *
- * @param string $db current db
- * @param string $table current table
- * @param PMA_Index $index current index
- * @param bool &$error whether error occurred or not
- *
- * @return string
- */
-function PMA_getSqlQueryForIndexCreateOrEdit($db, $table, $index, &$error)
-{
- // $sql_query is the one displayed in the query box
- $sql_query = 'ALTER TABLE ' . PMA_Util::backquote($db)
- . '.' . PMA_Util::backquote($table);
-
- // Drops the old index
- if (! empty($_REQUEST['old_index'])) {
- if ($_REQUEST['old_index'] == 'PRIMARY') {
- $sql_query .= ' DROP PRIMARY KEY,';
- } else {
- $sql_query .= ' DROP INDEX '
- . PMA_Util::backquote($_REQUEST['old_index']) . ',';
- }
- } // end if
-
- // Builds the new one
- switch ($index->getChoice()) {
- case 'PRIMARY':
- if ($index->getName() == '') {
- $index->setName('PRIMARY');
- } elseif ($index->getName() != 'PRIMARY') {
- $error = PMA_Message::error(
- __('The name of the primary key must be "PRIMARY"!')
- );
- }
- $sql_query .= ' ADD PRIMARY KEY';
- break;
- case 'FULLTEXT':
- case 'UNIQUE':
- case 'INDEX':
- case 'SPATIAL':
- if ($index->getName() == 'PRIMARY') {
- $error = PMA_Message::error(__('Can\'t rename index to PRIMARY!'));
- }
- $sql_query .= ' ADD ' . $index->getChoice() . ' '
- . ($index->getName() ? PMA_Util::backquote($index->getName()) : '');
- break;
- } // end switch
-
- $index_fields = array();
- foreach ($index->getColumns() as $key => $column) {
- $index_fields[$key] = PMA_Util::backquote($column->getName());
- if ($column->getSubPart()) {
- $index_fields[$key] .= '(' . $column->getSubPart() . ')';
- }
- } // end while
-
- if (empty($index_fields)) {
- $error = PMA_Message::error(__('No index parts defined!'));
- } else {
- $sql_query .= ' (' . implode(', ', $index_fields) . ')';
- }
-
- $keyBlockSizes = $index->getKeyBlockSize();
- if (! empty($keyBlockSizes)) {
- $sql_query .= " KEY_BLOCK_SIZE = "
- . PMA_Util::sqlAddSlashes($keyBlockSizes);
- }
-
- // specifying index type is allowed only for primary, unique and index only
- $type = $index->getType();
- if ($index->getChoice() != 'SPATIAL'
- && $index->getChoice() != 'FULLTEXT'
- && in_array($type, PMA_Index::getIndexTypes())
- ) {
- $sql_query .= ' USING ' . $type;
- }
-
- $parser = $index->getParser();
- if ($index->getChoice() == 'FULLTEXT' && ! empty($parser)) {
- $sql_query .= " WITH PARSER " . PMA_Util::sqlAddSlashes($parser);
- }
-
- $comment = $index->getComment();
- if (! empty($comment)) {
- $sql_query .= " COMMENT '" . PMA_Util::sqlAddSlashes($comment) . "'";
- }
-
- $sql_query .= ';';
-
- return $sql_query;
-}
-
-/**
- * Function to prepare the form values for index
- *
- * @param string $db current database
- * @param string $table current table
- *
- * @return PMA_Index
- */
-function PMA_prepareFormValues($db, $table)
-{
- if (isset($_REQUEST['index'])) {
- if (is_array($_REQUEST['index'])) {
- // coming already from form
- $index = new PMA_Index($_REQUEST['index']);
- } else {
- $index = PMA_Index::singleton($db, $table, $_REQUEST['index']);
- }
- } else {
- $index = new PMA_Index;
- }
-
- return $index;
-}
-
-/**
- * Function to get the number of fields for the form
- *
- * @param PMA_Index $index index
- *
- * @return int
- */
-function PMA_getNumberOfFieldsForForm($index)
-{
- if (isset($_REQUEST['index']) && is_array($_REQUEST['index'])) {
- // coming already from form
- $add_fields
- = isset($_REQUEST['index']['columns']['names'])?
- count($_REQUEST['index']['columns']['names'])
- - $index->getColumnCount():0;
- if (isset($_REQUEST['add_fields'])) {
- $add_fields += $_REQUEST['added_fields'];
- }
- } elseif (isset($_REQUEST['create_index'])) {
- $add_fields = $_REQUEST['added_fields'];
- } else {
- $add_fields = 0;
- }// end preparing form values
-
- return $add_fields;
-}
-
-/**
- * Function to get form parameters
- *
- * @param string $db current db
- * @param string $table current table
- *
- * @return array
- */
-function PMA_getFormParameters($db, $table)
-{
- $form_params = array(
- 'db' => $db,
- 'table' => $table,
- );
-
- if (isset($_REQUEST['create_index'])) {
- $form_params['create_index'] = 1;
- } elseif (isset($_REQUEST['old_index'])) {
- $form_params['old_index'] = $_REQUEST['old_index'];
- } elseif (isset($_REQUEST['index'])) {
- $form_params['old_index'] = $_REQUEST['index'];
- }
-
- return $form_params;
-}
-
-/**
- * Function to get html for displaying the index form
- *
- * @param array $fields fields
- * @param PMA_Index $index index
- * @param array $form_params form parameters
- * @param int $add_fields number of fields in the form
- *
- * @return string
- */
-function PMA_getHtmlForIndexForm($fields, $index, $form_params, $add_fields)
-{
- $html = "";
- $html .= '<form action="tbl_indexes.php" method="post" name="index_frm" id="'
- . 'index_frm" class="ajax"'
- . 'onsubmit="if (typeof(this.elements[\'index[Key_name]\'].disabled) !='
- . ' \'undefined\') {'
- . 'this.elements[\'index[Key_name]\'].disabled = false}">';
-
- $html .= PMA_URL_getHiddenInputs($form_params);
-
- $html .= '<fieldset id="index_edit_fields">';
-
- $html .= '<div class="index_info">';
-
- $html .= '<div>'
- . '<div class="label">'
- . '<strong>'
- . '<label for="input_index_name">'
- . __('Index name:')
- . PMA_Util::showHint(
- PMA_Message::notice(
- __(
- '"PRIMARY" <b>must</b> be the name of'
- . ' and <b>only of</b> a primary key!'
- )
- )
- )
- . '</label>'
- . '</strong>'
- . '</div>'
- . '<input type="text" name="index[Key_name]" id="input_index_name"'
- . ' size="25"'
- . 'value="' . htmlspecialchars($index->getName()) . '"'
- . 'onfocus="this.select()" />'
- . '</div>';
-
- $html .= '<div>'
- . '<div class="label">'
- . '<strong>'
- . '<label for="select_index_choice">'
- . __('Index choice:')
- . PMA_Util::showMySQLDocu('ALTER_TABLE')
- . '</label>'
- . '</strong>'
- . '</div>'
- . $index->generateIndexChoiceSelector(isset($_REQUEST['create_edit_table']))
- . '</div>';
-
- $html .= PMA_Util::getDivForSliderEffect(
- 'indexoptions', __('Options')
- );
-
- $html .= '<div>'
- . '<div class="label">'
- . '<strong>'
- . '<label for="input_key_block_size">'
- . __('Key block size:')
- . '</label>'
- . '</strong>'
- . '</div>'
- . '<input type="text" name="index[Key_block_size]" '
- . 'id="input_key_block_size" size="30" value="'
- . htmlspecialchars($index->getKeyBlockSize()) . '" />'
- . '</div>';
-
- $html .= '<div>'
- . '<div class="label">'
- . '<strong>'
- . '<label for="select_index_type">'
- . __('Index type:')
- . PMA_Util::showMySQLDocu('ALTER_TABLE')
- . '</label>'
- . '</strong>'
- . '</div>'
- . $index->generateIndexTypeSelector()
- . '</div>';
-
- $html .= '<div>'
- . '<div class="label">'
- . '<strong>'
- . '<label for="input_parser">'
- . __('Parser:')
- . '</label>'
- . '</strong>'
- . '</div>'
- . '<input type="text" name="index[Parser]" '
- . 'id="input_parse" size="30" value="' . htmlspecialchars($index->getParser()) . '" />'
- . '</div>';
-
- $html .= '<div>'
- . '<div class="label">'
- . '<strong>'
- . '<label for="input_index_comment">'
- . __('Comment:')
- . '</label>'
- . '</strong>'
- . '</div>'
- . '<input type="text" name="index[Index_comment]" '
- . 'id="input_index_comment" size="30"'
- . 'value="' . htmlspecialchars($index->getComment()) . '" />'
- . '</div>';
-
- $html .= '</div>'; // end of indexoptions div
-
- $html .= '<div class="clearfloat"></div>';
-
- $html .= '</div>';
-
- $html .= '<table id="index_columns">';
-
- $html .= '<thead>'
- . '<tr>'
- . '<th>' . __('Column') . '</th>'
- . '<th>' . __('Size') . '</th>'
- . '</tr>'
- . '</thead>';
-
- $odd_row = true;
- $spatial_types = array(
- 'geometry', 'point', 'linestring', 'polygon', 'multipoint',
- 'multilinestring', 'multipolygon', 'geomtrycollection'
- );
- $html .= '<tbody>';
- /* @var $column PMA_Index_Column */
- foreach ($index->getColumns() as $column) {
- $html .= '<tr class="';
- $html .= $odd_row ? 'odd' : 'even';
- $html .= 'noclick">';
- $html .= '<td><span class="drag_icon" title="' . __('Drag to reorder') . '"'
- . '></span>';
- $html .= '<select name="index[columns][names][]">';
- $html .= '<option value="">-- ' . __('Ignore') . ' --</option>';
- foreach ($fields as $field_name => $field_type) {
- if (($index->getChoice() != 'FULLTEXT'
- || preg_match('/(char|text)/i', $field_type))
- && ($index->getChoice() != 'SPATIAL'
- || in_array($field_type, $spatial_types))
- ) {
- $html .= '<option value="' . htmlspecialchars($field_name) . '"'
- . (($field_name == $column->getName())
- ? ' selected="selected"'
- : '') . '>'
- . htmlspecialchars($field_name) . ' ['
- . htmlspecialchars($field_type) . ']'
- . '</option>' . "\n";
- }
- } // end foreach $fields
- $html .= '</select>';
- $html .= '</td>';
- $html .= '<td>';
- $html .= '<input type="text" size="5" onfocus="this.select()"'
- . 'name="index[columns][sub_parts][]" value="';
- if ($index->getChoice() != 'SPATIAL') {
- $html .= $column->getSubPart();
- }
- $html .= '"/>';
- $html .= '</td>';
- $html .= '</tr>';
- $odd_row = !$odd_row;
- } // end foreach $edited_index_info['Sequences']
-
- for ($i = 0; $i < $add_fields; $i++) {
- $html .= '<tr class="';
- $html .= $odd_row ? 'odd' : 'even';
- $html .= 'noclick">';
- $html .= '<td><span class="drag_icon" title="' . __('Drag to reorder') . '"'
- . '></span>';
- $html .= '<select name="index[columns][names][]">';
- $html .= '<option value="">-- ' . __('Ignore') . ' --</option>';
- $j = 0;
- foreach ($fields as $field_name => $field_type) {
- if (isset($_REQUEST['create_edit_table'])) {
- $col_index = $field_type[1];
- $field_type = $field_type[0];
- }
- $html .= '<option value="'
- . htmlspecialchars((isset($col_index)) ? $col_index : $field_name)
- . '" ' . ($j++ == $i ? 'selected="selected"' : '') . '>'
- . htmlspecialchars($field_name) . ' ['
- . htmlspecialchars($field_type) . ']'
- . '</option>' . "\n";
- } // end foreach $fields
- $html .= '</select>';
- $html .= '</td>';
- $html .= '<td>'
- . '<input type="text" size="5" onfocus="this.select()"'
- . 'name="index[columns][sub_parts][]" value="" />'
- . '</td>';
- $html .= '</tr>';
- $odd_row = !$odd_row;
- } // end foreach $edited_index_info['Sequences']
-
- $html .= '</tbody>';
-
- $html .= '</table>';
-
- $html .= '<div class="add_more">';
- $btn_value = sprintf(__('Add %s column(s) to index'), 1);
- $html .= '<div class="slider"></div>';
- $html .= '<div class="add_fields hide">';
- $html .= '<input type="submit" id="add_fields" value="' . $btn_value . '" />';
- $html .= '</div>';
- $html .= '</div>';
-
- $html .= '</fieldset>';
-
- $html .= '<fieldset class="tblFooters">';
- $html .= '<button type="submit" id="preview_index_frm">' . __('Preview SQL') . '</button>';
- $html .= '<input type="submit" id="save_index_frm" value="' . __('Go') . '" />';
- $html .= '</fieldset>';
-
- $html .= '</form>';
-
- return $html;
-}
-?>
diff --git a/libraries/tbl_info.inc.php b/libraries/tbl_info.inc.php
index a03addc478..1f70188e7b 100644
--- a/libraries/tbl_info.inc.php
+++ b/libraries/tbl_info.inc.php
@@ -38,13 +38,14 @@ $GLOBALS['dbi']->selectDb($GLOBALS['db']);
*/
$GLOBALS['showtable'] = array();
-// PMA_Table::sGetStatusInfo() does caching by default, but here
+// PMA_Table::getStatusInfo() does caching by default, but here
// we force reading of the current table status
// if $reread_info is true (for example, coming from tbl_operations.php
// and we just changed the table's storage engine)
-$GLOBALS['showtable'] = PMA_Table::sGetStatusInfo(
+$GLOBALS['showtable'] = $GLOBALS['dbi']->getTable(
$GLOBALS['db'],
- $GLOBALS['table'],
+ $GLOBALS['table']
+)->getStatusInfo(
null,
(isset($reread_info) && $reread_info ? true : false)
);
@@ -57,7 +58,7 @@ if ($showtable) {
/** @var PMA_String $pmaString */
$pmaString = $GLOBALS['PMA_String'];
- if (PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])) {
+ if ($GLOBALS['dbi']->getTable($GLOBALS['db'], $GLOBALS['table'])->isView()) {
$tbl_is_view = true;
$tbl_storage_engine = __('View');
$show_comment = null;
@@ -76,9 +77,9 @@ if ($showtable) {
: $showtable['Collation'];
if (null === $showtable['Rows']) {
- $showtable['Rows'] = PMA_Table::countRecords(
- $GLOBALS['db'], $showtable['Name'], true
- );
+ $showtable['Rows'] = $GLOBALS['dbi']
+ ->getTable($GLOBALS['db'], $showtable['Name'])
+ ->countRecords(true);
}
$table_info_num_rows = isset($showtable['Rows']) ? $showtable['Rows'] : 0;
$row_format = isset($showtable['Row_format']) ? $showtable['Row_format'] : '';
@@ -106,4 +107,3 @@ if ($showtable) {
: $pack_keys;
unset($create_options, $each_create_option);
} // end if
-?>
diff --git a/libraries/tbl_printview.lib.php b/libraries/tbl_printview.lib.php
deleted file mode 100644
index 57b8daac9a..0000000000
--- a/libraries/tbl_printview.lib.php
+++ /dev/null
@@ -1,602 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Set of functions related to show table print view
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-/**
- * return html for tables' info
- *
- * @param array $the_tables selected tables
- *
- * @return string
- */
-function PMA_getHtmlForTablesInfo($the_tables)
-{
- $html = '';
- $multi_tables = (count($the_tables) > 1);
-
- if ($multi_tables) {
- $tbl_list = '';
- foreach ($the_tables as $table) {
- $tbl_list .= (empty($tbl_list) ? '' : ', ')
- . PMA_Util::backquote($table);
- }
- $html .= '<strong>' . __('Showing tables:') . ' '
- . htmlspecialchars($tbl_list) . '</strong>' . "\n";
- $html .= '<hr />' . "\n";
- } // end if
-
- return $html;
-}
-
-
-/**
- * return html for print view footer
- *
- * @return string
- */
-function PMA_getHtmlForPrintViewFooter()
-{
- $html = PMA_Util::getButton();
- $html .= "<div id='PMA_disable_floating_menubar'></div>\n";
-
- return $html;
-}
-
-/**
- * return html for Print View Columns
- *
- * @param bool $tbl_is_view whether table is a view
- * @param array $columns columns list
- * @param array $analyzed_sql analyzed sql
- * @param bool $have_rel have relation?
- * @param array $res_rel relations array
- * @param string $db database name
- * @param string $table table name
- * @param array $cfgRelation config from PMA_getRelationsParam
- *
- * @return string
- */
-function PMA_getHtmlForPrintViewColumns(
- $tbl_is_view, $columns, $analyzed_sql, $have_rel,
- $res_rel, $db, $table, $cfgRelation
-) {
- $html = '';
- $primary = PMA_Index::getPrimary($table, $db);
- foreach ($columns as $row) {
- $extracted_columnspec = PMA_Util::extractColumnSpec($row['Type']);
- $type = $extracted_columnspec['print_type'];
-
- if (! isset($row['Default'])) {
- if ($row['Null'] != '' && $row['Null'] != 'NO') {
- $row['Default'] = '<i>NULL</i>';
- }
- } else {
- $row['Default'] = htmlspecialchars($row['Default']);
- }
- $field_name = htmlspecialchars($row['Field']);
-
- if (! $tbl_is_view) {
- // here, we have a TIMESTAMP that SHOW FULL COLUMNS reports as having
- // the NULL attribute, but SHOW CREATE TABLE says the contrary.
- // Believe the latter.
- /**
- * @todo merge this logic with the one in tbl_structure.php
- * or move it in a function similar to $GLOBALS['dbi']->getColumnsFull()
- * but based on SHOW CREATE TABLE because information_schema
- * cannot be trusted in this case (MySQL bug)
- */
- $analyzed_for_field
- = $analyzed_sql[0]['create_table_fields'][$field_name];
- if (! empty($analyzed_for_field['type'])
- && $analyzed_for_field['type'] == 'TIMESTAMP'
- && $analyzed_for_field['timestamp_not_null']
- ) {
- $row['Null'] = '';
- }
- }
-
- $html .= "\n";
- $html .= '<tr><td>';
-
- $html .= ' ' . $field_name . "\n";
- if ($primary && $primary->hasColumn($field_name)) {
- $html .= ' <em>(' . __('Primary') . ')</em>';
- }
- $html .= "\n";
- $html .= '</td>';
- $html .= '<td>' . htmlspecialchars($type) . '<bdo dir="ltr"></bdo></td>';
- $html .= '<td>';
- $html .= (($row['Null'] == '' || $row['Null'] == 'NO')
- ? __('No')
- : __('Yes'));
- $html .= '&nbsp;</td>';
- $html .= '<td>';
- if (isset($row['Default'])) {
- $html .= $row['Default'];
- }
- $html .= '&nbsp;</td>';
- if ($have_rel) {
- $html .= ' <td>';
- $foreigner = PMA_searchColumnInForeigners($res_rel, $field_name);
- if ($foreigner) {
- $html .= htmlspecialchars(
- $foreigner['foreign_table']
- . ' -> ' . $foreigner['foreign_field']
- );
- }
- $html .= '&nbsp;</td>' . "\n";
- }
- $html .= ' <td>';
- $comments = PMA_getComments($db, $table);
- if (isset($comments[$field_name])) {
- $html .= htmlspecialchars($comments[$field_name]);
- }
- $html .= '&nbsp;</td>' . "\n";
- if ($cfgRelation['mimework']) {
- $mime_map = PMA_getMIME($db, $table, true);
-
- $html .= ' <td>';
- if (isset($mime_map[$field_name])) {
- $html .= htmlspecialchars(
- str_replace('_', '/', $mime_map[$field_name]['mimetype'])
- );
- }
- $html .= '&nbsp;</td>' . "\n";
- }
- $html .= '</tr>';
- } // end foreach
-
- return $html;
-}
-
-/**
- * return html for Row Statistic
- *
- * @param array $showtable showing table information
- * @param int $cell_align_left cell align left
- * @param int $avg_size avg size
- * @param int $avg_unit avg unit
- * @param bool $mergetable is merge table?
- *
- * @return string
- */
-function PMA_getHtmlForRowStatistics(
- $showtable, $cell_align_left, $avg_size, $avg_unit, $mergetable
-) {
- $html = '<td width="20">&nbsp;</td>';
-
- // Rows Statistic
- $html .= "\n";
- $html .= '<td class="vtop">';
- $html .= '<big>' . __('Row Statistics:') . '</big>';
- $html .= '<table width="100%">';
- if (isset($showtable['Row_format'])) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Format') . '</td>';
- $html .= '<td class="' . $cell_align_left . '">';
- if ($showtable['Row_format'] == 'Fixed') {
- $html .= __('static');
- } elseif ($showtable['Row_format'] == 'Dynamic') {
- $html .= __('dynamic');
- } else {
- $html .= $showtable['Row_format'];
- }
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Rows'])) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Rows') . '</td>';
- $html .= '<td class="right">';
- $html .= PMA_Util::formatNumber($showtable['Rows'], 0);
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Avg_row_length'])
- && $showtable['Avg_row_length'] > 0
- ) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Row length') . '&nbsp;&oslash;</td>';
- $html .= '<td>';
- $html .= PMA_Util::formatNumber(
- $showtable['Avg_row_length'], 0
- );
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Data_length'])
- && $showtable['Rows'] > 0
- && $mergetable == false
- ) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Row size') . '&nbsp;&oslash;</td>';
- $html .= '<td class="right">';
- $html .= $avg_size . ' ' . $avg_unit;
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Auto_increment'])) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Next autoindex') . ' </td>';
- $html .= '<td class="right">';
- $html .= PMA_Util::formatNumber(
- $showtable['Auto_increment'], 0
- );
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Create_time'])) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Creation') . '</td>';
- $html .= '<td class="right">';
- $html .= PMA_Util::localisedDate(
- strtotime($showtable['Create_time'])
- );
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Update_time'])) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Last update') . '</td>';
- $html .= '<td class="right">';
- $html .= PMA_Util::localisedDate(
- strtotime($showtable['Update_time'])
- );
- $html .= '</td>';
- $html .= '</tr>';
- }
- if (isset($showtable['Check_time'])) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td>' . __('Last check') . '</td>';
- $html .= '<td class="right">';
- $html .= PMA_Util::localisedDate(
- strtotime($showtable['Check_time'])
- );
- $html .= '</td>';
- $html .= '</tr>';
- }
-
- return $html;
-}
-
-/**
- * return html for Space Usage
- *
- * @param int $data_size data size
- * @param int $data_unit data unit
- * @param int $index_size index size
- * @param int $index_unit index unit
- * @param int $free_size free size
- * @param int $free_unit free unit
- * @param int $effect_size effect size
- * @param int $effect_unit effect unit
- * @param int $tot_size total size
- * @param int $tot_unit total unit
- * @param bool $mergetable is merge table?
- *
- * @return string
- */
-function PMA_getHtmlForSpaceUsage(
- $data_size, $data_unit, $index_size, $index_unit,
- $free_size, $free_unit, $effect_size, $effect_unit,
- $tot_size, $tot_unit, $mergetable
-) {
- $html = '<table cellspacing="0" cellpadding="0">';
- $html .= "\n";
- $html .= '<tr>';
-
- // Space usage
- $html .= '<td class="vtop">';
- $html .= '<big>' . __('Space usage:') . '</big>';
- $html .= '<table width="100%">';
- $html .= '<tr>';
- $html .= '<td style="padding-right: 10px">' . __('Data') . '</td>';
- $html .= '<td class="right">' . $data_size . '</td>';
- $html .= '<td>' . $data_unit . '</td>';
- $html .= '</tr>';
- if (isset($index_size)) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td style="padding-right: 10px">' . __('Index') . '</td>';
- $html .= '<td class="right">' . $index_size . '</td>';
- $html .= '<td>' . $index_unit . '</td>';
- $html .= '</tr>';
- }
- if (isset($free_size)) {
- $html .= "\n";
- $html .= '<tr style="color: #bb0000">';
- $html .= '<td style="padding-right: 10px">';
- $html .= __('Overhead');
- $html .= '</td>';
- $html .= '<td class="right">' . $free_size . '</td>';
- $html .= '<td>' . $free_unit . '</td>';
- $html .= '</tr>';
- $html .= '<tr>';
- $html .= '<td style="padding-right: 10px">';
- $html .= __('Effective');
- $html .= '</td>';
- $html .= '<td class="right">' . $effect_size . '</td>';
- $html .= '<td>' . $effect_unit . '</td>';
- $html .= '</tr>';
- }
- if (isset($tot_size) && $mergetable == false) {
- $html .= "\n";
- $html .= '<tr>';
- $html .= '<td style="padding-right: 10px">' . __('Total') . '</td>';
- $html .= '<td class="right">' . $tot_size . '</td>';
- $html .= '<td>' . $tot_unit . '</td>';
- $html .= '</tr>';
- }
- $html .= "\n";
- $html .= '</table>';
-
- return $html;
-}
-/**
- * return html for Space Usage And Row Statistic
- *
- * @param array $showtable showing table information
- * @param string $db database
- * @param string $table table
- * @param int $cell_align_left cell align left
- *
- * @return string
- */
-function PMA_getHtmlForSpaceUsageAndRowStatistics(
- $showtable, $db, $table, $cell_align_left
-) {
- $html = '';
- $nonisam = false;
- if (isset($showtable['Type'])
- && ! preg_match('@ISAM|HEAP@i', $showtable['Type'])
- ) {
- $nonisam = true;
- }
- if ($nonisam == false) {
- // Gets some sizes
-
- $mergetable = PMA_Table::isMerge($db, $table);
-
- list($data_size, $data_unit) = PMA_Util::formatByteDown(
- $showtable['Data_length']
- );
- if ($mergetable == false) {
- list($index_size, $index_unit)
- = PMA_Util::formatByteDown(
- $showtable['Index_length']
- );
- }
- if (isset($showtable['Data_free']) && $showtable['Data_free'] > 0) {
- list($free_size, $free_unit)
- = PMA_Util::formatByteDown(
- $showtable['Data_free']
- );
- list($effect_size, $effect_unit)
- = PMA_Util::formatByteDown(
- $showtable['Data_length'] + $showtable['Index_length']
- - $showtable['Data_free']
- );
- } else {
- unset($free_size);
- unset($free_unit);
- list($effect_size, $effect_unit)
- = PMA_Util::formatByteDown(
- $showtable['Data_length'] + $showtable['Index_length']
- );
- }
- list($tot_size, $tot_unit) = PMA_Util::formatByteDown(
- $showtable['Data_length'] + $showtable['Index_length']
- );
- $num_rows = (isset($showtable['Rows']) ? $showtable['Rows'] : 0);
- if ($num_rows > 0) {
- list($avg_size, $avg_unit)
- = PMA_Util::formatByteDown(
- ($showtable['Data_length'] + $showtable['Index_length'])
- / $showtable['Rows'],
- 6,
- 1
- );
- }
-
- // Displays them
- $html .= '<br /><br />';
- $html .= PMA_getHtmlForSpaceUsage(
- $data_size, $data_unit,
- isset($index_size)? $index_size : null,
- isset($index_unit)? $index_unit : null,
- isset($free_size)? $free_size : null,
- isset($free_unit)? $free_unit : null,
- isset($effect_size)? $effect_size : null,
- isset($effect_unit)? $effect_unit : null,
- isset($tot_size)? $tot_size : null,
- isset($tot_unit)? $tot_unit : null,
- $mergetable
- );
-
- $html .= '</td>';
- $html .= PMA_getHtmlForRowStatistics(
- $showtable, $cell_align_left,
- isset($avg_size)? $avg_size: 0,
- isset($avg_unit)? $avg_unit: 0,
- $mergetable
- );
- $html .= "\n";
- $html .= '</table>';
- $html .= '</td>';
- $html .= '</tr>';
- $html .= '</table>';
- } // end if ($nonisam == false)
-
- return $html;
-}
-
-/**
- * return html for Table Structure
- *
- * @param bool $have_rel whether have relation
- * @param bool $tbl_is_view Is a table view?
- * @param array $columns columns list
- * @param array $analyzed_sql analyzed sql
- * @param array $res_rel relations array
- * @param string $db database
- * @param string $table table
- * @param array $cfgRelation config from PMA_getRelationsParam
- * @param array $cfg global config
- * @param array $showtable showing table information
- * @param int $cell_align_left cell align left
- *
- * @return string
- */
-function PMA_getHtmlForTableStructure(
- $have_rel, $tbl_is_view, $columns, $analyzed_sql,
- $res_rel, $db, $table, $cfgRelation,
- $cfg, $showtable, $cell_align_left
-) {
- /**
- * Displays the table structure
- */
- $html = '<table style="width: 100%;">';
- $html .= '<thead>';
- $html .= '<tr>';
- $html .= '<th>' . __('Column') . '</th>';
- $html .= '<th>' . __('Type') . '</th>';
- $html .= '<th>' . __('Null') . '</th>';
- $html .= '<th>' . __('Default') . '</th>';
- if ($have_rel) {
- $html .= '<th>' . __('Links to') . '</th>' . "\n";
- }
- $html .= ' <th>' . __('Comments') . '</th>' . "\n";
- if ($cfgRelation['mimework']) {
- $html .= ' <th>MIME</th>' . "\n";
- }
- $html .= '</tr>';
- $html .= '</thead>';
- $html .= '<tbody>';
- $html .= PMA_getHtmlForPrintViewColumns(
- $tbl_is_view, $columns, $analyzed_sql, $have_rel,
- $res_rel, $db, $table, $cfgRelation
- );
- $html .= '</tbody>';
- $html .= '</table>';
- if (! $tbl_is_view && !$GLOBALS['dbi']->isSystemSchema($db)) {
- /**
- * Displays indexes
- */
- $html .= PMA_Index::getView($table, $db, true);
-
- /**
- * Displays Space usage and row statistics
- *
- */
- if ($cfg['ShowStats']) {
- $html .= PMA_getHtmlForSpaceUsageAndRowStatistics(
- $showtable, $db, $table, $cell_align_left
- );
- } // end if ($cfg['ShowStats'])
- }
-
- return $html;
-}
-
-/**
- * return html for tables' detail
- *
- * @param array $the_tables tables list
- * @param string $db database name
- * @param array $cfg global config
- * @param array $cfgRelation config from PMA_getRelationsParam
- * @param int $cell_align_left cell align left
- *
- * @return string
- */
-function PMA_getHtmlForTablesDetail(
- $the_tables, $db, $cfg, $cfgRelation, $cell_align_left
-) {
- $html = '';
- $tables_cnt = count($the_tables);
- $multi_tables = (count($the_tables) > 1);
- $counter = 0;
-
- foreach ($the_tables as $table) {
- if ($counter + 1 >= $tables_cnt) {
- $breakstyle = '';
- } else {
- $breakstyle = ' style="page-break-after: always;"';
- }
- $counter++;
- $html .= '<div' . $breakstyle . '>' . "\n";
- $html .= '<h1>' . htmlspecialchars($table) . '</h1>' . "\n";
-
- /**
- * Gets table informations
- */
- $showtable = PMA_Table::sGetStatusInfo($db, $table);
- $num_rows = (isset($showtable['Rows']) ? $showtable['Rows'] : 0);
- $show_comment = (isset($showtable['Comment']) ? $showtable['Comment'] : '');
-
- $tbl_is_view = PMA_Table::isView($db, $table);
-
- /**
- * Gets fields properties
- */
- $columns = $GLOBALS['dbi']->getColumns($db, $table);
-
- // We need this to correctly learn if a TIMESTAMP is NOT NULL, since
- // SHOW FULL FIELDS or INFORMATION_SCHEMA incorrectly says NULL
- // and SHOW CREATE TABLE says NOT NULL (tested
- // in MySQL 4.0.25 and 5.0.21, http://bugs.mysql.com/20910).
-
- $show_create_table = $GLOBALS['dbi']->fetchValue(
- 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($table),
- 0, 1
- );
- $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table));
-
- // Check if we can use Relations
- // Find which tables are related with the current one and write it in
- // an array
- $res_rel = PMA_getForeigners($db, $table);
- $have_rel = (bool) count($res_rel);
-
- /**
- * Displays the comments of the table if MySQL >= 3.23
- */
- if (!empty($show_comment)) {
- $html .= __('Table comments:') . ' '
- . htmlspecialchars($show_comment) . '<br /><br />';
- }
-
- $html .= PMA_getHtmlForTableStructure(
- $have_rel, $tbl_is_view, $columns, $analyzed_sql,
- $res_rel, $db, $table, $cfgRelation,
- $cfg, $showtable, $cell_align_left
- );
-
- if ($multi_tables) {
- unset($num_rows, $show_comment);
- $html .= '<hr />' . "\n";
- } // end if
- $html .= '</div>' . "\n";
-
- } // end while
-
- return $html;
-}
-
-?>
diff --git a/libraries/tbl_relation.lib.php b/libraries/tbl_relation.lib.php
deleted file mode 100644
index a7ab588cbb..0000000000
--- a/libraries/tbl_relation.lib.php
+++ /dev/null
@@ -1,1224 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Functions for the table relation page
- *
- * @package PhpMyAdmin
- */
-
-/**
- * Generate dropdown choices
- *
- * @param string $dropdown_question Message to display
- * @param string $select_name Name of the <select> field
- * @param array $choices Choices for dropdown
- * @param string $selected_value Selected value
- *
- * @return string The html code for existing value (for selected)
- *
- * @access public
- */
-function PMA_generateDropdown(
- $dropdown_question, $select_name, $choices, $selected_value
-) {
- $html_output = (! empty($dropdown_question) ?
- htmlspecialchars($dropdown_question) . '&nbsp;&nbsp;' : '')
- . '<select name="' . htmlspecialchars($select_name) . '">' . "\n";
-
- foreach ($choices as $one_value => $one_label) {
- $html_output .= '<option value="' . htmlspecialchars($one_value) . '"';
- if ($selected_value == $one_value) {
- $html_output .= ' selected="selected" ';
- }
- $html_output .= '>' . htmlspecialchars($one_label) . '</option>' . "\n";
- }
- $html_output .= '</select>' . "\n";
-
- return $html_output;
-}
-
-/**
- * Split a string on backquote pairs
- *
- * @param string $text original string
- *
- * @return array containing the elements (and their surrounding backquotes)
- *
- * @access public
- */
-function PMA_backquoteSplit($text)
-{
- $elements = array();
- $final_pos = /*overload*/mb_strlen($text) - 1;
- $pos = 0;
- while ($pos <= $final_pos) {
- $first_backquote = /*overload*/mb_strpos($text, '`', $pos);
- $second_backquote = /*overload*/mb_strpos($text, '`', $first_backquote + 1);
- // after the second one, there might be another one which means
- // this is an escaped backquote
- if ($second_backquote < $final_pos && '`' == $text[$second_backquote + 1]) {
- $second_backquote
- = /*overload*/mb_strpos($text, '`', $second_backquote + 2);
- }
- if (false === $first_backquote || false === $second_backquote) {
- break;
- }
- $elements[] = /*overload*/mb_substr(
- $text, $first_backquote, $second_backquote - $first_backquote + 1
- );
- $pos = $second_backquote + 1;
- }
- return($elements);
-}
-
-/**
- * Returns the DROP query for a foreign key constraint
- *
- * @param string $table table of the foreign key
- * @param string $fk foreign key name
- *
- * @return string DROP query for the foreign key constraint
- */
-function PMA_getSQLToDropForeignKey($table, $fk)
-{
- return 'ALTER TABLE ' . PMA_Util::backquote($table)
- . ' DROP FOREIGN KEY ' . PMA_Util::backquote($fk) . ';';
-}
-
-/**
- * Returns the SQL query for foreign key constraint creation
- *
- * @param string $table table name
- * @param array $field field names
- * @param string $foreignDb foreign database name
- * @param string $foreignTable foreign table name
- * @param array $foreignField foreign field names
- * @param string $name name of the constraint
- * @param string $onDelete on delete action
- * @param string $onUpdate on update action
- *
- * @return string SQL query for foreign key constraint creation
- */
-function PMA_getSQLToCreateForeignKey($table, $field, $foreignDb, $foreignTable,
- $foreignField, $name = null, $onDelete = null, $onUpdate = null
-) {
- $sql_query = 'ALTER TABLE ' . PMA_Util::backquote($table) . ' ADD ';
- // if user entered a constraint name
- if (! empty($name)) {
- $sql_query .= ' CONSTRAINT ' . PMA_Util::backquote($name);
- }
-
- foreach ($field as $key => $one_field) {
- $field[$key] = PMA_Util::backquote($one_field);
- }
- foreach ($foreignField as $key => $one_field) {
- $foreignField[$key] = PMA_Util::backquote($one_field);
- }
- $sql_query .= ' FOREIGN KEY (' . implode(', ', $field) . ')'
- . ' REFERENCES ' . PMA_Util::backquote($foreignDb)
- . '.' . PMA_Util::backquote($foreignTable)
- . '(' . implode(', ', $foreignField) . ')';
-
- if (! empty($onDelete)) {
- $sql_query .= ' ON DELETE ' . $onDelete;
- }
- if (! empty($onUpdate)) {
- $sql_query .= ' ON UPDATE ' . $onUpdate;
- }
- $sql_query .= ';';
-
- return $sql_query;
-}
-
-/**
- * Creates and populates dropdowns to select foreign db/table/column
- *
- * @param string $name name of the dropdowns
- * @param array $values dropdown values
- * @param string|boolean $foreign value of the item to be selected
- * @param string $title title to show on hovering the dropdown
- *
- * @return string HTML for the dropdown
- */
-function PMA_generateRelationalDropdown(
- $name, $values = array(), $foreign = false, $title = ''
-) {
- $html_output = '<select name="' . $name . '" title="' . $title . '">';
- $html_output .= '<option value=""></option>';
-
- $seen_key = false;
- foreach ($values as $value) {
- $html_output .= '<option value="' . htmlspecialchars($value) . '"';
- if ($foreign && $value == $foreign) {
- $html_output .= ' selected="selected"';
- $seen_key = true;
- }
- $html_output .= '>' . htmlspecialchars($value) . '</option>';
- }
-
- if (is_string($foreign) && ! $seen_key) {
- $html_output .= '<option value="' . htmlspecialchars($foreign) . '"'
- . ' selected="selected">' . htmlspecialchars($foreign) . '</option>';
- }
- $html_output .= '</select>';
- return $html_output;
-}
-
-/**
- * Function to get html for the common form
- *
- * @param string $db current database
- * @param string $table current table
- * @param array $columns columns
- * @param array $cfgRelation configuration relation
- * @param string $tbl_storage_engine table storage engine
- * @param array $existrel db, table, column
- * @param array $existrel_foreign db, table, column
- * @param array $options_array options array
- *
- * @return string
- */
-function PMA_getHtmlForCommonForm($db, $table, $columns, $cfgRelation,
- $tbl_storage_engine, $existrel, $existrel_foreign, $options_array
-) {
- $html_output = PMA_getHtmlForCommonFormHeader($db, $table);
-
- if ($cfgRelation['relwork']) {
- $html_output .= PMA_getHtmlForInternalRelationForm(
- $columns, $tbl_storage_engine, $existrel, $db
- );
- }
-
- if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
- $html_output .= PMA_getHtmlForForeignKeyForm(
- $columns, $existrel_foreign,
- $db, $tbl_storage_engine, $options_array
- );
- } // end if (InnoDB)
-
- if ($cfgRelation['displaywork']) {
- $html_output .= PMA_getHtmlForDisplayFieldInfos(
- $db, $table,
- array_values($columns)
- );
- }
-
- $html_output .= PMA_getHtmlForCommonFormFooter();
-
- return $html_output;
-}
-
-/**
- * Function to get html for Internal relations form
- *
- * @param array $columns columns
- * @param string $tbl_storage_engine table storage engine
- * @param array $existrel db, table, column
- * @param string $db current database
- *
- * @return string
- */
-function PMA_getHtmlForInternalRelationForm($columns, $tbl_storage_engine,
- $existrel, $db
-) {
- $save_row = array_values($columns);
- $saved_row_cnt = count($save_row);
-
- $html_output = '<fieldset>'
- . '<legend>' . __('Internal relations') . '</legend>'
- . '<table id="internal_relations" class="relationalTable">';
-
- $html_output .= '<tr><th>' . __('Column') . '</th>';
-
- $html_output .= '<th>' . __('Internal relation');
- if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
- $html_output .= PMA_Util::showHint(
- __(
- 'An internal relation is not necessary when a corresponding'
- . ' FOREIGN KEY relation exists.'
- )
- );
- }
-
- $html_output .= '</th>';
-
- $odd_row = true;
- for ($i = 0; $i < $saved_row_cnt; $i++) {
- $html_output .= PMA_getHtmlForInternalRelationRow(
- $save_row, $i, $odd_row,
- $existrel, $db
- );
- $odd_row = ! $odd_row;
- }
-
- $html_output .= '</table>';
- $html_output .= '</fieldset>';
-
- return $html_output;
-}
-
-/**
- * Function to get html for an entire row in common form
- *
- * @param array $save_row save row
- * @param int $i counter
- * @param bool $odd_row whether odd row or not
- * @param array $existrel db, table, column
- * @param string $db current db
- *
- * @return string
- */
-function PMA_getHtmlForInternalRelationRow($save_row, $i, $odd_row,
- $existrel, $db
-) {
- $myfield = $save_row[$i]['Field'];
- // Use an md5 as array index to avoid having special characters
- // in the name attribute (see bug #1746964 )
- $myfield_md5 = md5($myfield);
- $myfield_html = htmlspecialchars($myfield);
-
- $html_output = '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
- . '<td class="vmiddle">'
- . '<strong>' . $myfield_html . '</strong>'
- . '<input type="hidden" name="fields_name[' . $myfield_md5 . ']"'
- . ' value="' . $myfield_html . '"/>'
- . '</td>';
-
- $html_output .= '<td>';
-
- $foreign_table = false;
- $foreign_column = false;
-
- // database dropdown
- if (isset($existrel[$myfield])) {
- $foreign_db = $existrel[$myfield]['foreign_db'];
- } else {
- $foreign_db = $db;
- }
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_db[' . $myfield_md5 . ']',
- $GLOBALS['pma']->databases,
- $foreign_db,
- __('Database')
- );
- // end of database dropdown
-
- // table dropdown
- $tables = array();
- if ($foreign_db) {
- if (isset($existrel[$myfield])) {
- $foreign_table = $existrel[$myfield]['foreign_table'];
- }
- $tables_rs = $GLOBALS['dbi']->query(
- 'SHOW TABLES FROM ' . PMA_Util::backquote($foreign_db),
- null,
- PMA_DatabaseInterface::QUERY_STORE
- );
- while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
- $tables[] = $row[0];
- }
- }
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_table[' . $myfield_md5 . ']',
- $tables,
- $foreign_table,
- __('Table')
- );
- // end of table dropdown
-
- // column dropdown
- $columns = array();
- if ($foreign_db && $foreign_table) {
- if (isset($existrel[$myfield])) {
- $foreign_column = $existrel[$myfield]['foreign_field'];
- }
- $table_obj = new PMA_Table($foreign_table, $foreign_db);
- $columns = $table_obj->getUniqueColumns(false, false);
- }
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_column[' . $myfield_md5 . ']',
- $columns,
- $foreign_column,
- __('Column')
- );
- // end of column dropdown
-
- $html_output .= '</td>';
- $html_output .= '</tr>';
-
- return $html_output;
-}
-
-/**
- * Function to get html for Foreign key form
- *
- * @param array $columns columns
- * @param array $existrel_foreign db, table, column
- * @param string $db current database
- * @param string $tbl_storage_engine table storage engine
- * @param array $options_array options array
- *
- * @return string
- */
-function PMA_getHtmlForForeignKeyForm($columns, $existrel_foreign, $db,
- $tbl_storage_engine, $options_array
-) {
- $html_output = '<fieldset>'
- . '<legend>' . __('Foreign key constraints') . '</legend>'
- . '<table id="foreign_keys" class="relationalTable">';
-
- $html_output .= '<tr><th>' . __('Actions') . '</th>';
- $html_output .= '<th>' . __('Constraint properties') . '</th>'
- . '<th>'
- . __('Column')
- . PMA_Util::showHint(
- __(
- 'Only columns with index will be displayed. You can define an'
- . ' index below.'
- )
- )
- . '</th>';
- $html_output .= '<th colspan="3">' . __('Foreign key constraint')
- . ' (' . $tbl_storage_engine . ')';
- $html_output .= '</th></tr>';
-
- $odd_row = true;
- $i = 0;
- if (! empty($existrel_foreign)) {
- foreach ($existrel_foreign as $key => $one_key) {
- $html_output .= PMA_getHtmlForForeignKeyRow(
- $one_key, $odd_row, $columns, $i++, $options_array,
- $tbl_storage_engine, $db
- );
- $odd_row = ! $odd_row;
- }
- }
- $html_output .= PMA_getHtmlForForeignKeyRow(
- array(), $odd_row, $columns, $i++, $options_array, $tbl_storage_engine,
- $db
- );
-
- $html_output .= '<tr>'
- . '<td colspan="5"><a class="formelement clearfloat'
- . ' add_foreign_key" href="">'
- . __('+ Add constraint')
- . '</td>';
- $html_output .= '</tr>';
- $html_output .= '</table>'
- . '</fieldset>';
-
- return $html_output;
-}
-
-/**
- * Function to get html for an entire row in foreign key form
- *
- * @param array $one_key Single foreign key constraint
- * @param bool $odd_row whether odd or even row
- * @param array $columns Array of table columns
- * @param int $i Row number
- * @param array $options_array Options array
- * @param string $tbl_storage_engine table storage engine
- * @param string $db Database
- *
- * @return string html
- */
-function PMA_getHtmlForForeignKeyRow($one_key, $odd_row, $columns, $i,
- $options_array, $tbl_storage_engine, $db
-) {
- $html_output = '<tr class="' . ($odd_row ? 'odd' : 'even') . '">';
- // Drop key anchor.
- $html_output .= '<td>';
- if (isset($one_key['constraint'])) {
- $drop_fk_query = 'ALTER TABLE ' . PMA_Util::backquote($GLOBALS['table'])
- . ' DROP FOREIGN KEY '
- . PMA_Util::backquote($one_key['constraint']) . ';';
- $this_params = $GLOBALS['url_params'];
- $this_params['goto'] = 'tbl_relation.php';
- $this_params['back'] = 'tbl_relation.php';
- $this_params['sql_query'] = $drop_fk_query;
- $this_params['message_to_show'] = sprintf(
- __('Foreign key constraint %s has been dropped'),
- $one_key['constraint']
- );
- $js_msg = PMA_jsFormat(
- 'ALTER TABLE ' . $GLOBALS['table']
- . ' DROP FOREIGN KEY '
- . $one_key['constraint'] . ';'
- );
-
- $html_output .= '<input type="hidden" class="drop_foreign_key_msg"'
- . ' value="' . $js_msg . '" />';
- $html_output .= ' <a class="drop_foreign_key_anchor';
- $html_output .= ' ajax';
- $html_output .= '" href="sql.php' . PMA_URL_getCommon($this_params)
- . '" >'
- . PMA_Util::getIcon('b_drop.png', __('Drop')) . '</a>';
- }
- $html_output .= '</td>';
- $html_output .= '<td>';
- $html_output .= '<span class="formelement clearfloat">';
- $constraint_name = isset($one_key['constraint'])
- ? $one_key['constraint'] : '';
- $html_output .= '<input type="text" name="constraint_name[' . $i . ']"'
- . ' value="' . htmlspecialchars($constraint_name) . '"'
- . ' placeholder="' . __('Constraint name') . '" />';
- $html_output .= '</span>' . "\n";
-
- $html_output .= '<div class="floatleft">';
- $html_output .= '<span class="formelement">';
- // For ON DELETE and ON UPDATE, the default action
- // is RESTRICT as per MySQL doc; however, a SHOW CREATE TABLE
- // won't display the clause if it's set as RESTRICT.
- $on_delete = isset($one_key['on_delete'])
- ? $one_key['on_delete'] : 'RESTRICT';
- $html_output .= PMA_generateDropdown(
- 'ON DELETE',
- 'on_delete[' . $i . ']',
- $options_array,
- $on_delete
- );
- $html_output .= '</span>' . "\n";
-
- $html_output .= '<span class="formelement">' . "\n";
- $on_update = isset($one_key['on_update'])
- ? $one_key['on_update'] : 'RESTRICT';
- $html_output .= PMA_generateDropdown(
- 'ON UPDATE',
- 'on_update[' . $i . ']',
- $options_array,
- $on_update
- );
- $html_output .= '</span>';
- $html_output .= '</div>';
-
- $column_array = array();
- $column_array[''] = '';
- foreach ($columns as $column) {
- if (! empty($column['Key'])) {
- $column_array[$column['Field']] = $column['Field'];
- }
- }
-
- $html_output .= '</span>' . "\n";
- $html_output .= '</td>';
- $html_output .= '<td>';
- if (isset($one_key['index_list'])) {
- foreach ($one_key['index_list'] as $key => $column) {
- $html_output .= '<span class="formelement clearfloat">';
- $html_output .= PMA_generateDropdown(
- '',
- 'foreign_key_fields_name[' . $i . '][]',
- $column_array,
- $column
- );
- $html_output .= '</span>';
- }
- } else {
- $html_output .= '<span class="formelement clearfloat">';
- $html_output .= PMA_generateDropdown(
- '',
- 'foreign_key_fields_name[' . $i . '][]',
- $column_array,
- ''
- );
- $html_output .= '</span>';
- }
-
- $html_output .= '<a class="formelement clearfloat add_foreign_key_field"'
- . ' href="" data-index="' . $i . '">'
- . __('+ Add column')
- . '</a>';
- $html_output .= '</td>';
- $html_output .= '<td>';
- $foreign_table = false;
-
- // foreign database dropdown
- $foreign_db = (isset($one_key['ref_db_name'])) ? $one_key['ref_db_name'] : $db;
- $html_output .= '<span class="formelement clearfloat">';
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_foreign_db[' . $i . ']',
- $GLOBALS['pma']->databases,
- $foreign_db,
- __('Database')
- );
- // end of foreign database dropdown
- $html_output .= '</td>';
- $html_output .= '<td>';
- // foreign table dropdown
- $tables = array();
- if ($foreign_db) {
- $foreign_table = isset($one_key['ref_table_name'])
- ? $one_key['ref_table_name'] : '';
-
- // In Drizzle, 'SHOW TABLE STATUS' will show status only for the tables
- // which are currently in the table cache. Hence we have to use
- // 'SHOW TABLES' and manualy retrieve table engine values.
- if (PMA_DRIZZLE) {
- $tables_rs = $GLOBALS['dbi']->query(
- 'SHOW TABLES FROM ' . PMA_Util::backquote($foreign_db),
- null,
- PMA_DatabaseInterface::QUERY_STORE
- );
- while ($row = $GLOBALS['dbi']->fetchArray($tables_rs)) {
- $engine = PMA_Table::sGetStatusInfo(
- $foreign_db,
- $row[0],
- 'Engine'
- );
- if (isset($engine)
- && /*overload*/mb_strtoupper($engine) == $tbl_storage_engine
- ) {
- $tables[] = $row[0];
- }
- }
- } else {
- $tables_rs = $GLOBALS['dbi']->query(
- 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($foreign_db),
- null,
- PMA_DatabaseInterface::QUERY_STORE
- );
- while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
- if (isset($row[1])
- && /*overload*/mb_strtoupper($row[1]) == $tbl_storage_engine
- ) {
- $tables[] = $row[0];
- }
- }
- }
- }
- $html_output .= '<span class="formelement clearfloat">';
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_foreign_table[' . $i . ']',
- $tables,
- $foreign_table,
- __('Table')
- );
- $html_output .= '</span>';
- // end of foreign table dropdown
- $html_output .= '</td>';
- $html_output .= '<td>';
- // foreign column dropdown
- if ($foreign_db && $foreign_table) {
- foreach ($one_key['ref_index_list'] as $foreign_column) {
- $table_obj = new PMA_Table($foreign_table, $foreign_db);
- $columns = $table_obj->getUniqueColumns(false, false);
- $html_output .= '<span class="formelement clearfloat">';
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_foreign_column[' . $i . '][]',
- $columns,
- $foreign_column,
- __('Column')
- );
- $html_output .= '</span>';
- }
- } else {
- $html_output .= '<span class="formelement clearfloat">';
- $html_output .= PMA_generateRelationalDropdown(
- 'destination_foreign_column[' . $i . '][]',
- array(),
- '',
- __('Column')
- );
- $html_output .= '</span>';
- }
- // end of foreign column dropdown
- $html_output .= '</td>';
- $html_output .= '</tr>';
-
- return $html_output;
-}
-
-/**
- * Function to get html for the common form header
- *
- * @param string $db current database
- * @param string $table current table
- *
- * @return string
- */
-function PMA_getHtmlForCommonFormHeader($db, $table)
-{
- return '<form method="post" action="tbl_relation.php">' . "\n"
- . PMA_URL_getHiddenInputs($db, $table);
-}
-
-/**
- * Function to get html for the common form footer
- *
- * @return string
- */
-function PMA_getHtmlForCommonFormFooter()
-{
- return '<fieldset class="tblFooters">'
- . '<input type="button" class="preview_sql" value="'
- . __('Preview SQL') . '" />'
- . '<input type="submit" value="' . __('Save') . '" />'
- . '</fieldset>'
- . '</form>';
-}
-
-/**
- * Function to get html for display field infos
- *
- * @param string $db current database
- * @param string $table current table
- * @param array $save_row save row
- *
- * @return string
- */
-function PMA_getHtmlForDisplayFieldInfos($db, $table, $save_row)
-{
- $disp = PMA_getDisplayField($db, $table);
- $html_output = '<fieldset>'
- . '<label>' . __('Choose column to display:') . '</label>'
- . '<select name="display_field">'
- . '<option value="">---</option>';
-
- foreach ($save_row as $row) {
- $html_output .= '<option value="'
- . htmlspecialchars($row['Field']) . '"';
- if (isset($disp) && $row['Field'] == $disp) {
- $html_output .= ' selected="selected"';
- }
- $html_output .= '>' . htmlspecialchars($row['Field'])
- . '</option>' . "\n";
- } // end while
-
- $html_output .= '</select>'
- . '</fieldset>';
-
- return $html_output;
-}
-
-/**
- * Function to send html for table or column dropdown list
- *
- * @return void
- */
-function PMA_sendHtmlForTableOrColumnDropdownList()
-{
- if (isset($_REQUEST['foreignTable'])) { // if both db and table are selected
- PMA_sendHtmlForColumnDropdownList();
- } else { // if only the db is selected
- PMA_sendHtmlForTableDropdownList();
- }
- exit;
-}
-
-/**
- * Function to send html for column dropdown list
- *
- * @return void
- */
-function PMA_sendHtmlForColumnDropdownList()
-{
- $response = PMA_Response::getInstance();
-
- $foreignTable = $_REQUEST['foreignTable'];
- $table_obj = new PMA_Table($foreignTable, $_REQUEST['foreignDb']);
- // Since views do not have keys defined on them provide the full list of columns
- if (PMA_Table::isView($_REQUEST['foreignDb'], $foreignTable)) {
- $columnList = $table_obj->getColumns(false, false);
- } else {
- $columnList = $table_obj->getIndexedColumns(false, false);
- }
- $columns = array();
- foreach ($columnList as $column) {
- $columns[] = htmlspecialchars($column);
- }
- $response->addJSON('columns', $columns);
-
- // @todo should be: $server->db($db)->table($table)->primary()
- $primary = PMA_Index::getPrimary($foreignTable, $_REQUEST['foreignDb']);
- if (false === $primary) {
- return;
- }
-
- $primarycols = array_keys($primary->getColumns());
- $response->addJSON('primary', $primarycols);
-}
-
-/**
- * Function to send html for table dropdown list
- *
- * @return void
- */
-function PMA_sendHtmlForTableDropdownList()
-{
- $response = PMA_Response::getInstance();
- $tables = array();
-
- $foreign = isset($_REQUEST['foreign']) && $_REQUEST['foreign'] === 'true';
- if ($foreign) {
- $tbl_storage_engine = /*overload*/mb_strtoupper(
- PMA_Table::sGetStatusInfo(
- $_REQUEST['db'],
- $_REQUEST['table'],
- 'Engine'
- )
- );
- }
-
- // In Drizzle, 'SHOW TABLE STATUS' will show status only for the tables
- // which are currently in the table cache. Hence we have to use 'SHOW TABLES'
- // and manually retrieve table engine values.
- if ($foreign && ! PMA_DRIZZLE) {
- $query = 'SHOW TABLE STATUS FROM '
- . PMA_Util::backquote($_REQUEST['foreignDb']);
- $tables_rs = $GLOBALS['dbi']->query(
- $query,
- null,
- PMA_DatabaseInterface::QUERY_STORE
- );
-
- while ($row = $GLOBALS['dbi']->fetchArray($tables_rs)) {
- if (isset($row['Engine'])
- && /*overload*/mb_strtoupper($row['Engine']) == $tbl_storage_engine
- ) {
- $tables[] = htmlspecialchars($row['Name']);
- }
- }
- } else {
- $query = 'SHOW TABLES FROM '
- . PMA_Util::backquote($_REQUEST['foreignDb']);
- $tables_rs = $GLOBALS['dbi']->query(
- $query,
- null,
- PMA_DatabaseInterface::QUERY_STORE
- );
- while ($row = $GLOBALS['dbi']->fetchArray($tables_rs)) {
- if ($foreign && PMA_DRIZZLE) {
- $engine = /*overload*/mb_strtoupper(
- PMA_Table::sGetStatusInfo(
- $_REQUEST['foreignDb'],
- $row[0],
- 'Engine'
- )
- );
- if (isset($engine) && $engine == $tbl_storage_engine) {
- $tables[] = htmlspecialchars($row[0]);
- }
- } else {
- $tables[] = htmlspecialchars($row[0]);
- }
- }
- }
- $response->addJSON('tables', $tables);
-}
-
-/**
- * Function to handle update for display field
- *
- * @param string $disp current display field
- * @param string $display_field display field
- * @param string $db current database
- * @param string $table current table
- * @param array $cfgRelation configuration relation
- *
- * @return string
- */
-function PMA_handleUpdateForDisplayField($disp, $display_field, $db, $table,
- $cfgRelation
-) {
- $html_output = '';
- $upd_query = PMA_getQueryForDisplayUpdate(
- $disp, $display_field, $db, $table, $cfgRelation
- );
- if ($upd_query) {
- PMA_queryAsControlUser($upd_query);
- $html_output = PMA_Util::getMessage(
- __('Display column was successfully updated.'),
- '', 'success'
- );
- }
- return $html_output;
-}
-
-/**
- * Function to get display query for handlingdisplay update
- *
- * @param string $disp current display field
- * @param string $display_field display field
- * @param string $db current database
- * @param string $table current table
- * @param array $cfgRelation configuration relation
- *
- * @return string
- */
-function PMA_getQueryForDisplayUpdate($disp, $display_field, $db, $table,
- $cfgRelation
-) {
- $upd_query = false;
- if ($disp) {
- if ($display_field == '') {
- $upd_query = 'DELETE FROM '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($cfgRelation['table_info'])
- . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND table_name = \'' . PMA_Util::sqlAddSlashes($table) . '\'';
- } elseif ($disp != $display_field) {
- $upd_query = 'UPDATE '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($cfgRelation['table_info'])
- . ' SET display_field = \''
- . PMA_Util::sqlAddSlashes($display_field) . '\''
- . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND table_name = \'' . PMA_Util::sqlAddSlashes($table) . '\'';
- }
- } elseif ($display_field != '') {
- $upd_query = 'INSERT INTO '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($cfgRelation['table_info'])
- . '(db_name, table_name, display_field) VALUES('
- . '\'' . PMA_Util::sqlAddSlashes($db) . '\','
- . '\'' . PMA_Util::sqlAddSlashes($table) . '\','
- . '\'' . PMA_Util::sqlAddSlashes($display_field) . '\')';
- }
-
- return $upd_query;
-}
-
-/**
- * Function to handle updates for internal relations
- *
- * @param array $destination_db destination databases
- * @param array $multi_edit_columns_name multi edit column names
- * @param array $destination_table destination tables
- * @param array $destination_column destination columns
- * @param array $cfgRelation configuration relation
- * @param string $db current database
- * @param string $table current table
- * @param array|null $existrel db, table, column
- *
- * @return string
- */
-function PMA_handleUpdatesForInternalRelations($destination_db,
- $multi_edit_columns_name, $destination_table, $destination_column, $cfgRelation,
- $db, $table, $existrel
-) {
- $html_output = '';
- $updated = false;
- foreach ($destination_db as $master_field_md5 => $foreign_db) {
- $upd_query = PMA_getQueryForInternalRelationUpdate(
- $multi_edit_columns_name,
- $master_field_md5, $foreign_db, $destination_table, $destination_column,
- $cfgRelation, $db, $table, isset($existrel) ? $existrel : null
- );
- if ($upd_query) {
- PMA_queryAsControlUser($upd_query);
- $updated = true;
- }
- }
- if ($updated) {
- $html_output = PMA_Util::getMessage(
- __('Internal relations were successfully updated.'),
- '', 'success'
- );
- }
- return $html_output;
-}
-
-/**
- * Function to get update query for updating internal relations
- *
- * @param array $multi_edit_columns_name multi edit column names
- * @param string $master_field_md5 master field md5
- * @param string $foreign_db foreign database
- * @param array $destination_table destination tables
- * @param array $destination_column destination columns
- * @param array $cfgRelation configuration relation
- * @param string $db current database
- * @param string $table current table
- * @param array|null $existrel db, table, column
- *
- * @return string
- */
-function PMA_getQueryForInternalRelationUpdate($multi_edit_columns_name,
- $master_field_md5, $foreign_db, $destination_table, $destination_column,
- $cfgRelation, $db, $table, $existrel
-) {
- $upd_query = false;
-
- // Map the fieldname's md5 back to its real name
- $master_field = $multi_edit_columns_name[$master_field_md5];
-
- $foreign_table = $destination_table[$master_field_md5];
- $foreign_field = $destination_column[$master_field_md5];
- if (! empty($foreign_db)
- && ! empty($foreign_table)
- && ! empty($foreign_field)
- ) {
- if (! isset($existrel[$master_field])) {
- $upd_query = 'INSERT INTO '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($cfgRelation['relation'])
- . '(master_db, master_table, master_field, foreign_db,'
- . ' foreign_table, foreign_field)'
- . ' values('
- . '\'' . PMA_Util::sqlAddSlashes($db) . '\', '
- . '\'' . PMA_Util::sqlAddSlashes($table) . '\', '
- . '\'' . PMA_Util::sqlAddSlashes($master_field) . '\', '
- . '\'' . PMA_Util::sqlAddSlashes($foreign_db) . '\', '
- . '\'' . PMA_Util::sqlAddSlashes($foreign_table) . '\','
- . '\'' . PMA_Util::sqlAddSlashes($foreign_field) . '\')';
-
- } elseif ($existrel[$master_field]['foreign_db'] != $foreign_db
- || $existrel[$master_field]['foreign_table'] != $foreign_table
- || $existrel[$master_field]['foreign_field'] != $foreign_field
- ) {
- $upd_query = 'UPDATE '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($cfgRelation['relation']) . ' SET'
- . ' foreign_db = \''
- . PMA_Util::sqlAddSlashes($foreign_db) . '\', '
- . ' foreign_table = \''
- . PMA_Util::sqlAddSlashes($foreign_table) . '\', '
- . ' foreign_field = \''
- . PMA_Util::sqlAddSlashes($foreign_field) . '\' '
- . ' WHERE master_db = \''
- . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND master_table = \''
- . PMA_Util::sqlAddSlashes($table) . '\''
- . ' AND master_field = \''
- . PMA_Util::sqlAddSlashes($master_field) . '\'';
- } // end if... else....
- } elseif (isset($existrel[$master_field])) {
- $upd_query = 'DELETE FROM '
- . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
- . '.' . PMA_Util::backquote($cfgRelation['relation'])
- . ' WHERE master_db = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND master_table = \'' . PMA_Util::sqlAddSlashes($table) . '\''
- . ' AND master_field = \'' . PMA_Util::sqlAddSlashes($master_field)
- . '\'';
- } // end if... else....
-
- return $upd_query;
-}
-
-/**
- * Function to handle foreign key updates
- *
- * @param array $destination_foreign_db destination foreign database
- * @param array $multi_edit_columns_name multi edit column names
- * @param array $destination_foreign_table destination foreign table
- * @param array $destination_foreign_column destination foreign column
- * @param array $options_array options array
- * @param string $table current table
- * @param array $existrel_foreign db, table, column
- *
- * @return string
- */
-function PMA_handleUpdatesForForeignKeys($destination_foreign_db,
- $multi_edit_columns_name, $destination_foreign_table,
- $destination_foreign_column, $options_array, $table, $existrel_foreign
-) {
- $html_output = '';
- $preview_sql_data = '';
- $display_query = '';
- $seen_error = false;
- $preview_sql = (isset($_REQUEST['preview_sql'])) ? true : false;
- foreach ($destination_foreign_db as $master_field_md5 => $foreign_db) {
- list($html, $sql_data) = PMA_handleUpdateForForeignKey(
- $multi_edit_columns_name, $master_field_md5,
- $destination_foreign_table, $destination_foreign_column, $options_array,
- $existrel_foreign, $table, $seen_error, $display_query, $foreign_db,
- $preview_sql
- );
- $html_output .= $html;
- $preview_sql_data .= $sql_data;
- } // end foreach
-
- // If there is a request for SQL previewing.
- if ($preview_sql) {
- PMA_previewSQL($preview_sql_data);
- }
-
- if (! empty($display_query) && ! $seen_error) {
- $GLOBALS['display_query'] = $display_query;
- $html_output = PMA_Util::getMessage(
- __('Your SQL query has been executed successfully.'),
- null, 'success'
- );
- }
-
- return $html_output;
-}
-
-/**
- * Function to handle update for a foreign key
- *
- * @param array $multi_edit_columns_name multi edit columns names
- * @param string $master_field_md5 master field md5
- * @param array $destination_foreign_table destination foreign tables
- * @param array $destination_foreign_column destination foreign columns
- * @param array $options_array options array
- * @param array $existrel_foreign db, table, column
- * @param string $table current table
- * @param bool &$seen_error whether seen error
- * @param string &$display_query display query
- * @param string $foreign_db foreign database
- * @param bool $preview_sql preview sql before executing
- *
- * @return array
- */
-function PMA_handleUpdateForForeignKey($multi_edit_columns_name, $master_field_md5,
- $destination_foreign_table, $destination_foreign_column, $options_array,
- $existrel_foreign, $table, &$seen_error, &$display_query,
- $foreign_db, $preview_sql
-) {
- $html_output = '';
- $preview_sql_data = '';
- $create = false;
- $drop = false;
-
- // Map the fieldname's md5 back to its real name
- $master_field = $multi_edit_columns_name[$master_field_md5];
-
- $foreign_table = $destination_foreign_table[$master_field_md5];
- $foreign_field = $destination_foreign_column[$master_field_md5];
-
- if (isset($existrel_foreign[$master_field_md5]['ref_db_name'])) {
- $ref_db_name = $existrel_foreign[$master_field_md5]['ref_db_name'];
- } else {
- $ref_db_name = $GLOBALS['db'];
- }
-
- $empty_fields = false;
- foreach ($master_field as $key => $one_field) {
- if ((! empty($one_field) && empty($foreign_field[$key]))
- || (empty($one_field) && ! empty($foreign_field[$key]))
- ) {
- $empty_fields = true;
- }
-
- if (empty($one_field) && empty($foreign_field[$key])) {
- unset($master_field[$key]);
- unset($foreign_field[$key]);
- }
- }
-
- if (! empty($foreign_db)
- && ! empty($foreign_table)
- && ! $empty_fields
- ) {
- if (isset($existrel_foreign[$master_field_md5])) {
- $constraint_name = $existrel_foreign[$master_field_md5]['constraint'];
- $on_delete = ! empty(
- $existrel_foreign[$master_field_md5]['on_delete'])
- ? $existrel_foreign[$master_field_md5]['on_delete']
- : 'RESTRICT';
- $on_update = ! empty(
- $existrel_foreign[$master_field_md5]['on_update'])
- ? $existrel_foreign[$master_field_md5]['on_update']
- : 'RESTRICT';
-
- if ($ref_db_name != $foreign_db
- || $existrel_foreign[$master_field_md5]['ref_table_name'] != $foreign_table
- || $existrel_foreign[$master_field_md5]['ref_index_list'] != $foreign_field
- || $existrel_foreign[$master_field_md5]['index_list'] != $master_field
- || $_REQUEST['constraint_name'][$master_field_md5] != $constraint_name
- || ($_REQUEST['on_delete'][$master_field_md5] != $on_delete)
- || ($_REQUEST['on_update'][$master_field_md5] != $on_update)
- ) {
- // another foreign key is already defined for this field
- // or an option has been changed for ON DELETE or ON UPDATE
- $drop = true;
- $create = true;
- } // end if... else....
- } else {
- // no key defined for this field(s)
- $create = true;
- }
- } elseif (isset($existrel_foreign[$master_field_md5])) {
- $drop = true;
- } // end if... else....
-
- $tmp_error_drop = false;
- if ($drop) {
- $drop_query = PMA_getSQLToDropForeignKey(
- $table, $existrel_foreign[$master_field_md5]['constraint']
- );
-
- if (! $preview_sql) {
- $display_query .= $drop_query . "\n";
- $GLOBALS['dbi']->tryQuery($drop_query);
- $tmp_error_drop = $GLOBALS['dbi']->getError();
-
- if (! empty($tmp_error_drop)) {
- $seen_error = true;
- $html_output .= PMA_Util::mysqlDie(
- $tmp_error_drop, $drop_query, false, '', false
- );
- return $html_output;
- }
- } else {
- $preview_sql_data .= $drop_query . "\n";
- }
- }
- $tmp_error_create = false;
- if (!$create) {
- return array($html_output, $preview_sql_data);
- }
-
- $create_query = PMA_getSQLToCreateForeignKey(
- $table, $master_field, $foreign_db, $foreign_table, $foreign_field,
- $_REQUEST['constraint_name'][$master_field_md5],
- $options_array[$_REQUEST['on_delete'][$master_field_md5]],
- $options_array[$_REQUEST['on_update'][$master_field_md5]]
- );
-
- if (! $preview_sql) {
- $display_query .= $create_query . "\n";
- $GLOBALS['dbi']->tryQuery($create_query);
- $tmp_error_create = $GLOBALS['dbi']->getError();
- if (! empty($tmp_error_create)) {
- $seen_error = true;
-
- if (substr($tmp_error_create, 1, 4) == '1005') {
- $message = PMA_Message::error(
- __('Error creating foreign key on %1$s (check data types)')
- );
- $message->addParam(implode(', ', $master_field));
- $html_output .= $message->getDisplay();
- } else {
- $html_output .= PMA_Util::mysqlDie(
- $tmp_error_create, $create_query, false, '', false
- );
- }
- $html_output .= PMA_Util::showMySQLDocu(
- 'InnoDB_foreign_key_constraints'
- ) . "\n";
- }
- } else {
- $preview_sql_data .= $create_query . "\n";
- }
-
- // this is an alteration and the old constraint has been dropped
- // without creation of a new one
- if ($drop && $create && empty($tmp_error_drop)
- && ! empty($tmp_error_create)
- ) {
- // a rollback may be better here
- $sql_query_recreate = '# Restoring the dropped constraint...' . "\n";
- $sql_query_recreate .= PMA_getSQLToCreateForeignKey(
- $table,
- $master_field,
- $existrel_foreign[$master_field_md5]['ref_db_name'],
- $existrel_foreign[$master_field_md5]['ref_table_name'],
- $existrel_foreign[$master_field_md5]['ref_index_list'],
- $existrel_foreign[$master_field_md5]['constraint'],
- $options_array[$existrel_foreign[$master_field_md5]['on_delete']],
- $options_array[$existrel_foreign[$master_field_md5]['on_update']]
- );
- if (! $preview_sql) {
- $display_query .= $sql_query_recreate . "\n";
- $GLOBALS['dbi']->tryQuery($sql_query_recreate);
- } else {
- $preview_sql_data .= $sql_query_recreate;
- }
- }
-
- return array($html_output, $preview_sql_data);
-}
-?>
diff --git a/libraries/tbl_views.lib.php b/libraries/tbl_views.lib.php
deleted file mode 100644
index 67aa22a30d..0000000000
--- a/libraries/tbl_views.lib.php
+++ /dev/null
@@ -1,161 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Set of functions related to applying transformations for VIEWs
- *
- * @package PhpMyAdmin
- */
-if (! defined('PHPMYADMIN')) {
- exit;
-}
-
-
-/**
- * Get the column details of VIEW with its original references
- *
- * @param string $sql_query SQL for original resource
- * @param array $view_columns Columns of VIEW if defined new column names
- *
- * @return array $column_map Details of VIEW columns
- */
-function PMA_getColumnMap($sql_query, $view_columns)
-{
-
- $column_map = array();
- // Select query which give results for VIEW
- $real_source_result = $GLOBALS['dbi']->tryQuery($sql_query);
-
- if ($real_source_result !== false) {
-
- $real_source_fields_meta = $GLOBALS['dbi']->getFieldsMeta(
- $real_source_result
- );
-
- $nbColumns = count($view_columns);
- $nbFields = count($real_source_fields_meta);
- if ($nbFields > 0) {
-
- for ($i=0; $i < $nbFields; $i++) {
-
- $map = array();
- $map['table_name'] = $real_source_fields_meta[$i]->table;
- $map['refering_column'] = $real_source_fields_meta[$i]->name;
-
- if ($nbColumns > 1) {
- $map['real_column'] = $view_columns[$i];
- }
-
- $column_map[] = $map;
-
- }
-
- }
-
- }
- unset($real_source_result);
-
- return $column_map;
-
-}
-
-
-/**
- * Get existing data on transformations applied for
- * columns in a particular table
- *
- * @param string $db Database name looking for
- *
- * @return mysqli_result Result of executed SQL query
- */
-function PMA_getExistingTransformationData($db)
-{
- $cfgRelation = PMA_getRelationsParam();
-
- // Get the existing transformation details of the same database
- // from pma__column_info table
- $pma_transformation_sql = 'SELECT * FROM '
- . PMA_Util::backquote($cfgRelation['db']) . '.'
- . PMA_Util::backquote($cfgRelation['column_info'])
- . ' WHERE `db_name` = \''
- . PMA_Util::sqlAddSlashes($db) . '\'';
-
- return $GLOBALS['dbi']->tryQuery($pma_transformation_sql);
-
-}
-
-
-/**
- * Get SQL query for store new transformation details of a VIEW
- *
- * @param mysqli_result $pma_transformation_data Result set of SQL execution
- * @param array $column_map Details of VIEW columns
- * @param string $view_name Name of the VIEW
- * @param string $db Database name of the VIEW
- *
- * @return string $new_transformations_sql SQL query for new transformations
- */
-function PMA_getNewTransformationDataSql(
- $pma_transformation_data, $column_map, $view_name, $db
-) {
- $cfgRelation = PMA_getRelationsParam();
-
- // Need to store new transformation details for VIEW
- $new_transformations_sql = 'INSERT INTO '
- . PMA_Util::backquote($cfgRelation['db']) . '.'
- . PMA_Util::backquote($cfgRelation['column_info'])
- . ' (`db_name`, `table_name`, `column_name`, `comment`, '
- . '`mimetype`, `transformation`, `transformation_options`)'
- . ' VALUES ';
-
- $column_count = 0;
- $add_comma = false;
-
- while ($data_row = $GLOBALS['dbi']->fetchAssoc($pma_transformation_data)) {
-
- foreach ($column_map as $column) {
-
- if ($data_row['table_name'] == $column['table_name']
- && $data_row['column_name'] == $column['refering_column']
- ) {
-
- $new_transformations_sql .= $add_comma ? ', ' : '';
-
- $new_transformations_sql .= '('
- . '\'' . $db . '\', '
- . '\'' . $view_name . '\', '
- . '\'';
-
- $new_transformations_sql .= (isset($column['real_column']))
- ? $column['real_column']
- : $column['refering_column'];
-
- $new_transformations_sql .= '\', '
- . '\'' . $data_row['comment'] . '\', '
- . '\'' . $data_row['mimetype'] . '\', '
- . '\'' . $data_row['transformation'] . '\', '
- . '\''
- . PMA_Util::sqlAddSlashes(
- $data_row['transformation_options']
- )
- . '\')';
-
- $add_comma = true;
- $column_count++;
- break;
-
- }
-
- }
-
- if ($column_count == count($column_map)) {
- break;
- }
-
- }
-
- return ($column_count > 0) ? $new_transformations_sql : '';
-
-}
-
-
-?>
diff --git a/libraries/tcpdf/README.TXT b/libraries/tcpdf/README.TXT
index 07ed3f82dc..b3a4a8bc5d 100644
--- a/libraries/tcpdf/README.TXT
+++ b/libraries/tcpdf/README.TXT
@@ -8,11 +8,11 @@ http://sourceforge.net/donate/index.php?group_id=128076
------------------------------------------------------------
Name: TCPDF
-Version: 6.2.3
-Release date: 2014-12-18
+Version: 6.2.9
+Release date: 2015-06-18
Author: Nicola Asuni
-Copyright (c) 2002-2014:
+Copyright (c) 2002-2015:
Nicola Asuni
Tecnick.com LTD
www.tecnick.com
@@ -34,7 +34,7 @@ Main Features:
* font subsetting;
* methods to publish some XHTML + CSS code, Javascript and Forms;
* images, graphic (geometric figures) and transformation methods;
- * supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http: www.imagemagick.org/www/formats.html)
+ * supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/script/formats.php)
* 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extension, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, Datamatrix, QR-Code, PDF417;
* JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;
* automatic page header and footer management;
diff --git a/libraries/tcpdf/include/tcpdf_images.php b/libraries/tcpdf/include/tcpdf_images.php
index c7ae9bd967..40cbe9d621 100644
--- a/libraries/tcpdf/include/tcpdf_images.php
+++ b/libraries/tcpdf/include/tcpdf_images.php
@@ -160,6 +160,14 @@ class TCPDF_IMAGES {
* @public static
*/
public static function _parsejpeg($file) {
+ // check if is a local file
+ if (!@file_exists($file)) {
+ // try to encode spaces on filename
+ $tfile = str_replace(' ', '%20', $file);
+ if (@file_exists($tfile)) {
+ $file = $tfile;
+ }
+ }
$a = getimagesize($file);
if (empty($a)) {
//Missing or incorrect image file
diff --git a/libraries/tcpdf/include/tcpdf_static.php b/libraries/tcpdf/include/tcpdf_static.php
index da87518cee..4ab18b6c4d 100644
--- a/libraries/tcpdf/include/tcpdf_static.php
+++ b/libraries/tcpdf/include/tcpdf_static.php
@@ -1,13 +1,13 @@
<?php
//============================================================+
// File name : tcpdf_static.php
-// Version : 1.1.0
+// Version : 1.1.3
// Begin : 2002-08-03
-// Last Update : 2014-12-10
+// Last Update : 2015-04-28
// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
// -------------------------------------------------------------------
-// Copyright (C) 2002-2014 Nicola Asuni - Tecnick.com LTD
+// Copyright (C) 2002-2015 Nicola Asuni - Tecnick.com LTD
//
// This file is part of TCPDF software library.
//
@@ -38,7 +38,7 @@
* This is a PHP class that contains static methods for the TCPDF class.<br>
* @package com.tecnick.tcpdf
* @author Nicola Asuni
- * @version 1.1.0
+ * @version 1.1.2
*/
/**
@@ -46,7 +46,7 @@
* Static methods used by the TCPDF class.
* @package com.tecnick.tcpdf
* @brief PHP class for generating PDF documents without requiring external extensions.
- * @version 1.1.0
+ * @version 1.1.1
* @author Nicola Asuni - info@tecnick.com
*/
class TCPDF_STATIC {
@@ -55,7 +55,7 @@ class TCPDF_STATIC {
* Current TCPDF version.
* @private static
*/
- private static $tcpdf_version = '6.2.3';
+ private static $tcpdf_version = '6.2.9';
/**
* String alias for total number of pages.
@@ -2434,8 +2434,8 @@ class TCPDF_STATIC {
public static function fopenLocal($filename, $mode) {
if (strpos($filename, '://') === false) {
$filename = 'file://'.$filename;
- } elseif (strpos($filename, 'file://') !== 0) {
- $this->Error('Unsupported file protocol');
+ } elseif (stream_is_local($filename) !== true) {
+ return false;
}
return fopen($filename, $mode);
}
@@ -2480,7 +2480,7 @@ class TCPDF_STATIC {
}
$urldata = @parse_url($url);
if (!isset($urldata['query']) OR (strlen($urldata['query']) <= 0)) {
- if (strpos($url, K_PATH_URL) === 0) {
+ if (K_PATH_URL AND (strpos($url, K_PATH_URL) === 0)) {
// convert URL to full server path
$tmp = str_replace(K_PATH_URL, K_PATH_MAIN, $url);
$tmp = htmlspecialchars_decode(urldecode($tmp));
diff --git a/libraries/tcpdf/tcpdf.php b/libraries/tcpdf/tcpdf.php
index 92ac141b0f..1412834912 100644
--- a/libraries/tcpdf/tcpdf.php
+++ b/libraries/tcpdf/tcpdf.php
@@ -1,13 +1,13 @@
<?php
//============================================================+
// File name : tcpdf.php
-// Version : 6.2.3
+// Version : 6.2.9
// Begin : 2002-08-03
-// Last Update : 2014-12-18
+// Last Update : 2015-06-18
// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
// -------------------------------------------------------------------
-// Copyright (C) 2002-2014 Nicola Asuni - Tecnick.com LTD
+// Copyright (C) 2002-2015 Nicola Asuni - Tecnick.com LTD
//
// This file is part of TCPDF software library.
//
@@ -104,7 +104,7 @@
* Tools to encode your unicode fonts are on fonts/utils directory.</p>
* @package com.tecnick.tcpdf
* @author Nicola Asuni
- * @version 6.2.3
+ * @version 6.2.8
*/
// TCPDF configuration
@@ -128,7 +128,7 @@ require_once(dirname(__FILE__).'/include/tcpdf_static.php');
* TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br>
* @package com.tecnick.tcpdf
* @brief PHP class for generating PDF documents without requiring external extensions.
- * @version 6.2.3
+ * @version 6.2.8
* @author Nicola Asuni - info@tecnick.com
*/
class TCPDF {
@@ -5748,7 +5748,7 @@ class TCPDF {
* @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width.
* @param $maxh (float) maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when $ishtml=false.
* @param $valign (string) Vertical alignment of text (requires $maxh = $h > 0). Possible values are:<ul><li>T: TOP</li><li>M: middle</li><li>B: bottom</li></ul>. This feature works only when $ishtml=false and the cell must fit in a single page.
- * @param $fitcell (boolean) if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). $maxh must be greater than 0 and wqual to $h.
+ * @param $fitcell (boolean) if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). $maxh must be greater than 0 and equal to $h.
* @return int Return the number of cells or 1 for html mode.
* @public
* @since 1.3
@@ -6819,10 +6819,10 @@ class TCPDF {
if ($this->state != 2) {
return;
}
- if ($x === '') {
+ if (strcmp($x, '') === 0) {
$x = $this->x;
}
- if ($y === '') {
+ if (strcmp($y, '') === 0) {
$y = $this->y;
}
// check page for no-write regions and adapt page margins if necessary
@@ -7026,6 +7026,7 @@ class TCPDF {
AND (($info === 'pngalpha') OR (isset($info['trns']) AND !empty($info['trns'])))) {
return $this->ImagePngAlpha($file, $x, $y, $pixw, $pixh, $w, $h, 'PNG', $link, $align, $resize, $dpi, $palign, $filehash);
}
+ $info = false;
}
if (($info === false) AND function_exists($gdfunction)) {
try {
@@ -9537,13 +9538,13 @@ class TCPDF {
$dcdate = TCPDF_STATIC::getFormattedDate($this->doc_creation_timestamp);
$doccreationdate = substr($dcdate, 0, 4).'-'.substr($dcdate, 4, 2).'-'.substr($dcdate, 6, 2);
$doccreationdate .= 'T'.substr($dcdate, 8, 2).':'.substr($dcdate, 10, 2).':'.substr($dcdate, 12, 2);
- $doccreationdate .= '+'.substr($dcdate, 15, 2).':'.substr($dcdate, 18, 2);
+ $doccreationdate .= substr($dcdate, 14, 3).':'.substr($dcdate, 18, 2);
$doccreationdate = TCPDF_STATIC::_escapeXML($doccreationdate);
// convert doc modification date format
$dmdate = TCPDF_STATIC::getFormattedDate($this->doc_modification_timestamp);
$docmoddate = substr($dmdate, 0, 4).'-'.substr($dmdate, 4, 2).'-'.substr($dmdate, 6, 2);
$docmoddate .= 'T'.substr($dmdate, 8, 2).':'.substr($dmdate, 10, 2).':'.substr($dmdate, 12, 2);
- $docmoddate .= '+'.substr($dmdate, 15, 2).':'.substr($dmdate, 18, 2);
+ $docmoddate .= substr($dmdate, 14, 3).':'.substr($dmdate, 18, 2);
$docmoddate = TCPDF_STATIC::_escapeXML($docmoddate);
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n";
$xmp .= "\t\t\t".'<xmp:CreateDate>'.$doccreationdate.'</xmp:CreateDate>'."\n";
@@ -10362,7 +10363,7 @@ class TCPDF {
* @public
*/
public function addHtmlLink($url, $name, $fill=false, $firstline=false, $color='', $style=-1, $firstblock=false) {
- if (isset($url[1]) AND ($url[0] == '#')) {
+ if (isset($url[1]) AND ($url[0] == '#') AND is_numeric($url[1])) {
// convert url to internal link
$lnkdata = explode(',', $url);
if (isset($lnkdata[0]) ) {
@@ -18175,7 +18176,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
// inherit column width
$cellw = 0;
for ($i = 0; $i < $colspan; ++$i) {
- $cellw += $table_colwidths[($colid + $i)];
+ $cellw += (isset($table_colwidths[($colid + $i)]) ? $table_colwidths[($colid + $i)] : 0);
}
}
$cellw += (($colspan - 1) * $cellspacing['H']);
@@ -18649,7 +18650,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
$this->lispacer = $prev_lispacer;
if ($ln AND (!($cell AND ($dom[$key-1]['value'] == 'table')))) {
$this->Ln($this->lasth);
- if ($this->y < $maxbottomliney) {
+ if (($this->y < $maxbottomliney) AND ($startlinepage == $this->page)) {
$this->y = $maxbottomliney;
}
}
@@ -19427,8 +19428,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
$prev_page = $this->page;
$this->setPage($dom[($dom[$key]['parent'])]['endpage']);
if ($this->num_columns > 1) {
- if ((($this->current_column == 0) AND ($dom[($dom[$key]['parent'])]['endcolumn'] == ($this->num_columns - 1)))
- OR (($this->current_column == $dom[($dom[$key]['parent'])]['endcolumn']) AND ($prev_page < $this->page))) {
+ if (($prev_page < $this->page)
+ AND ((($this->current_column == 0) AND ($dom[($dom[$key]['parent'])]['endcolumn'] == ($this->num_columns - 1)))
+ OR ($this->current_column == $dom[($dom[$key]['parent'])]['endcolumn']))) {
// page jump
$this->selectColumn(0);
$dom[($dom[$key]['parent'])]['endcolumn'] = 0;
diff --git a/libraries/tracking.lib.php b/libraries/tracking.lib.php
index e9e8871fe4..dc839b0413 100644
--- a/libraries/tracking.lib.php
+++ b/libraries/tracking.lib.php
@@ -220,7 +220,8 @@ function PMA_getHtmlForActivateDeactivateTracking(
);
$html .= '</legend>';
$html .= '<input type="hidden" name="version" value="' . $last_version . '" />';
- $html .= '<input type="hidden" name="toggle_activation" value="' . $value . '" />';
+ $html .= '<input type="hidden" name="toggle_activation" value="' . $value
+ . '" />';
$html .= '<input type="submit" value="' . $button . '" />';
$html .= '</fieldset>';
$html .= '</form>';
@@ -301,7 +302,7 @@ function PMA_getHtmlForTableVersionDetails(
. '&amp;submit_delete_version=true';
$checkbox_id = 'selected_versions_' . htmlspecialchars($version['version']);
- $html .= '<tr class="noclick ' . $style . '">';
+ $html .= '<tr class="' . $style . '">';
$html .= '<td class="center">';
$html .= '<input type="checkbox" name="selected_versions[]"'
. ' class="checkall" id="' . $checkbox_id . '"'
@@ -874,6 +875,7 @@ function PMA_getHtmlForColumns($columns)
$html .= '<table id="tablestructure" class="data">';
$html .= '<thead>';
$html .= '<tr>';
+ $html .= '<th>' . __('#') . '</th>';
$html .= '<th>' . __('Column') . '</th>';
$html .= '<th>' . __('Type') . '</th>';
$html .= '<th>' . __('Collation') . '</th>';
@@ -885,8 +887,9 @@ function PMA_getHtmlForColumns($columns)
$html .= '</thead>';
$html .= '<tbody>';
$style = 'odd';
+ $index = 1;
foreach ($columns as $field) {
- $html .= PMA_getHtmlForField($field, $style);
+ $html .= PMA_getHtmlForField($index++, $field, $style);
if ($style == 'even') {
$style = 'odd';
} else {
@@ -903,19 +906,25 @@ function PMA_getHtmlForColumns($columns)
/**
* Function to get html for field
*
+ * @param int $index index
* @param array $field field
* @param string $style style
*
* @return string
*/
-function PMA_getHtmlForField($field, $style)
+function PMA_getHtmlForField($index, $field, $style)
{
$html = '<tr class="noclick ' . $style . '">';
+ $html .= '<td>' . $index . '</td>';
$html .= '<td><b>' . htmlspecialchars($field['Field']);
if ($field['Key'] == 'PRI') {
$html .= ' ' . PMA_Util::getImage(
'b_primary.png', __('Primary')
);
+ } elseif (! empty($field['Key'])) {
+ $html .= ' ' . PMA_Util::getImage(
+ 'bd_primary.png', __('Index')
+ );
}
$html .= '</b></td>';
$html .= "\n";
@@ -1329,7 +1338,7 @@ function PMA_createTrackingVersion()
$GLOBALS['table'],
$_REQUEST['version'],
$tracking_set,
- PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])
+ $GLOBALS['dbi']->getTable($GLOBALS['db'], $GLOBALS['table'])->isView()
);
if ($versionCreated) {
$msg = PMA_Message::success(
@@ -1362,7 +1371,7 @@ function PMA_createTrackingForMultipleTables($selected)
$selected_table,
$_REQUEST['version'],
$tracking_set,
- PMA_Table::isView($GLOBALS['db'], $selected_table)
+ $GLOBALS['dbi']->getTable($GLOBALS['db'], $selected_table)->isView()
);
}
}
@@ -1436,4 +1445,297 @@ function PMA_getVersionStatus($version)
return __('not active');
}
}
-?>
+
+/**
+ * Display untracked tables
+ *
+ * @param string $db current database
+ * @param array $untracked_tables untracked tables
+ * @param string $url_query url query string
+ * @param string $pmaThemeImage path to theme's image folder
+ * @param string $text_dir text direction
+ *
+ * @return void
+ */
+function PMA_displayUntrackedTables(
+ $db, $untracked_tables, $url_query, $pmaThemeImage, $text_dir
+) {
+ ?>
+ <h3><?php echo __('Untracked tables');?></h3>
+ <form method="post" action="db_tracking.php" name="untrackedForm"
+ id="untrackedForm" class="ajax">
+ <?php
+ echo PMA_URL_getHiddenInputs($db)
+ ?>
+ <table id="noversions" class="data">
+ <thead>
+ <tr>
+ <th></th>
+ <th style="width: 300px"><?php echo __('Table');?></th>
+ <th><?php echo __('Action');?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php
+
+ // Print out list of untracked tables
+ $style = 'odd';
+ foreach ($untracked_tables as $key => $tablename) {
+ $style = PMA_displayOneUntrackedTable($db, $tablename, $url_query, $style);
+ }
+ ?>
+ </tbody>
+ </table>
+ <?php
+ echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "untrackedForm");
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_track',
+ __('Track table'), 'eye.png', 'track'
+ );
+ ?>
+ </form>
+ <?php
+}
+
+/**
+ * Display one untracked table
+ *
+ * @param string $db current database
+ * @param string $tablename the table name for which to display a line
+ * @param string $url_query url query string
+ * @param string $style odd|even
+ *
+ * @return string $style changed style (even|odd)
+ */
+function PMA_displayOneUntrackedTable($db, $tablename, $url_query, $style)
+{
+ $checkbox_id = "selected_tbl_"
+ . htmlspecialchars($tablename);
+ if (PMA_Tracker::getVersion($db, $tablename) == -1) {
+ $my_link = '<a href="tbl_tracking.php' . $url_query
+ . '&amp;table=' . htmlspecialchars($tablename) . '">';
+ $my_link .= PMA_Util::getIcon('eye.png', __('Track table'));
+ $my_link .= '</a>';
+ ?>
+ <tr class="<?php echo $style;?>">
+ <td class="center">
+ <input type="checkbox" name="selected_tbl[]"
+ class="checkall" id="<?php echo $checkbox_id;?>"
+ value="<?php echo htmlspecialchars($tablename);?>"/>
+ </td>
+ <th>
+ <label for="<?php echo $checkbox_id;?>">
+ <?php echo htmlspecialchars($tablename);?>
+ </label>
+ </th>
+ <td><?php echo $my_link;?></td>
+ </tr>
+ <?php
+ if ($style == 'even') {
+ $style = 'odd';
+ } else {
+ $style = 'even';
+ }
+ }
+ return $style;
+}
+
+/**
+ * Get untracked tables
+ *
+ * @param string $db current database
+ *
+ * @return array $untracked_tables
+ */
+function PMA_getUntrackedTables($db)
+{
+ $untracked_tables = array();
+ $sep = $GLOBALS['cfg']['NavigationTreeTableSeparator'];
+
+ // Get list of tables
+ $table_list = PMA_Util::getTableList($db);
+
+ // For each table try to get the tracking version
+ foreach ($table_list as $key => $value) {
+ // If $value is a table group.
+ if (array_key_exists(('is' . $sep . 'group'), $value)
+ && $value['is' . $sep . 'group']
+ ) {
+ foreach ($value as $temp_table) {
+ // If $temp_table is a table with the value for 'Name' is set,
+ // rather than a property of the table group.
+ if (is_array($temp_table)
+ && array_key_exists('Name', $temp_table)
+ ) {
+ $tracking_version = PMA_Tracker::getVersion(
+ $db,
+ $temp_table['Name']
+ );
+ if ($tracking_version == -1) {
+ $untracked_tables[] = $temp_table['Name'];
+ }
+ }
+ }
+ } else { // If $value is a table.
+ if (PMA_Tracker::getVersion($db, $value['Name']) == -1) {
+ $untracked_tables[] = $value['Name'];
+ }
+ }
+ }
+ return $untracked_tables;
+}
+
+/**
+ * Display tracked tables
+ *
+ * @param string $db current database
+ * @param object $all_tables_result result set of tracked tables
+ * @param string $url_query url query string
+ * @param string $pmaThemeImage path to theme's image folder
+ * @param string $text_dir text direction
+ * @param array $cfgRelation configuration storage info
+ *
+ * @return void
+ */
+function PMA_displayTrackedTables(
+ $db, $all_tables_result, $url_query, $pmaThemeImage, $text_dir, $cfgRelation
+) {
+ ?>
+ <div id="tracked_tables">
+ <h3><?php echo __('Tracked tables');?></h3>
+
+ <form method="post" action="db_tracking.php" name="trackedForm"
+ id="trackedForm" class="ajax">
+ <?php
+ echo PMA_URL_getHiddenInputs($db)
+ ?>
+ <table id="versions" class="data">
+ <thead>
+ <tr>
+ <th></th>
+ <th><?php echo __('Table');?></th>
+ <th><?php echo __('Last version');?></th>
+ <th><?php echo __('Created');?></th>
+ <th><?php echo __('Updated');?></th>
+ <th><?php echo __('Status');?></th>
+ <th><?php echo __('Action');?></th>
+ <th><?php echo __('Show');?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php
+
+ // Print out information about versions
+
+ $delete = PMA_Util::getIcon('b_drop.png', __('Delete tracking'));
+ $versions = PMA_Util::getIcon('b_versions.png', __('Versions'));
+ $report = PMA_Util::getIcon('b_report.png', __('Tracking report'));
+ $structure = PMA_Util::getIcon('b_props.png', __('Structure snapshot'));
+
+ $style = 'odd';
+ while ($one_result = $GLOBALS['dbi']->fetchArray($all_tables_result)) {
+ list($table_name, $version_number) = $one_result;
+ $table_query = ' SELECT * FROM ' .
+ PMA_Util::backquote($cfgRelation['db']) . '.' .
+ PMA_Util::backquote($cfgRelation['tracking']) .
+ ' WHERE `db_name` = \'' . PMA_Util::sqlAddSlashes($_REQUEST['db'])
+ . '\' AND `table_name` = \'' . PMA_Util::sqlAddSlashes($table_name)
+ . '\' AND `version` = \'' . $version_number . '\'';
+
+ $table_result = PMA_queryAsControlUser($table_query);
+ $version_data = $GLOBALS['dbi']->fetchArray($table_result);
+
+ $tbl_link = 'tbl_tracking.php' . $url_query . '&amp;table='
+ . htmlspecialchars($version_data['table_name']);
+ $delete_link = 'db_tracking.php' . $url_query . '&amp;table='
+ . htmlspecialchars($version_data['table_name'])
+ . '&amp;delete_tracking=true&amp';
+ $checkbox_id = "selected_tbl_"
+ . htmlspecialchars($version_data['table_name']);
+ ?>
+ <tr class="<?php echo $style;?>">
+ <td class="center">
+ <input type="checkbox" name="selected_tbl[]"
+ class="checkall" id="<?php echo $checkbox_id;?>"
+ value="<?php echo htmlspecialchars($version_data['table_name']);?>"/>
+ </td>
+ <th>
+ <label for="<?php echo $checkbox_id;?>">
+ <?php echo htmlspecialchars($version_data['table_name']);?>
+ </label>
+ </th>
+ <td class="right"><?php echo $version_data['version'];?></td>
+ <td><?php echo $version_data['date_created'];?></td>
+ <td><?php echo $version_data['date_updated'];?></td>
+ <td>
+ <?php
+ PMA_displayStatusButton($version_data, $tbl_link);
+ ?>
+ </td>
+ <td>
+ <a class="delete_tracking_anchor ajax"
+ href="<?php echo $delete_link;?>" >
+ <?php echo $delete; ?></a>
+ <?php
+ echo '</td>'
+ . '<td>'
+ . '<a href="' . $tbl_link . '">' . $versions . '</a>'
+ . '&nbsp;&nbsp;'
+ . '<a href="' . $tbl_link . '&amp;report=true&amp;version='
+ . $version_data['version'] . '">' . $report . '</a>'
+ . '&nbsp;&nbsp;'
+ . '<a href="' . $tbl_link . '&amp;snapshot=true&amp;version='
+ . $version_data['version'] . '">' . $structure . '</a>'
+ . '</td>'
+ . '</tr>';
+ if ($style == 'even') {
+ $style = 'odd';
+ } else {
+ $style = 'even';
+ }
+ }
+ ?>
+ </tbody>
+ </table>
+ <?php
+ echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "trackedForm");
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_delete_tracking',
+ __('Delete tracking'), 'b_drop.png', 'delete_tracking'
+ );
+ ?>
+ </form>
+ </div>
+ <?php
+}
+
+/**
+ * Display tracking status button
+ *
+ * @param array $version_data data about tracking versions
+ * @param string $tbl_link link for tbl_tracking.php
+ *
+ * @return void
+ */
+function PMA_displayStatusButton($version_data, $tbl_link)
+{
+ $state = PMA_getVersionStatus($version_data);
+ $options = array(
+ 0 => array(
+ 'label' => __('not active'),
+ 'value' => 'deactivate_now',
+ 'selected' => ($state != 'active')
+ ),
+ 1 => array(
+ 'label' => __('active'),
+ 'value' => 'activate_now',
+ 'selected' => ($state == 'active')
+ )
+ );
+ echo PMA_Util::toggleButton(
+ $tbl_link . '&amp;version=' . $version_data['version'],
+ 'toggle_activation',
+ $options,
+ null
+ );
+}
diff --git a/libraries/transformations.lib.php b/libraries/transformations.lib.php
index a202e0ea99..3983b7589c 100644
--- a/libraries/transformations.lib.php
+++ b/libraries/transformations.lib.php
@@ -162,14 +162,13 @@ function PMA_getTransformationClassName($filename)
/**
* Returns the description of the transformation
*
- * @param string $file transformation file
- * @param boolean $html_formatted whether the description should be formatted
- * as HTML
+ * @param string $file transformation file
*
* @return String the description of the transformation
*/
-function PMA_getTransformationDescription($file, $html_formatted = true)
+function PMA_getTransformationDescription($file)
{
+ /* @var $class_name TransformationsInterface */
$class_name = PMA_getTransformationClassName($file);
// include and instantiate the class
include_once 'libraries/plugins/transformations/' . $file;
@@ -177,6 +176,22 @@ function PMA_getTransformationDescription($file, $html_formatted = true)
}
/**
+ * Returns the name of the transformation
+ *
+ * @param string $file transformation file
+ *
+ * @return String the name of the transformation
+ */
+function PMA_getTransformationName($file)
+{
+ /* @var $class_name TransformationsInterface */
+ $class_name = PMA_getTransformationClassName($file);
+ // include and instantiate the class
+ include_once 'libraries/plugins/transformations/' . $file;
+ return $class_name::getName();
+}
+
+/**
* Gets the mimetypes for all columns of a table
*
* @param string $db the name of the db to check for
@@ -398,7 +413,7 @@ function PMA_setMIME($db, $table, $key, $mimetype, $transformation,
*/
function PMA_Transformation_globalHtmlReplace($buffer, $options = array())
{
- if ( ! isset($options['string']) ) {
+ if (! isset($options['string'])) {
$options['string'] = '';
}
@@ -458,4 +473,3 @@ function PMA_clearTransformations($db, $table = '', $column = '')
}
-?>
diff --git a/libraries/url_generating.lib.php b/libraries/url_generating.lib.php
index 799489b225..992ec45e8a 100644
--- a/libraries/url_generating.lib.php
+++ b/libraries/url_generating.lib.php
@@ -253,4 +253,3 @@ function PMA_URL_getArgSeparator($encode = 'none')
}
}
-?>
diff --git a/libraries/user_preferences.inc.php b/libraries/user_preferences.inc.php
index 241ca086d7..dc28f6d62b 100644
--- a/libraries/user_preferences.inc.php
+++ b/libraries/user_preferences.inc.php
@@ -10,7 +10,7 @@ if (!defined('PHPMYADMIN')) {
}
// build user preferences menu
-$form_param = filter_input(INPUT_GET, 'form');
+$form_param = isset($_GET['form']) ? $_GET['form'] : null;
if (! isset($forms[$form_param])) {
$forms_keys = array_keys($forms);
$form_param = array_shift($forms_keys);
@@ -22,14 +22,14 @@ $tabs_icons = array(
'Main_panel' => 'b_props.png',
'Import' => 'b_import.png',
'Export' => 'b_export.png');
-echo '<ul id="topmenu2">';
-echo PMA_Util::getHtmlTab(
+
+require_once './libraries/Template.class.php';
+$content = PMA_Util::getHtmlTab(
array(
'link' => 'prefs_manage.php',
'text' => __('Manage your settings')
)
) . "\n";
-echo '<li>&nbsp; &nbsp;</li>' . "\n";
$script_name = basename($GLOBALS['PMA_PHP_SELF']);
foreach (array_keys($forms) as $formset) {
$tab = array(
@@ -37,9 +37,17 @@ foreach (array_keys($forms) as $formset) {
'text' => PMA_lang('Form_' . $formset),
'icon' => $tabs_icons[$formset],
'active' => ($script_name == 'prefs_forms.php' && $formset == $form_param));
- echo PMA_Util::getHtmlTab($tab, array('form' => $formset)) . "\n";
+ $content .= PMA_Util::getHtmlTab($tab, array('form' => $formset)) . "\n";
}
-echo '</ul><div class="clearfloat"></div>';
+echo PMA\Template::get('list/unordered')->render(
+ array(
+ 'id' => 'topmenu2',
+ 'class' => 'user_prefs_tabs',
+ 'content' => $content,
+ )
+);
+echo '<div class="clearfloat"></div>';
+
// show "configuration saved" message and reload navigation panel if needed
if (!empty($_GET['saved'])) {
@@ -63,7 +71,10 @@ $msg->display();
// warn about using session storage for settings
$cfgRelation = PMA_getRelationsParam();
if (! $cfgRelation['userconfigwork']) {
- $msg = __('Your preferences will be saved for current session only. Storing them permanently requires %sphpMyAdmin configuration storage%s.');
+ $msg = __(
+ 'Your preferences will be saved for current session only. Storing them '
+ . 'permanently requires %sphpMyAdmin configuration storage%s.'
+ );
$msg = PMA_sanitize(
sprintf($msg, '[doc@linked-tables]', '[/doc]')
);
diff --git a/libraries/user_preferences.lib.php b/libraries/user_preferences.lib.php
index c2fb9fb0f7..2d1df548f8 100644
--- a/libraries/user_preferences.lib.php
+++ b/libraries/user_preferences.lib.php
@@ -9,6 +9,8 @@ if (! defined('PHPMYADMIN')) {
exit;
}
+require_once './libraries/Template.class.php';
+
/**
* Common initialization for user preferences modification pages
*
@@ -266,36 +268,23 @@ function PMA_userprefsRedirect($file_name,
*/
function PMA_userprefsAutoloadGetHeader()
{
- $retval = '';
-
if (isset($_REQUEST['prefs_autoload'])
&& $_REQUEST['prefs_autoload'] == 'hide'
) {
$_SESSION['userprefs_autoload'] = true;
- } else {
- $script_name = basename(basename($GLOBALS['PMA_PHP_SELF']));
- $return_url = htmlspecialchars(
- $script_name . '?' . http_build_query($_GET, '', '&')
- );
+ return '';
+ }
- $retval .= '<div id="prefs_autoload" class="notice" style="display:none">';
- $retval .= '<form action="prefs_manage.php" method="post" class="disableAjax">';
- $retval .= PMA_URL_getHiddenInputs();
- $retval .= '<input type="hidden" name="json" value="" />';
- $retval .= '<input type="hidden" name="submit_import" value="1" />';
- $retval .= '<input type="hidden" name="return_url" value="'
- . $return_url . '" />';
- $retval .= __(
- 'Your browser has phpMyAdmin configuration for this domain. '
- . 'Would you like to import it for current session?'
+ $script_name = basename(basename($GLOBALS['PMA_PHP_SELF']));
+ $return_url = htmlspecialchars(
+ $script_name . '?' . http_build_query($_GET, '', '&')
+ );
+
+ return PMA\Template::get('prefs_autoload')
+ ->render(
+ array(
+ 'hiddenInputs' => PMA_URL_getHiddenInputs(),
+ 'return_url' => $return_url,
+ )
);
- $retval .= '<br />';
- $retval .= '<a href="#yes">' . __('Yes') . '</a>';
- $retval .= ' / ';
- $retval .= '<a href="#no">' . __('No') . '</a>';
- $retval .= '</form>';
- $retval .= '</div>';
- }
- return $retval;
}
-?>
diff --git a/libraries/util.lib.php b/libraries/util.lib.php
new file mode 100644
index 0000000000..813252b8d6
--- /dev/null
+++ b/libraries/util.lib.php
@@ -0,0 +1,38 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Util file creation
+ *
+ * @package PhpMyAdmin
+ */
+
+namespace PMA\Util;
+
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+/**
+ * Access to a multidimensional array by dot notation
+ *
+ * @param array $array List of values
+ * @param string|array $path Path to searched value
+ * @param mixed $default Default value
+ *
+ * @return mixed Searched value
+ */
+function get($array, $path, $default = null)
+{
+ if (is_string($path)) {
+ $path = explode('.', $path);
+ }
+ $p = array_shift($path);
+ while (isset($p)) {
+ if (!isset($array[$p])) {
+ return $default;
+ }
+ $array = $array[$p];
+ $p = array_shift($path);
+ }
+ return $array;
+} \ No newline at end of file
diff --git a/libraries/vendor_config.php b/libraries/vendor_config.php
index e3b1443161..70871509b6 100644
--- a/libraries/vendor_config.php
+++ b/libraries/vendor_config.php
@@ -46,7 +46,7 @@ define('SQL_DIR', './sql/');
* It is not used directly in code, just a convenient
* define used further in this file.
*/
-define('CONFIG_DIR', './');
+define('CONFIG_DIR', '');
/**
* Filename of a configuration file.
@@ -85,9 +85,12 @@ define('TCPDF_INC', './libraries/tcpdf/tcpdf.php');
define('PHPSECLIB_INC_DIR', './libraries/phpseclib/');
/**
+ * Path to the udan11/sql-parser. Useful when you want to use system version.
+ */
+define('SQL_PARSER_AUTOLOAD', './libraries/sql-parser/autoload.php');
+
+/**
* Avoid referring to nonexistent files (causes warnings when open_basedir
* is used)
*/
define('K_PATH_IMAGES', '');
-
-?>
diff --git a/libraries/zip.lib.php b/libraries/zip.lib.php
index 37ef614314..43c08d851c 100644
--- a/libraries/zip.lib.php
+++ b/libraries/zip.lib.php
@@ -145,7 +145,7 @@ class ZipFile
$fr .= $zdata;
// echo this entry on the fly, ...
- if ( $this -> doWrite) {
+ if ($this -> doWrite) {
echo $fr;
} else { // ... OR add this entry to array
$this -> datasec[] = $fr;
@@ -198,7 +198,7 @@ class ZipFile
pack('V', $this -> old_offset) . //offset to start of central dir
"\x00\x00"; //.zip file comment length
- if ( $this -> doWrite ) { // Send central directory & end ctrl dir to STDOUT
+ if ($this -> doWrite) { // Send central directory & end ctrl dir to STDOUT
echo $header;
return ""; // Return empty string
} else { // Return entire ZIP archive as string
@@ -208,4 +208,3 @@ class ZipFile
} // end of the 'file()' method
} // end of the 'ZipFile' class
-?>
diff --git a/libraries/zip_extension.lib.php b/libraries/zip_extension.lib.php
index 33562db9a3..b27158cc8a 100644
--- a/libraries/zip_extension.lib.php
+++ b/libraries/zip_extension.lib.php
@@ -101,7 +101,7 @@ function PMA_getZipContents($file, $specific_entry = null)
*
* @return string the file name of the first file that matches the given regexp
*/
-function PMA_findFileFromZipArchive ($file_regexp, $file)
+function PMA_findFileFromZipArchive($file_regexp, $file)
{
$zip_handle = zip_open($file);
if (is_resource($zip_handle)) {
@@ -192,4 +192,3 @@ function PMA_getZipError($code)
}
return $message;
}
-?>
diff --git a/license.php b/license.php
index d076cae49f..7348af874f 100644
--- a/license.php
+++ b/license.php
@@ -25,7 +25,10 @@ $filename = LICENSE_FILE;
if (is_readable($filename)) {
readfile($filename);
} else {
- printf(__('The %s file is not available on this system, please visit www.phpmyadmin.net for more information.'), $filename);
+ printf(
+ __(
+ 'The %s file is not available on this system, please visit ' .
+ 'www.phpmyadmin.net for more information.'
+ ), $filename
+ );
}
-
-?>
diff --git a/lint.php b/lint.php
new file mode 100644
index 0000000000..9aef982888
--- /dev/null
+++ b/lint.php
@@ -0,0 +1,37 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Represents the interface between the linter and the query editor.
+ *
+ * @package PhpMyAdmin
+ */
+
+/**
+ * Loading common files. Used to check for authorization, localization and to
+ * load the parsing library.
+ */
+require_once 'libraries/common.inc.php';
+
+/**
+ * Loads the linter.
+ */
+require_once 'libraries/Linter.class.php';
+
+/**
+ * The SQL query to be analyzed.
+ *
+ * This does not need to be checked again XSS or MySQL injections because it is
+ * never executed, just parsed.
+ *
+ * The client, which will recieve the JSON response will decode the message and
+ * and any HTML fragments that are displayed to the user will be encoded anyway.
+ *
+ * @var string
+ */
+$sql_query = !empty($_POST['sql_query']) ? $_POST['sql_query'] : '';
+
+// Disabling standard response.
+$response = PMA_Response::getInstance();
+$response->disable();
+
+echo json_encode(PMA_Linter::lint($sql_query));
diff --git a/locale/az/LC_MESSAGES/phpmyadmin.mo b/locale/az/LC_MESSAGES/phpmyadmin.mo
index 8c0559e56d..a3aab0d1e0 100644
--- a/locale/az/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/az/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/bg/LC_MESSAGES/phpmyadmin.mo b/locale/bg/LC_MESSAGES/phpmyadmin.mo
index cd8f219be9..53ebd430b7 100644
--- a/locale/bg/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/bg/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/bn/LC_MESSAGES/phpmyadmin.mo b/locale/bn/LC_MESSAGES/phpmyadmin.mo
index 947a69f581..b0ee39ab3e 100644
--- a/locale/bn/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/bn/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/ca/LC_MESSAGES/phpmyadmin.mo b/locale/ca/LC_MESSAGES/phpmyadmin.mo
index b5798f3619..d6d8fd4b6d 100644
--- a/locale/ca/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/ca/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/cs/LC_MESSAGES/phpmyadmin.mo b/locale/cs/LC_MESSAGES/phpmyadmin.mo
index 01e55b45f5..f11b3b755a 100644
--- a/locale/cs/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/cs/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/da/LC_MESSAGES/phpmyadmin.mo b/locale/da/LC_MESSAGES/phpmyadmin.mo
index beef545d8d..dfe90070de 100644
--- a/locale/da/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/da/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/de/LC_MESSAGES/phpmyadmin.mo b/locale/de/LC_MESSAGES/phpmyadmin.mo
index a0a954480c..a3b119df58 100644
--- a/locale/de/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/de/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/el/LC_MESSAGES/phpmyadmin.mo b/locale/el/LC_MESSAGES/phpmyadmin.mo
index f6ea3c4f22..9f698478f1 100644
--- a/locale/el/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/el/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/en_GB/LC_MESSAGES/phpmyadmin.mo b/locale/en_GB/LC_MESSAGES/phpmyadmin.mo
index 69ae068c8d..7d68b5b6c8 100644
--- a/locale/en_GB/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/en_GB/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/es/LC_MESSAGES/phpmyadmin.mo b/locale/es/LC_MESSAGES/phpmyadmin.mo
index 1c243a2aa1..7252cec84e 100644
--- a/locale/es/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/es/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/et/LC_MESSAGES/phpmyadmin.mo b/locale/et/LC_MESSAGES/phpmyadmin.mo
index d53a720b1b..e206c12e30 100644
--- a/locale/et/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/et/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/fi/LC_MESSAGES/phpmyadmin.mo b/locale/fi/LC_MESSAGES/phpmyadmin.mo
index 0b9e07711a..cc5ab2f3b7 100644
--- a/locale/fi/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/fi/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/fr/LC_MESSAGES/phpmyadmin.mo b/locale/fr/LC_MESSAGES/phpmyadmin.mo
index dca5241371..3bb10ecb8f 100644
--- a/locale/fr/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/fr/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/gl/LC_MESSAGES/phpmyadmin.mo b/locale/gl/LC_MESSAGES/phpmyadmin.mo
index c104bba41e..9f5cd095bd 100644
--- a/locale/gl/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/gl/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/hi/LC_MESSAGES/phpmyadmin.mo b/locale/hi/LC_MESSAGES/phpmyadmin.mo
deleted file mode 100644
index e88b5cb5f2..0000000000
--- a/locale/hi/LC_MESSAGES/phpmyadmin.mo
+++ /dev/null
Binary files differ
diff --git a/locale/hu/LC_MESSAGES/phpmyadmin.mo b/locale/hu/LC_MESSAGES/phpmyadmin.mo
index 9f4ad1ea09..5d7564af07 100644
--- a/locale/hu/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/hu/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/hy/LC_MESSAGES/phpmyadmin.mo b/locale/hy/LC_MESSAGES/phpmyadmin.mo
index f6accf5617..358efcf5af 100644
--- a/locale/hy/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/hy/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/ia/LC_MESSAGES/phpmyadmin.mo b/locale/ia/LC_MESSAGES/phpmyadmin.mo
index 029508f179..b554491520 100644
--- a/locale/ia/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/ia/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/id/LC_MESSAGES/phpmyadmin.mo b/locale/id/LC_MESSAGES/phpmyadmin.mo
index ab42885066..710184bff8 100644
--- a/locale/id/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/id/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/it/LC_MESSAGES/phpmyadmin.mo b/locale/it/LC_MESSAGES/phpmyadmin.mo
index a630cf901f..ebed0cc5cb 100644
--- a/locale/it/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/it/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/ja/LC_MESSAGES/phpmyadmin.mo b/locale/ja/LC_MESSAGES/phpmyadmin.mo
index e539ffc8e4..cabde5277c 100644
--- a/locale/ja/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/ja/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/ko/LC_MESSAGES/phpmyadmin.mo b/locale/ko/LC_MESSAGES/phpmyadmin.mo
index 99648ec8ed..abec258674 100644
--- a/locale/ko/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/ko/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/lt/LC_MESSAGES/phpmyadmin.mo b/locale/lt/LC_MESSAGES/phpmyadmin.mo
index b6ab4dc79b..da371f63ac 100644
--- a/locale/lt/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/lt/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/nb/LC_MESSAGES/phpmyadmin.mo b/locale/nb/LC_MESSAGES/phpmyadmin.mo
index bd8e33081d..27bb62441b 100644
--- a/locale/nb/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/nb/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/nl/LC_MESSAGES/phpmyadmin.mo b/locale/nl/LC_MESSAGES/phpmyadmin.mo
index 8cfa9b3d26..2bd96342d9 100644
--- a/locale/nl/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/nl/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/pl/LC_MESSAGES/phpmyadmin.mo b/locale/pl/LC_MESSAGES/phpmyadmin.mo
index 62fba5895a..b145fbe05b 100644
--- a/locale/pl/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/pl/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/pt/LC_MESSAGES/phpmyadmin.mo b/locale/pt/LC_MESSAGES/phpmyadmin.mo
index 1eb8e12706..03b62cba1d 100644
--- a/locale/pt/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/pt/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/pt_BR/LC_MESSAGES/phpmyadmin.mo b/locale/pt_BR/LC_MESSAGES/phpmyadmin.mo
index 3c0ec815a4..c065015e03 100644
--- a/locale/pt_BR/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/pt_BR/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/ro/LC_MESSAGES/phpmyadmin.mo b/locale/ro/LC_MESSAGES/phpmyadmin.mo
index 11b5cf356f..90a9aafb72 100644
--- a/locale/ro/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/ro/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/ru/LC_MESSAGES/phpmyadmin.mo b/locale/ru/LC_MESSAGES/phpmyadmin.mo
index 0e1c280d39..b4e8d5ea17 100644
--- a/locale/ru/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/ru/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/si/LC_MESSAGES/phpmyadmin.mo b/locale/si/LC_MESSAGES/phpmyadmin.mo
index 4c376d6c45..665e31ebce 100644
--- a/locale/si/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/si/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/sk/LC_MESSAGES/phpmyadmin.mo b/locale/sk/LC_MESSAGES/phpmyadmin.mo
index 32a1cccfc4..d858f69205 100644
--- a/locale/sk/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/sk/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/sl/LC_MESSAGES/phpmyadmin.mo b/locale/sl/LC_MESSAGES/phpmyadmin.mo
index 2a7629a3b7..7650f57188 100644
--- a/locale/sl/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/sl/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/sq/LC_MESSAGES/phpmyadmin.mo b/locale/sq/LC_MESSAGES/phpmyadmin.mo
index 0103363208..2c987ee2e2 100644
--- a/locale/sq/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/sq/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/sr@latin/LC_MESSAGES/phpmyadmin.mo b/locale/sr@latin/LC_MESSAGES/phpmyadmin.mo
index 0ea1910560..374d631f19 100644
--- a/locale/sr@latin/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/sr@latin/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/sv/LC_MESSAGES/phpmyadmin.mo b/locale/sv/LC_MESSAGES/phpmyadmin.mo
index 31c3f83ef1..d7a99dd487 100644
--- a/locale/sv/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/sv/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/tr/LC_MESSAGES/phpmyadmin.mo b/locale/tr/LC_MESSAGES/phpmyadmin.mo
index 45fd317798..a4155663e5 100644
--- a/locale/tr/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/tr/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/uk/LC_MESSAGES/phpmyadmin.mo b/locale/uk/LC_MESSAGES/phpmyadmin.mo
index 6bd9f3401b..57396350a6 100644
--- a/locale/uk/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/uk/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/zh_CN/LC_MESSAGES/phpmyadmin.mo b/locale/zh_CN/LC_MESSAGES/phpmyadmin.mo
index 51be8b859e..5f50a92bc8 100644
--- a/locale/zh_CN/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/zh_CN/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/locale/zh_TW/LC_MESSAGES/phpmyadmin.mo b/locale/zh_TW/LC_MESSAGES/phpmyadmin.mo
index 258bc414e7..0d1a37cd58 100644
--- a/locale/zh_TW/LC_MESSAGES/phpmyadmin.mo
+++ b/locale/zh_TW/LC_MESSAGES/phpmyadmin.mo
Binary files differ
diff --git a/navigation.php b/navigation.php
index 2b1b85a5d2..8aeb2156a7 100644
--- a/navigation.php
+++ b/navigation.php
@@ -23,8 +23,13 @@ if (! $response->isAjax()) {
exit;
}
+if (isset($_REQUEST['getNaviSettings']) && $_REQUEST['getNaviSettings']) {
+ $response->addJSON('message', PMA_PageSettings::getNaviSettings());
+ exit();
+}
+
$cfgRelation = PMA_getRelationsParam();
-if (isset($cfgRelation['navwork']) && $cfgRelation['navwork']) {
+if ($cfgRelation['navwork']) {
if (isset($_REQUEST['hideNavItem'])) {
if (! empty($_REQUEST['itemName'])
&& ! empty($_REQUEST['itemType'])
@@ -68,4 +73,3 @@ if (isset($cfgRelation['navwork']) && $cfgRelation['navwork']) {
// Do the magic
$response->addJSON('message', $navigation->getDisplay());
-?>
diff --git a/normalization.php b/normalization.php
index c7f7229013..a988935c95 100644
--- a/normalization.php
+++ b/normalization.php
@@ -12,7 +12,6 @@
require_once 'libraries/common.inc.php';
require_once 'libraries/transformations.lib.php';
require_once 'libraries/normalization.lib.php';
-require_once 'libraries/tbl_columns_definition_form.lib.php';
require_once 'libraries/Index.class.php';
if (isset($_REQUEST['getColumns'])) {
diff --git a/phpinfo.php b/phpinfo.php
index 5854ff4c9e..283f701aa6 100644
--- a/phpinfo.php
+++ b/phpinfo.php
@@ -18,4 +18,3 @@ PMA_Response::getInstance()->disable();
if ($GLOBALS['cfg']['ShowPhpInfo']) {
phpinfo();
}
-?>
diff --git a/phpmyadmin.css.php b/phpmyadmin.css.php
index 050953e764..e3a7348539 100644
--- a/phpmyadmin.css.php
+++ b/phpmyadmin.css.php
@@ -23,9 +23,11 @@ if (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER == '6'
include_once 'libraries/OutputBuffering.class.php';
$buffer = PMA_OutputBuffering::getInstance();
$buffer->start();
- register_shutdown_function(function() {
- echo PMA_OutputBuffering::getInstance()->getContents();
- });
+ register_shutdown_function(
+ function () {
+ echo PMA_OutputBuffering::getInstance()->getContents();
+ }
+ );
}
// Send correct type:
@@ -36,4 +38,3 @@ header('Content-Type: text/css; charset=UTF-8');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
$_SESSION['PMA_Theme_Manager']->printCss();
-?>
diff --git a/prefs_forms.php b/prefs_forms.php
index d0c09b0b61..68b7274ab0 100644
--- a/prefs_forms.php
+++ b/prefs_forms.php
@@ -23,7 +23,7 @@ PMA_userprefsPageInit($cf);
// handle form processing
-$form_param = filter_input(INPUT_GET, 'form');
+$form_param = isset($_GET['form']) ? $_GET['form'] : null;
if (! isset($forms[$form_param])) {
$forms_keys = array_keys($forms);
$form_param = array_shift($forms_keys);
@@ -57,7 +57,8 @@ if ($form_display->process(false) && !$form_display->hasErrors()) {
if ($result === true) {
// reload config
$GLOBALS['PMA_Config']->loadUserPreferences();
- $hash = ltrim(filter_input(INPUT_POST, 'tab_hash'), '#');
+ $tabHash = isset($_POST['tab_hash']) ? $_POST['tab_hash'] : null;
+ $hash = ltrim($tabHash, '#');
PMA_userprefsRedirect(
'prefs_forms.php',
array('form' => $form_param),
@@ -83,10 +84,17 @@ if ($form_display->hasErrors()) {
// form has errors
?>
<div class="error config-form">
- <b><?php echo __('Cannot save settings, submitted form contains errors!') ?></b>
- <?php $form_display->displayErrors(); ?>
+ <b>
+ <?php echo __('Cannot save settings, submitted form contains errors!') ?>
+ </b>
+ <?php echo $form_display->displayErrors(); ?>
</div>
<?php
}
-$form_display->display(true, true);
-?>
+echo $form_display->getDisplay(true, true);
+
+if ($response->isAjax()) {
+ $response->addJSON('_disableNaviSettings', true);
+} else {
+ define('PMA_DISABLE_NAVI_SETTINGS', true);
+}
diff --git a/prefs_manage.php b/prefs_manage.php
index 3eb10a36e7..a6b2bcdd9b 100644
--- a/prefs_manage.php
+++ b/prefs_manage.php
@@ -23,7 +23,8 @@ PMA_userprefsPageInit($cf);
$error = '';
if (isset($_POST['submit_export'])
- && filter_input(INPUT_POST, 'export_type') == 'text_file'
+ && isset($_POST['export_type'])
+ && $_POST['export_type'] == 'text_file'
) {
// export to JSON file
PMA_Response::getInstance()->disable();
@@ -41,7 +42,8 @@ if (isset($_POST['submit_export'])
} else if (isset($_POST['submit_import'])) {
// load from JSON file
$json = '';
- if (filter_input(INPUT_POST, 'import_type') == 'text_file'
+ if (isset($_POST['import_type'])
+ && $_POST['import_type'] == 'text_file'
&& isset($_FILES['import_file'])
&& $_FILES['import_file']['error'] == UPLOAD_ERR_OK
&& is_uploaded_file($_FILES['import_file']['tmp_name'])
@@ -70,14 +72,14 @@ if (isset($_POST['submit_export'])
}
} else {
// read from POST value (json)
- $json = filter_input(INPUT_POST, 'json');
+ $json = isset($_POST['json']) ? $_POST['json'] : null;
}
// hide header message
$_SESSION['userprefs_autoload'] = true;
$config = json_decode($json, true);
- $return_url = filter_input(INPUT_POST, 'return_url');
+ $return_url = isset($_POST['return_url']) ? $_POST['return_url'] : null;
if (! is_array($config)) {
$error = __('Could not import configuration');
} else {
@@ -115,7 +117,7 @@ if (isset($_POST['submit_export'])
);
$msg->display();
echo '<div class="config-form">';
- $form_display->displayErrors();
+ echo $form_display->displayErrors();
echo '</div>';
echo '<form action="prefs_manage.php" method="post">';
echo PMA_URL_getHiddenInputs() . "\n";
@@ -181,7 +183,7 @@ if (isset($_POST['submit_export'])
if ($k == 'token') {
continue;
}
- $params[$k] = /*overload*/mb_substr($q, $pos+1);
+ $params[$k] = /*overload*/mb_substr($q, $pos + 1);
}
} else {
$return_url = 'prefs_manage.php';
@@ -373,3 +375,10 @@ if (file_exists('setup/index.php')) {
</div>
<br class="clearfloat" />
</div>
+
+<?php
+if ($response->isAjax()) {
+ $response->addJSON('_disableNaviSettings', true);
+} else {
+ define('PMA_DISABLE_NAVI_SETTINGS', true);
+}
diff --git a/schema_export.php b/schema_export.php
index 9573b2ac7f..ec1c4e0b54 100644
--- a/schema_export.php
+++ b/schema_export.php
@@ -23,20 +23,9 @@ require_once 'libraries/pmd_common.php';
require_once 'libraries/plugin_interface.lib.php';
/**
- * get all the export options and verify
- * call and include the appropriate Schema Class depending on $export_type
+ * Include the appropriate Schema Class depending on $export_type
* default is PDF
*/
-
-$post_params = array(
- 'db'
-);
-foreach ($post_params as $one_post_param) {
- if (isset($_REQUEST[$one_post_param])) {
- $GLOBALS[$one_post_param] = $_REQUEST[$one_post_param];
- }
-}
-
PMA_processExportSchema($_REQUEST['export_type']);
/**
@@ -60,6 +49,7 @@ function PMA_processExportSchema($export_type)
$export_type = PMA_securePath($export_type);
// get the specific plugin
+ /* @var $export_plugin SchemaPlugin */
$export_plugin = PMA_getPlugin(
"schema",
$export_type,
@@ -74,4 +64,3 @@ function PMA_processExportSchema($export_type)
$GLOBALS['dbi']->selectDb($GLOBALS['db']);
$export_plugin->exportSchema($GLOBALS['db']);
}
-?>
diff --git a/server_binlog.php b/server_binlog.php
index 1ff1924267..4d07e7ace4 100644
--- a/server_binlog.php
+++ b/server_binlog.php
@@ -50,5 +50,3 @@ $response->addHTML(PMA_getLogSelector($binary_logs, $url_params));
$response->addHTML(PMA_getLogInfo($url_params));
exit;
-
-?>
diff --git a/server_collations.php b/server_collations.php
index b1b9c71a09..714319f51f 100644
--- a/server_collations.php
+++ b/server_collations.php
@@ -35,5 +35,3 @@ $response->addHTML(
$mysql_collations_available
)
);
-
-?>
diff --git a/server_databases.php b/server_databases.php
index 8e9cffdc4b..ea83ad3784 100644
--- a/server_databases.php
+++ b/server_databases.php
@@ -114,5 +114,3 @@ if ($databases_count > 0) {
unset($databases_count);
$response->addHTML($html);
-
-?>
diff --git a/server_engines.php b/server_engines.php
index 12320498a5..2dff2dfa25 100644
--- a/server_engines.php
+++ b/server_engines.php
@@ -30,5 +30,3 @@ $response->addHTML(PMA_getHtmlForSubPageHeader('engines'));
$response->addHTML(PMA_getHtmlForServerEngines());
exit;
-
-?>
diff --git a/server_export.php b/server_export.php
index c0bffdb3e1..5888f80610 100644
--- a/server_export.php
+++ b/server_export.php
@@ -12,6 +12,9 @@
require_once 'libraries/common.inc.php';
require_once 'libraries/server_common.inc.php';
require_once 'libraries/display_export.lib.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Export');
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -25,5 +28,3 @@ $multi_values = PMA_getHtmlForExportSelectOptions($select_item);
$export_type = 'server';
require_once 'libraries/display_export.inc.php';
-
-?>
diff --git a/server_import.php b/server_import.php
index 83d27cf7c1..675882e757 100644
--- a/server_import.php
+++ b/server_import.php
@@ -10,6 +10,9 @@
*
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Import');
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -21,7 +24,10 @@ $scripts->addFile('import.js');
*/
require 'libraries/server_common.inc.php';
-$import_type = 'server';
-require 'libraries/display_import.inc.php';
-
-?>
+require 'libraries/display_import.lib.php';
+$response = PMA_Response::getInstance();
+$response->addHTML(
+ PMA_getImportDisplay(
+ 'server', $db, $table, $max_upload_size
+ )
+);
diff --git a/server_modules.php b/server_modules.php
new file mode 100644
index 0000000000..b167b9f133
--- /dev/null
+++ b/server_modules.php
@@ -0,0 +1,31 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * object the server modules page
+ *
+ * @package PhpMyAdmin
+ */
+
+/**
+ * requirements
+ */
+require_once 'libraries/common.inc.php';
+
+/**
+ * Does the common work
+ */
+require 'libraries/server_common.inc.php';
+require 'libraries/server_plugins.lib.php';
+
+$modules = PMA_getServerModules();
+
+/**
+ * Displays the page
+ */
+$response = PMA_Response::getInstance();
+$response->addHTML('<div>');
+$response->addHTML(PMA_getHtmlForPluginsSubTabs('server_modules.php'));
+$response->addHTML(PMA_getModuleTab($modules));
+$response->addHTML('</div>');
+
+exit;
diff --git a/server_plugins.php b/server_plugins.php
index 089bfd1d7f..11654b8f8d 100644
--- a/server_plugins.php
+++ b/server_plugins.php
@@ -26,34 +26,14 @@ $scripts->addFile('server_plugins.js');
require 'libraries/server_common.inc.php';
require 'libraries/server_plugins.lib.php';
-/**
- * Prepare plugin list
- */
-$sql = "SELECT p.plugin_name, p.plugin_type, p.is_active, m.module_name,
- m.module_library, m.module_version, m.module_author,
- m.module_description, m.module_license
- FROM data_dictionary.plugins p
- JOIN data_dictionary.modules m USING (module_name)
- ORDER BY m.module_name, p.plugin_type, p.plugin_name";
-$res = $GLOBALS['dbi']->query($sql);
-$plugins = array();
-$modules = array();
-while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
- $plugins[$row['plugin_type']][] = $row;
- $modules[$row['module_name']]['info'] = $row;
- $modules[$row['module_name']]['plugins'][$row['plugin_type']][] = $row;
-}
-$GLOBALS['dbi']->freeResult($res);
-
-// sort plugin list (modules are already sorted)
-ksort($plugins);
+$plugins = PMA_getServerPlugins();
/**
* Displays the page
*/
-$response->addHTML(PMA_getHtmlForSubPageHeader('plugins'));
-$response->addHTML(PMA_getPluginAndModuleInfo($plugins, $modules));
+$response->addHTML('<div>');
+$response->addHTML(PMA_getHtmlForPluginsSubTabs('server_plugins.php'));
+$response->addHTML(PMA_getPluginTab($plugins));
+$response->addHTML('</div>');
exit;
-
-?>
diff --git a/server_privileges.php b/server_privileges.php
index 2db8f91ce7..a08f159914 100644
--- a/server_privileges.php
+++ b/server_privileges.php
@@ -29,7 +29,6 @@ $scripts->addFile('server_privileges.js');
if ((isset($_REQUEST['viewing_mode'])
&& $_REQUEST['viewing_mode'] == 'server')
- && isset($GLOBALS['cfgRelation']['menuswork'])
&& $GLOBALS['cfgRelation']['menuswork']
) {
include_once 'libraries/server_users.lib.php';
@@ -242,6 +241,7 @@ if (isset($_REQUEST['change_pw'])) {
if (isset($_REQUEST['delete'])
|| (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)
) {
+ include_once 'libraries/relation_cleanup.lib.php';
$queries = PMA_getDataForDeleteUsers($queries);
if (empty($_REQUEST['change_copy'])) {
list($sql_query, $message) = PMA_deleteUser($queries);
@@ -308,7 +308,19 @@ if (isset($_REQUEST['viewing_mode']) && $_REQUEST['viewing_mode'] == 'db') {
// Gets the database structure
$sub_part = '_structure';
ob_start();
- include 'libraries/db_info.inc.php';
+
+ list(
+ $tables,
+ $num_tables,
+ $total_num_tables,
+ $sub_part,
+ $is_show_stats,
+ $db_is_system_schema,
+ $tooltip_truename,
+ $tooltip_aliasname,
+ $pos
+ ) = PMA_Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
+
$content = ob_get_contents();
ob_end_clean();
$response->addHTML($content . "\n");
@@ -406,5 +418,3 @@ if ((isset($_REQUEST['viewing_mode']) && $_REQUEST['viewing_mode'] == 'server')
) {
$response->addHTML('</div>');
}
-
-?>
diff --git a/server_replication.php b/server_replication.php
index 3197cbd0bf..93e4100d19 100644
--- a/server_replication.php
+++ b/server_replication.php
@@ -80,4 +80,3 @@ if (! isset($_REQUEST['repl_clear_scr'])) {
if (isset($_REQUEST['sl_configure'])) {
$response->addHTML(PMA_getHtmlForReplicationChangeMaster("slave_changemaster"));
}
-?>
diff --git a/server_sql.php b/server_sql.php
index 953e17587d..1d53a74a43 100644
--- a/server_sql.php
+++ b/server_sql.php
@@ -10,6 +10,9 @@
*
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Sql_queries');
/**
* Does the common work
@@ -28,5 +31,3 @@ require_once 'libraries/sql_query_form.lib.php';
* Query box, bookmark, insert data from textfile
*/
$response->addHTML(PMA_getHtmlForSqlQueryForm());
-
-?>
diff --git a/server_status.php b/server_status.php
index 9eb4d52e84..a69b84c84f 100644
--- a/server_status.php
+++ b/server_status.php
@@ -23,16 +23,22 @@ if (PMA_DRIZZLE) {
include_once 'libraries/replication_gui.lib.php';
}
-$ServerStatusData = new PMA_ServerStatusData();
-
/**
* start output
*/
$response = PMA_Response::getInstance();
$response->addHTML('<div>');
-$response->addHTML($ServerStatusData->getMenuHtml());
-$response->addHTML(PMA_getHtmlForServerStatus($ServerStatusData));
-$response->addHTML('</div>');
+$serverStatusData = new PMA_ServerStatusData();
+$response->addHTML($serverStatusData->getMenuHtml());
+if ($serverStatusData->dataLoaded) {
+ $response->addHTML(PMA_getHtmlForServerStatus($serverStatusData));
+} else {
+ $response->addHTML(
+ PMA_Message::error(
+ __('Not enough privilege to view server status.')
+ )->getDisplay()
+ );
+}
+$response->addHTML('</div>');
exit;
-?>
diff --git a/server_status_advisor.php b/server_status_advisor.php
index 4ab2ed60bc..eb2e57c86b 100644
--- a/server_status_advisor.php
+++ b/server_status_advisor.php
@@ -20,7 +20,7 @@ if (PMA_DRIZZLE) {
include_once 'libraries/replication_gui.lib.php';
}
-$ServerStatusData = new PMA_ServerStatusData();
+$serverStatusData = new PMA_ServerStatusData();
$response = PMA_Response::getInstance();
$scripts = $response->getHeader()->getScripts();
@@ -30,10 +30,16 @@ $scripts->addFile('server_status_advisor.js');
* Output
*/
$response->addHTML('<div>');
-$response->addHTML($ServerStatusData->getMenuHtml());
-$response->addHTML(PMA_getHtmlForAdvisor());
+$response->addHTML($serverStatusData->getMenuHtml());
+if ($serverStatusData->dataLoaded) {
+ $response->addHTML(PMA_getHtmlForAdvisor());
+} else {
+ $response->addHTML(
+ PMA_Message::error(
+ __('Not enough privilege to view the advisor.')
+ )->getDisplay()
+ );
+}
$response->addHTML('</div>');
exit;
-
-?>
diff --git a/server_status_monitor.php b/server_status_monitor.php
index 82010f3cc7..9af3f71e43 100644
--- a/server_status_monitor.php
+++ b/server_status_monitor.php
@@ -109,5 +109,3 @@ $response->addHTML(PMA_getHtmlForMonitor($ServerStatusData));
$response->addHTML(PMA_getHtmlForClientSideDataAndLinks($ServerStatusData));
$response->addHTML('</div>');
exit;
-
-?>
diff --git a/server_status_processes.php b/server_status_processes.php
index f5dfb3c266..015bd00d38 100644
--- a/server_status_processes.php
+++ b/server_status_processes.php
@@ -56,9 +56,9 @@ if ($response->isAjax() && !empty($_REQUEST['kill'])) {
$scripts->addFile('server_status_processes.js');
$response->addHTML('<div>');
$response->addHTML($ServerStatusData->getMenuHtml());
- $response->addHTML(PMA_getHtmlForServerProcesses());
$response->addHTML(PMA_getHtmlForProcessListFilter());
+ $response->addHTML(PMA_getHtmlForServerProcesslist());
+ $response->addHTML(PMA_getHtmlForProcessListAutoRefresh());
$response->addHTML('</div>');
}
exit;
-?>
diff --git a/server_status_queries.php b/server_status_queries.php
index 644774cfaa..99a83b7f05 100644
--- a/server_status_queries.php
+++ b/server_status_queries.php
@@ -21,7 +21,7 @@ if (PMA_DRIZZLE) {
include_once 'libraries/replication_gui.lib.php';
}
-$ServerStatusData = new PMA_ServerStatusData();
+$serverStatusData = new PMA_ServerStatusData();
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -46,9 +46,15 @@ $scripts->addFile('server_status_sorter.js');
// Add the html content to the response
$response->addHTML('<div>');
-$response->addHTML($ServerStatusData->getMenuHtml());
-$response->addHTML(PMA_getHtmlForQueryStatistics($ServerStatusData));
+$response->addHTML($serverStatusData->getMenuHtml());
+if ($serverStatusData->dataLoaded) {
+ $response->addHTML(PMA_getHtmlForQueryStatistics($serverStatusData));
+} else {
+ $response->addHTML(
+ PMA_Message::error(
+ __('Not enough privilege to view query statistics.')
+ )->getDisplay()
+ );
+}
$response->addHTML('</div>');
exit;
-
-?>
diff --git a/server_status_variables.php b/server_status_variables.php
index cfa108ab3d..735cc3aea6 100644
--- a/server_status_variables.php
+++ b/server_status_variables.php
@@ -36,7 +36,7 @@ if (isset($_REQUEST['flush'])) {
unset($_flush_commands);
}
-$ServerStatusData = new PMA_ServerStatusData();
+$serverStatusData = new PMA_ServerStatusData();
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -46,12 +46,18 @@ $scripts->addFile('jquery/jquery.tablesorter.js');
$scripts->addFile('server_status_sorter.js');
$response->addHTML('<div>');
-$response->addHTML($ServerStatusData->getMenuHtml());
-$response->addHTML(PMA_getHtmlForFilter($ServerStatusData));
-$response->addHTML(PMA_getHtmlForLinkSuggestions($ServerStatusData));
-$response->addHTML(PMA_getHtmlForVariablesList($ServerStatusData));
+$response->addHTML($serverStatusData->getMenuHtml());
+if ($serverStatusData->dataLoaded) {
+ $response->addHTML(PMA_getHtmlForFilter($serverStatusData));
+ $response->addHTML(PMA_getHtmlForLinkSuggestions($serverStatusData));
+ $response->addHTML(PMA_getHtmlForVariablesList($serverStatusData));
+} else {
+ $response->addHTML(
+ PMA_Message::error(
+ __('Not enough privilege to view status variables.')
+ )->getDisplay()
+ );
+}
$response->addHTML('</div>');
exit;
-
-?>
diff --git a/server_user_groups.php b/server_user_groups.php
index c9e9589527..94fc0f9bf8 100644
--- a/server_user_groups.php
+++ b/server_user_groups.php
@@ -69,4 +69,3 @@ if (isset($_REQUEST['addUserGroup'])) {
}
$response->addHTML('</div>');
-?>
diff --git a/server_variables.php b/server_variables.php
index b287777206..7c78db81aa 100644
--- a/server_variables.php
+++ b/server_variables.php
@@ -46,15 +46,49 @@ $doc_link = PMA_Util::showMySQLDocu('server_system_variables');
$response->addHtml(PMA_getHtmlForSubPageHeader('variables', $doc_link));
/**
- * Link templates
+ * Sends the queries and buffers the results
*/
-$response->addHtml(PMA_getHtmlForLinkTemplates());
+$serverVarsResult = $GLOBALS['dbi']->tryQuery('SHOW SESSION VARIABLES;');
-/**
- * Displays the page
- */
-$response->addHtml(PMA_getHtmlForServerVariables($variable_doc_links));
+if ($serverVarsResult !== false) {
-exit;
+ $serverVarsSession = array();
+ while ($arr = $GLOBALS['dbi']->fetchRow($serverVarsResult)) {
+ $serverVarsSession[$arr[0]] = $arr[1];
+ }
+ $GLOBALS['dbi']->freeResult($serverVarsResult);
+
+ $serverVars = $GLOBALS['dbi']->fetchResult('SHOW GLOBAL VARIABLES;', 0, 1);
-?>
+ /**
+ * Link templates
+ */
+ $response->addHtml(PMA_getHtmlForLinkTemplates());
+
+ /**
+ * Displays the page
+ */
+ $response->addHtml(
+ PMA_getHtmlForServerVariables(
+ $variable_doc_links, $serverVars, $serverVarsSession
+ )
+ );
+} else {
+ /**
+ * Display the error message
+ */
+ $response->addHTML(
+ PMA_Message::error(
+ sprintf(
+ __('Not enough privilege to view server variables and settings. %s'),
+ PMA_Util::showMySQLDocu(
+ 'server-system-variables',
+ false,
+ 'sysvar_show_compatibility_56'
+ )
+ )
+ )->getDisplay()
+ );
+}
+
+exit;
diff --git a/show_config_errors.php b/show_config_errors.php
index 0d0cdf4456..8cd1de5efa 100644
--- a/show_config_errors.php
+++ b/show_config_errors.php
@@ -37,4 +37,3 @@ error_reporting(E_ALL);
if (is_readable(CONFIG_FILE)) {
include CONFIG_FILE;
}
-?>
diff --git a/sql.php b/sql.php
index 425b8359c4..e834f87ff8 100644
--- a/sql.php
+++ b/sql.php
@@ -17,7 +17,10 @@ require_once 'libraries/Header.class.php';
require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/bookmark.lib.php';
require_once 'libraries/sql.lib.php';
-require_once 'libraries/sqlparser.lib.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Browse');
+
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -50,9 +53,13 @@ if (! empty($goto)) {
}
} else {
if (empty($table)) {
- $goto = $cfg['DefaultTabDatabase'];
+ $goto = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ );
} else {
- $goto = $cfg['DefaultTabTable'];
+ $goto = PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabTable'], 'table'
+ );
}
$is_gotofile = true;
} // end if
@@ -101,6 +108,16 @@ if (isset($_REQUEST['get_set_values']) && $_REQUEST['get_set_values'] == true) {
// script has exited at this point
}
+if (isset($_REQUEST['get_default_fk_check_value'])
+ && $_REQUEST['get_default_fk_check_value'] == true
+) {
+ $response = PMA_Response::getInstance();
+ $response->addJSON(
+ 'default_fk_check_value', PMA_Util::isForeignKeyCheck()
+ );
+ exit;
+}
+
/**
* Check ajax request to set the column order and visibility
*/
@@ -179,25 +196,22 @@ if ($goto == 'sql.php') {
} // end if
PMA_executeQueryAndSendQueryResponse(
- $analyzed_sql_results,
- $is_gotofile,
- $db,
- $table,
- isset($find_real_end) ? $find_real_end : null,
- isset($import_text) ? $import_text : null,
- isset($extra_data) ? $extra_data : null,
- $is_affected,
- isset($message_to_show) ? $message_to_show : null,
- isset($message) ? $message : null,
- isset($sql_data) ? $sql_data : null,
- $goto,
- $pmaThemeImage,
- isset($disp_query) ? $display_query : null,
- isset($disp_message) ? $disp_message : null,
- isset($query_type) ? $query_type : null,
- $sql_query,
- isset($selected) ? $selected : null,
- isset($complete_query) ? $complete_query : null
+ $analyzed_sql_results, // analyzed_sql_results
+ $is_gotofile, // is_gotofile
+ $db, // db
+ $table, // table
+ isset($find_real_end) ? $find_real_end : null, // find_real_end
+ isset($import_text) ? $import_text : null, // sql_query_for_bookmark
+ isset($extra_data) ? $extra_data : null, // extra_data
+ isset($message_to_show) ? $message_to_show : null, // message_to_show
+ isset($message) ? $message : null, // message
+ isset($sql_data) ? $sql_data : null, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ isset($disp_query) ? $display_query : null, // disp_query
+ isset($disp_message) ? $disp_message : null, // disp_message
+ isset($query_type) ? $query_type : null, // query_type
+ $sql_query, // sql_query
+ isset($selected) ? $selected : null, // selectedTables
+ isset($complete_query) ? $complete_query : null // complete_query
);
-
-?>
diff --git a/sql/create_tables.sql b/sql/create_tables.sql
index e11bf019b6..f906115fbe 100644
--- a/sql/create_tables.sql
+++ b/sql/create_tables.sql
@@ -81,7 +81,7 @@ CREATE TABLE IF NOT EXISTS `pma__history` (
`username` varchar(64) NOT NULL default '',
`db` varchar(64) NOT NULL default '',
`table` varchar(64) NOT NULL default '',
- `timevalue` timestamp NOT NULL,
+ `timevalue` timestamp NOT NULL default CURRENT_TIMESTAMP,
`sqlquery` text NOT NULL,
PRIMARY KEY (`id`),
KEY `username` (`username`,`db`,`table`,`timevalue`)
@@ -231,7 +231,7 @@ CREATE TABLE IF NOT EXISTS `pma__tracking` (
CREATE TABLE IF NOT EXISTS `pma__userconfig` (
`username` varchar(64) NOT NULL,
- `timevalue` timestamp NOT NULL,
+ `timevalue` timestamp NOT NULL default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`config_data` text NOT NULL,
PRIMARY KEY (`username`)
)
@@ -321,3 +321,35 @@ CREATE TABLE IF NOT EXISTS `pma__central_columns` (
)
COMMENT='Central list of columns'
DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `pma__designer_settings`
+--
+
+CREATE TABLE IF NOT EXISTS `pma__designer_settings` (
+ `username` varchar(64) NOT NULL,
+ `settings_data` text NOT NULL,
+ PRIMARY KEY (`username`)
+)
+ COMMENT='Settings related to Designer'
+ DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `pma__export_templates`
+--
+
+CREATE TABLE IF NOT EXISTS `pma__export_templates` (
+ `id` int(5) unsigned NOT NULL AUTO_INCREMENT,
+ `username` varchar(64) NOT NULL,
+ `export_type` varchar(10) NOT NULL,
+ `template_name` varchar(64) NOT NULL,
+ `template_data` text NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `u_user_type_template` (`username`,`export_type`,`template_name`)
+)
+ COMMENT='Saved export templates'
+ DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
diff --git a/sql/create_tables_drizzle.sql b/sql/create_tables_drizzle.sql
index 12248a5dc1..c4e523ac6f 100644
--- a/sql/create_tables_drizzle.sql
+++ b/sql/create_tables_drizzle.sql
@@ -273,3 +273,35 @@ CREATE TABLE IF NOT EXISTS `pma__savedsearches` (
)
COMMENT='Saved searches'
COLLATE utf8_bin;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `pma__designer_settings`
+--
+
+CREATE TABLE IF NOT EXISTS `pma__designer_settings` (
+ `username` varchar(64) NOT NULL,
+ `settings_data` text NOT NULL,
+ PRIMARY KEY (`username`)
+)
+ COMMENT='Settings related to Designer'
+ COLLATE utf8_bin;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `pma__export_templates`
+--
+
+CREATE TABLE IF NOT EXISTS `pma__export_templates` (
+ `id` int(5) unsigned NOT NULL AUTO_INCREMENT,
+ `username` varchar(64) NOT NULL,
+ `export_type` varchar(10) NOT NULL,
+ `template_name` varchar(64) NOT NULL,
+ `template_data` text NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `u_user_type_template` (`username`,`export_type`,`template_name`)
+)
+ COMMENT='Saved export templates'
+ COLLATE utf8_bin; \ No newline at end of file
diff --git a/tbl_addfield.php b/tbl_addfield.php
index 0c7aa1da2f..9bdc8bd347 100644
--- a/tbl_addfield.php
+++ b/tbl_addfield.php
@@ -109,7 +109,7 @@ if (isset($_REQUEST['do_save_data'])) {
*/
if ($abort == false) {
/**
- * Gets tables informations
+ * Gets tables information
*/
include_once 'libraries/tbl_common.inc.php';
include_once 'libraries/tbl_info.inc.php';
@@ -121,4 +121,3 @@ if ($abort == false) {
$action = 'tbl_addfield.php';
include_once 'libraries/tbl_columns_definition_form.inc.php';
}
-?>
diff --git a/tbl_change.php b/tbl_change.php
index 7b8c3e9ad0..0f2fc5e17d 100644
--- a/tbl_change.php
+++ b/tbl_change.php
@@ -12,6 +12,9 @@
* Gets the variables sent or posted to this script and displays the header
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Edit');
/**
* Ensures db and table are valid, else moves to the "parent" script
@@ -77,6 +80,8 @@ $scripts->addFile('sql.js');
$scripts->addFile('tbl_change.js');
$scripts->addFile('big_ints.js');
$scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
+$scripts->addFile('jquery/jquery.validate.js');
+$scripts->addFile('jquery/additional-methods.js');
$scripts->addFile('gis_data_editor.js');
/**
@@ -88,9 +93,6 @@ if (! empty($disp_message)) {
$response->addHTML(PMA_Util::getMessage($disp_message, null));
}
-// used as a global by PMA_Util::getDefaultFunctionForField()
-$analyzed_sql = PMA_Table::analyzeStructure($db, $table);
-
$table_columns = PMA_getTableColumns($db, $table);
// retrieve keys into foreign fields, if any
@@ -189,7 +191,7 @@ foreach ($rows as $row_id => $current_row) {
}
$html_output .= PMA_getHtmlForInsertEditRow(
- $url_params, $table_columns, $column, $comments_map, $timestamp_seen,
+ $url_params, $table_columns, $comments_map, $timestamp_seen,
$current_result, $chg_evt_handler, $jsvkey, $vkey, $insert_mode,
$current_row, $o_rows, $tabindex, $columns_cnt,
$is_upload, $tabindex_for_function, $foreigners, $tabindex_for_null,
@@ -200,8 +202,6 @@ foreach ($rows as $row_id => $current_row) {
$scripts->addFiles($GLOBALS['plugin_scripts']);
unset($unsaved_values, $checked, $repopulate, $GLOBALS['plugin_scripts']);
-$html_output .= PMA_getHtmlForGisEditor();
-
if (! isset($after_insert)) {
$after_insert = 'back';
}
@@ -219,6 +219,8 @@ if ($biggest_max_file_size > 0) {
) . "\n";
}
$html_output .= '</form>';
+
+$html_output .= PMA_getHtmlForGisEditor();
// end Insert/Edit form
if ($insert_mode) {
@@ -229,4 +231,3 @@ if ($insert_mode) {
}
$response->addHTML($html_output);
-?>
diff --git a/tbl_chart.php b/tbl_chart.php
index 283aaceba8..a435b5e485 100644
--- a/tbl_chart.php
+++ b/tbl_chart.php
@@ -6,137 +6,30 @@
* @package PhpMyAdmin
*/
-require_once 'libraries/common.inc.php';
-require_once 'libraries/tbl_chart.lib.php';
-
-/*
- * Execute the query and return the result
- */
-if (isset($_REQUEST['ajax_request'])
- && isset($_REQUEST['pos'])
- && isset($_REQUEST['session_max_rows'])
-) {
- $response = PMA_Response::getInstance();
-
- $tableLength = /*overload*/mb_strlen($GLOBALS['table']);
- $dbLength = /*overload*/mb_strlen($GLOBALS['db']);
- if ($tableLength && $dbLength) {
- include './libraries/tbl_common.inc.php';
- }
-
- $sql_with_limit = 'SELECT * FROM( ' . $sql_query . ' ) AS `temp_res` LIMIT '
- . $_REQUEST['pos'] . ', ' . $_REQUEST['session_max_rows'];
- $data = array();
- $result = $GLOBALS['dbi']->tryQuery($sql_with_limit);
- while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
- $data[] = $row;
- }
-
- if (empty($data)) {
- $response->isSuccess(false);
- $response->addJSON('message', __('No data to display'));
- exit;
- }
- $sanitized_data = array();
-
- foreach ($data as $data_row_number => $data_row) {
- $tmp_row = array();
- foreach ($data_row as $data_column => $data_value) {
- $tmp_row[htmlspecialchars($data_column)] = htmlspecialchars($data_value);
- }
- $sanitized_data[] = $tmp_row;
- }
- $response->isSuccess(true);
- $response->addJSON('message', null);
- $response->addJSON('chartData', json_encode($sanitized_data));
- unset($sanitized_data);
- exit;
-}
-
-$response = PMA_Response::getInstance();
-// Throw error if no sql query is set
-if (! isset($sql_query) || $sql_query == '') {
- $response->isSuccess(false);
- $response->addHTML(
- PMA_Message::error(__('No SQL query was set to fetch data.'))
- );
- exit;
-}
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('chart.js');
-$scripts->addFile('tbl_chart.js');
-$scripts->addFile('jqplot/jquery.jqplot.js');
-$scripts->addFile('jqplot/plugins/jqplot.barRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.canvasTextRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.categoryAxisRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.pointLabels.js');
-$scripts->addFile('jqplot/plugins/jqplot.pieRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.highlighter.js');
-
-/**
- * Runs common work
- */
-if (/*overload*/mb_strlen($GLOBALS['table'])) {
- $url_params['goto'] = $cfg['DefaultTabTable'];
- $url_params['back'] = 'tbl_sql.php';
- include 'libraries/tbl_common.inc.php';
- include 'libraries/tbl_info.inc.php';
-} elseif (/*overload*/mb_strlen($GLOBALS['db'])) {
- $url_params['goto'] = $cfg['DefaultTabDatabase'];
- $url_params['back'] = 'sql.php';
- include 'libraries/db_common.inc.php';
- include 'libraries/db_info.inc.php';
-} else {
- $url_params['goto'] = $cfg['DefaultTabServer'];
- $url_params['back'] = 'sql.php';
- include 'libraries/server_common.inc.php';
-}
-
-$data = array();
-
-$result = $GLOBALS['dbi']->tryQuery($sql_query);
-$fields_meta = $GLOBALS['dbi']->getFieldsMeta($result);
-while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
- $data[] = $row;
-}
-
-$keys = array_keys($data[0]);
-
-$numeric_types = array('int', 'real');
-$numeric_column_count = 0;
-foreach ($keys as $idx => $key) {
- if (in_array($fields_meta[$idx]->type, $numeric_types)) {
- $numeric_column_count++;
- }
-}
-if ($numeric_column_count == 0) {
- $response->isSuccess(false);
- $response->addJSON(
- 'message',
- __('No numeric columns present in the table to plot.')
- );
- exit;
-}
+namespace PMA;
-// get settings if any posted
-$chartSettings = array();
-if (PMA_isValid($_REQUEST['chartSettings'], 'array')) {
- $chartSettings = $_REQUEST['chartSettings'];
-}
+use PMA_Response;
-$url_params['db'] = $GLOBALS['db'];
-$url_params['reload'] = 1;
-
-/**
- * Displays the page
- */
-$htmlString = PMA_getHtmlForTableChartDisplay(
- $url_query, $url_params, $keys, $fields_meta, $numeric_types,
- $numeric_column_count, $sql_query
+require_once 'libraries/common.inc.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/Response.class.php';
+require_once 'libraries/controllers/TableChartController.class.php';
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableChartController');
+$container->alias(
+ 'TableChartController', 'PMA\Controllers\Table\TableChartController'
+);
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+
+/* Define dependencies for the concerned controller */
+$dependency_definitions = array(
+ "sql_query" => &$GLOBALS['sql_query'],
+ "url_query" => &$GLOBALS['url_query'],
+ "cfg" => &$GLOBALS['cfg']
);
-$response->addHTML($htmlString);
-?>
+/** @var Controllers\Table\TableChartController $controller */
+$controller = $container->get('TableChartController', $dependency_definitions);
+$controller->indexAction();
diff --git a/tbl_create.php b/tbl_create.php
index ebbef95151..3993baeaa4 100644
--- a/tbl_create.php
+++ b/tbl_create.php
@@ -104,5 +104,3 @@ $GLOBAL['table'] = '';
* Displays the form used to define the structure of the table
*/
require 'libraries/tbl_columns_definition_form.inc.php';
-
-?>
diff --git a/tbl_export.php b/tbl_export.php
index a8a1178936..afbe4fb9f1 100644
--- a/tbl_export.php
+++ b/tbl_export.php
@@ -10,14 +10,90 @@
*
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+require_once 'libraries/display_export.lib.php';
+
+PMA_PageSettings::showGroup('Export');
$response = PMA_Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('export.js');
+// Get the relation settings
+$cfgRelation = PMA_getRelationsParam();
+
+// handling export template actions
+if (isset($_REQUEST['templateAction']) && $cfgRelation['exporttemplateswork']) {
+
+ if (isset($_REQUEST['templateId'])) {
+ $templateId = $_REQUEST['templateId'];
+ $id = PMA_Util::sqlAddSlashes($templateId);
+ }
+
+ $templateTable = PMA_Util::backquote($cfgRelation['db']) . '.'
+ . PMA_Util::backquote($cfgRelation['export_templates']);
+ $user = PMA_Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']);
+
+ switch ($_REQUEST['templateAction']) {
+ case 'create':
+ $query = "INSERT INTO " . $templateTable . "("
+ . " `username`, `export_type`,"
+ . " `template_name`, `template_data`"
+ . ") VALUES ("
+ . "'" . $user . "', "
+ . "'" . PMA_Util::sqlAddSlashes($_REQUEST['exportType']) . "', "
+ . "'" . PMA_Util::sqlAddSlashes($_REQUEST['templateName']) . "', "
+ . "'" . PMA_Util::sqlAddSlashes($_REQUEST['templateData']) . "');";
+ break;
+ case 'load':
+ $query = "SELECT `template_data` FROM " . $templateTable
+ . " WHERE `id` = " . $id . " AND `username` = '" . $user . "'";
+ break;
+ case 'update':
+ $query = "UPDATE " . $templateTable . " SET `template_data` = "
+ . "'" . PMA_Util::sqlAddSlashes($_REQUEST['templateData']) . "'"
+ . " WHERE `id` = " . $id . " AND `username` = '" . $user . "'";
+ break;
+ case 'delete':
+ $query = "DELETE FROM " . $templateTable
+ . " WHERE `id` = " . $id . " AND `username` = '" . $user . "'";
+ break;
+ default:
+ break;
+ }
+
+ $result = PMA_queryAsControlUser($query, false);
+
+ $response = PMA_Response::getInstance();
+ if (! $result) {
+ $error = $GLOBALS['dbi']->getError($GLOBALS['controllink']);
+ $response->isSuccess(false);
+ $response->addJSON('message', $error);
+ exit;
+ }
+
+ $response->isSuccess(true);
+ if ('create' == $_REQUEST['templateAction']) {
+ $response->addJSON(
+ 'data',
+ PMA_getOptionsForExportTemplates($_REQUEST['exportType'])
+ );
+ } elseif ('load' == $_REQUEST['templateAction']) {
+ $data = null;
+ while ($row = $GLOBALS['dbi']->fetchAssoc(
+ $result, $GLOBALS['controllink']
+ )) {
+ $data = $row['template_data'];
+ }
+ $response->addJSON('data', $data);
+ }
+ $GLOBALS['dbi']->freeResult($result);
+ exit;
+}
+
/**
- * Gets tables informations and displays top links
+ * Gets tables information and displays top links
*/
require_once 'libraries/tbl_common.inc.php';
$url_query .= '&amp;goto=tbl_export.php&amp;back=tbl_export.php';
@@ -31,77 +107,71 @@ $export_page_title = __('View dump (schema) of table');
// generate WHERE clause (if we are asked to export specific rows)
if (! empty($sql_query)) {
- // Parse query so we can work with tokens
- $parsed_sql = PMA_SQP_parse($sql_query);
- $analyzed_sql = PMA_SQP_analyze($parsed_sql);
-
- // Need to generate WHERE clause?
- if (isset($where_clause)) {
-
- // If a table alias is used, get rid of it since
- // where clauses are on real table name
- if ($analyzed_sql[0]['table_ref'][0]['table_alias']) {
- // Exporting seleted rows is only allowed for queries involving
- // a single table. So we can safely assume that there is only one
- // table in 'table_ref' array.
- $temp_sql_array = preg_split('/\bfrom\b/i', $sql_query);
- $sql_query = $temp_sql_array[0] . 'FROM ';
- if (! empty($analyzed_sql[0]['table_ref'][0]['db'])) {
- $sql_query .= PMA_Util::backquote(
- $analyzed_sql[0]['table_ref'][0]['db']
- );
- $sql_query .= '.';
+ $parser = new SqlParser\Parser($sql_query);
+
+ if ((!empty($parser->statements[0]))
+ && ($parser->statements[0] instanceof SqlParser\Statements\SelectStatement)
+ ) {
+
+ // Finding aliases and removing them, but we keep track of them to be
+ // able to replace them in select expression too.
+ $aliases = array();
+ foreach ($parser->statements[0]->from as $from) {
+ if ((!empty($from->table)) && (!empty($from->alias))) {
+ $aliases[$from->alias] = $from->table;
+ // We remove the alias of the table because they are going to
+ // be replaced anyway.
+ $from->alias = null;
+ $from->expr = null; // Force rebuild.
}
- $sql_query .= PMA_Util::backquote(
- $analyzed_sql[0]['table_ref'][0]['table_name']
- );
}
- unset($temp_sql_array);
- // Regular expressions which can appear in sql query,
- // before the sql segment which remains as it is.
- $regex_array = array(
- '/\bwhere\b/i', '/\bgroup by\b/i', '/\bhaving\b/i', '/\border by\b/i'
- );
+ // Replacing the aliases in select expressions.
+ foreach ($parser->statements[0]->expr as $expr) {
+ if ((!empty($expr->table)) && (!empty($aliases[$expr->table]))) {
+ // Changing the table to null (leave the MySQL to find the
+ // right table).
+ // This is possible because exporting selected rows is only
+ // allowed for queries involing a single table.
+ $expr->table = null;
+ $expr->expr = null; // Force rebuild.
+ }
+ }
- $first_occurring_regex = PMA_Util::getFirstOccurringRegularExpression(
- $regex_array, $sql_query
+ // Rebuilding the SELECT and FROM clauses.
+ $replaces = array(
+ array(
+ 'SELECT', 'SELECT ' . SqlParser\Components\ExpressionArray::build(
+ $parser->statements[0]->expr
+ ),
+ ),
+ array(
+ 'FROM', 'FROM ' . SqlParser\Components\ExpressionArray::build(
+ $parser->statements[0]->from
+ ),
+ ),
);
- unset($regex_array);
-
- // The part "SELECT `id`, `name` FROM `customers`"
- // is not modified by the next code segment, when exporting
- // the result set from a query such as
- // "SELECT `id`, `name` FROM `customers` WHERE id NOT IN
- // ( SELECT id FROM companies WHERE name LIKE '%u%')"
- if (! is_null($first_occurring_regex)) {
- $temp_sql_array = preg_split($first_occurring_regex, $sql_query);
- $sql_query = $temp_sql_array[0];
- }
- unset($first_occurring_regex, $temp_sql_array);
- // Append the where clause using the primary key of each row
- if (is_array($where_clause) && (count($where_clause) > 0)) {
- $sql_query .= ' WHERE (' . implode(') OR (', $where_clause) . ')';
+ // Checking if the WHERE clause has to be replaced.
+ if ((!empty($where_clause)) && (is_array($where_clause))) {
+ $replaces[] = array(
+ 'WHERE', 'WHERE (' . implode(') OR (', $where_clause) . ')'
+ );
}
- if (!empty($analyzed_sql[0]['group_by_clause'])) {
- $sql_query .= ' GROUP BY ' . $analyzed_sql[0]['group_by_clause'];
- }
- if (!empty($analyzed_sql[0]['having_clause'])) {
- $sql_query .= ' HAVING ' . $analyzed_sql[0]['having_clause'];
- }
- if (!empty($analyzed_sql[0]['order_by_clause'])) {
- $sql_query .= ' ORDER BY ' . $analyzed_sql[0]['order_by_clause'];
- }
- } else {
- // Just crop LIMIT clause
- $sql_query = $analyzed_sql[0]['section_before_limit']
- . $analyzed_sql[0]['section_after_limit'];
+ // Preparing to remove the LIMIT clause.
+ $replaces[] = array('LIMIT', '');
+
+ // Replacing the clauses.
+ $sql_query = SqlParser\Utils\Query::replaceClauses(
+ $parser->statements[0],
+ $parser->list,
+ $replaces
+ );
}
+
echo PMA_Util::getMessage(PMA_Message::success());
}
$export_type = 'table';
require_once 'libraries/display_export.inc.php';
-?>
diff --git a/tbl_find_replace.php b/tbl_find_replace.php
index 3b19ebf1fb..dd5def5c9d 100644
--- a/tbl_find_replace.php
+++ b/tbl_find_replace.php
@@ -12,55 +12,27 @@
* Gets some core libraries
*/
require_once 'libraries/common.inc.php';
-require_once 'libraries/TableSearch.class.php';
-
-$response = PMA_Response::getInstance();
-$table_search = new PMA_TableSearch($db, $table, "replace");
-
-$connectionCharSet = $GLOBALS['dbi']->fetchValue(
- "SHOW VARIABLES LIKE 'character_set_connection'", 0, 1
+require_once 'libraries/tbl_common.inc.php';
+require_once 'libraries/tbl_info.inc.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/Response.class.php';
+require_once 'libraries/controllers/TableSearchController.class.php';
+
+use PMA\DI;
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableSearchController');
+$container->alias(
+ 'TableSearchController', 'PMA\Controllers\Table\TableSearchController'
);
-if (isset($_POST['find'])) {
- $preview = $table_search->getReplacePreview(
- $_POST['columnIndex'],
- $_POST['find'],
- $_POST['replaceWith'],
- $_POST['useRegex'],
- $connectionCharSet
- );
- $response->addJSON('preview', $preview);
- exit;
-}
-
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('tbl_find_replace.js');
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
-// Show secondary level of tabs
-$htmlOutput = $table_search->getSecondaryTabs();
-
-if (isset($_POST['replace'])) {
- $htmlOutput .= $table_search->replace(
- $_POST['columnIndex'],
- $_POST['findString'],
- $_POST['replaceWith'],
- $_POST['useRegex'],
- $connectionCharSet
- );
- $htmlOutput .= PMA_Util::getMessage(
- __('Your SQL query has been executed successfully.'),
- null, 'success'
- );
-}
-
-if (! isset($goto)) {
- $goto = $GLOBALS['cfg']['DefaultTabTable'];
-}
-// Defines the url to return to in case of error in the next sql statement
-$params = array('db' => $db, 'table' => $table);
-$err_url = $goto . '?' . PMA_URL_getCommon($params);
-// Displays the find and replace form
-$htmlOutput .= $table_search->getSelectionForm($goto);
-$response->addHTML($htmlOutput);
+$dependency_definitions = array(
+ 'searchType' => 'replace',
+ 'url_query' => &$url_query
+);
-?>
+/** @var PMA\Controllers\Table\TableSearchController $controller */
+$controller = $container->get('TableSearchController', $dependency_definitions);
+$controller->indexAction();
diff --git a/tbl_get_field.php b/tbl_get_field.php
index f4570ebac1..bd055ce2d9 100644
--- a/tbl_get_field.php
+++ b/tbl_get_field.php
@@ -40,7 +40,9 @@ $result = $GLOBALS['dbi']->fetchValue($sql);
/* Check return code */
if ($result === false) {
- PMA_Util::mysqlDie(__('MySQL returned an empty result set (i.e. zero rows).'), $sql);
+ PMA_Util::mysqlDie(
+ __('MySQL returned an empty result set (i.e. zero rows).'), $sql
+ );
}
/* Avoid corrupting data */
@@ -52,4 +54,3 @@ PMA_downloadHeader(
/*overload*/mb_strlen($result, '8bit')
);
echo $result;
-?>
diff --git a/tbl_gis_visualization.php b/tbl_gis_visualization.php
index 3448ba103c..94c8956cfc 100644
--- a/tbl_gis_visualization.php
+++ b/tbl_gis_visualization.php
@@ -6,110 +6,38 @@
* @package PhpMyAdmin
*/
-require_once 'libraries/common.inc.php';
+namespace PMA;
-// Runs common work
-require_once 'libraries/db_common.inc.php';
-$url_params['goto'] = $cfg['DefaultTabDatabase'];
-$url_params['back'] = 'sql.php';
+use PMA_Response;
+use PMA_Util;
-// Import visualization functions
-require_once 'libraries/tbl_gis_visualization.lib.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/Response.class.php';
+require_once 'libraries/controllers/TableGisVisualizationController.class.php';
+require_once 'libraries/Util.class.php';
-$response = PMA_Response::getInstance();
-// Throw error if no sql query is set
-if (! isset($sql_query) || $sql_query == '') {
- $response->isSuccess(false);
- $response->addHTML(
- PMA_Message::error(__('No SQL query was set to fetch data.'))
- );
- exit;
-}
-
-// Execute the query and return the result
-$result = $GLOBALS['dbi']->tryQuery($sql_query);
-// Get the meta data of results
-$meta = $GLOBALS['dbi']->getFieldsMeta($result);
-
-// Find the candidate fields for label column and spatial column
-$labelCandidates = array(); $spatialCandidates = array();
-foreach ($meta as $column_meta) {
- if ($column_meta->type == 'geometry') {
- $spatialCandidates[] = $column_meta->name;
- } else {
- $labelCandidates[] = $column_meta->name;
- }
-}
-
-// Get settings if any posted
-$visualizationSettings = array();
-if (PMA_isValid($_REQUEST['visualizationSettings'], 'array')) {
- $visualizationSettings = $_REQUEST['visualizationSettings'];
-}
-
-if (! isset($visualizationSettings['labelColumn']) && isset($labelCandidates[0])) {
- $visualizationSettings['labelColumn'] = '';
-}
-
-// If spatial column is not set, use first geometric column as spatial column
-if (! isset($visualizationSettings['spatialColumn'])) {
- $visualizationSettings['spatialColumn'] = $spatialCandidates[0];
-}
-
-// Convert geometric columns from bytes to text.
-$modified_query = PMA_GIS_modifyQuery($sql_query, $visualizationSettings);
-$modified_result = $GLOBALS['dbi']->tryQuery($modified_query);
-
-$data = array();
-while ($row = $GLOBALS['dbi']->fetchAssoc($modified_result)) {
- $data[] = $row;
-}
-
-if (isset($_REQUEST['saveToFile'])) {
- $response->disable();
- $file_name = $visualizationSettings['spatialColumn'];
- $save_format = $_REQUEST['fileFormat'];
- PMA_GIS_saveToFile($data, $visualizationSettings, $save_format, $file_name);
- exit();
-}
-
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('openlayers/OpenLayers.js');
-$scripts->addFile('jquery/jquery.svg.js');
-$scripts->addFile('tbl_gis_visualization.js');
-$scripts->addFile('OpenStreetMap.js');
-
-// If all the rows contain SRID, use OpenStreetMaps on the initial loading.
-if (! isset($_REQUEST['displayVisualization'])) {
- $visualizationSettings['choice'] = 'useBaseLayer';
- foreach ($data as $row) {
- if ($row['srid'] == 0) {
- unset($visualizationSettings['choice']);
- break;
- }
- }
-}
-
-$svg_support = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8)
- ? false : true;
-$format = $svg_support ? 'svg' : 'png';
-
-// get the chart and settings after chart generation
-$visualization = PMA_GIS_visualizationResults(
- $data, $visualizationSettings, $format
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableGisVisualizationController');
+$container->alias(
+ 'TableGisVisualizationController',
+ 'PMA\Controllers\Table\TableGisVisualizationController'
);
-
-/**
- * Displays the page
- */
-
-$html = PMA_getHtmlForGisVisualization(
- $url_params, $labelCandidates, $spatialCandidates,
- $visualizationSettings, $sql_query, $visualization, $svg_support,
- $data
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+
+/* Define dependencies for the concerned controller */
+$dependency_definitions = array(
+ "sql_query" => &$GLOBALS['sql_query'],
+ "url_params" => &$GLOBALS['url_params'],
+ "goto" => PMA_Util::getScriptNameForOption(
+ $GLOBALS['cfg']['DefaultTabDatabase'], 'database'
+ ),
+ "back" => 'sql.php',
+ "visualizationSettings" => array()
);
-$response->addHTML($html);
-
-?>
+/** @var Controllers\Table\TableGisVisualizationController $controller */
+$controller = $container->get(
+ 'TableGisVisualizationController', $dependency_definitions
+);
+$controller->indexAction();
diff --git a/tbl_import.php b/tbl_import.php
index fc642d86ea..8dc70e30dd 100644
--- a/tbl_import.php
+++ b/tbl_import.php
@@ -10,6 +10,9 @@
*
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Import');
$response = PMA_Response::getInstance();
$header = $response->getHeader();
@@ -17,14 +20,17 @@ $scripts = $header->getScripts();
$scripts->addFile('import.js');
/**
- * Gets tables informations and displays top links
+ * Gets tables information and displays top links
*/
require_once 'libraries/tbl_common.inc.php';
$url_query .= '&amp;goto=tbl_import.php&amp;back=tbl_import.php';
require_once 'libraries/tbl_info.inc.php';
-$import_type = 'table';
-require_once 'libraries/display_import.inc.php';
-
-?>
+require 'libraries/display_import.lib.php';
+$response = PMA_Response::getInstance();
+$response->addHTML(
+ PMA_getImportDisplay(
+ 'table', $db, $table, $max_upload_size
+ )
+);
diff --git a/tbl_indexes.php b/tbl_indexes.php
index f083edad71..63fee93951 100644
--- a/tbl_indexes.php
+++ b/tbl_indexes.php
@@ -6,55 +6,48 @@
* @package PhpMyAdmin
*/
-/**
- * Gets some core libraries
- */
-require_once 'libraries/common.inc.php';
-require_once 'libraries/Index.class.php';
-require_once 'libraries/tbl_indexes.lib.php';
-
-if (! isset($_REQUEST['create_edit_table'])) {
- include_once 'libraries/tbl_common.inc.php';
-}
+namespace PMA;
+use PMA_Index;
+use PMA_Response;
-$index = PMA_prepareFormValues($db, $table);
-/**
- * Process the data from the edit/create index form,
- * run the query to build the new index
- * and moves back to "tbl_sql.php"
- */
-if (isset($_REQUEST['do_save_data'])) {
- PMA_handleCreateOrEditIndex($db, $table, $index);
-} // end builds the new index
-
-
-/**
- * Display the form to edit/create an index
- */
-require_once 'libraries/tbl_info.inc.php';
+require_once 'libraries/common.inc.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/controllers/TableIndexesController.class.php';
+require_once 'libraries/Response.class.php';
+require_once 'libraries/Index.class.php';
-$add_fields = PMA_getNumberOfFieldsForForm($index);
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableIndexesController');
+$container->alias(
+ 'TableIndexesController', 'PMA\Controllers\Table\TableIndexesController'
+);
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
-$form_params = PMA_getFormParameters($db, $table);
+/* Define dependencies for the concerned controller */
+$db = $container->get('db');
+$table = $container->get('table');
+$dbi = $container->get('dbi');
-// Get fields and stores their name/type
-if (isset($_REQUEST['create_edit_table'])) {
- $fields = json_decode($_REQUEST['columns'], true);
- $index_params = array(
- 'Non_unique' => ($_REQUEST['index']['Index_choice'] == 'UNIQUE') ? '0' : '1'
- );
- $index->set($index_params);
- $add_fields = count($fields);
+if (!isset($_REQUEST['create_edit_table'])) {
+ include_once 'libraries/tbl_common.inc.php';
+}
+if (isset($_REQUEST['index'])) {
+ if (is_array($_REQUEST['index'])) {
+ // coming already from form
+ $index = new PMA_Index($_REQUEST['index']);
+ } else {
+ $index = $dbi->getTable($db, $table)->getIndex($_REQUEST['index']);
+ }
} else {
- $fields = PMA_getNameAndTypeOfTheColumns($db, $table);
+ $index = new PMA_Index;
}
-$html = PMA_getHtmlForIndexForm($fields, $index, $form_params, $add_fields);
+$dependency_definitions = array(
+ "index" => $index
+);
-$response = PMA_Response::getInstance();
-$response->addHTML($html);
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('indexes.js');
-?>
+/** @var Controllers\Table\TableIndexesController $controller */
+$controller = $container->get('TableIndexesController', $dependency_definitions);
+$controller->indexAction();
diff --git a/tbl_operations.php b/tbl_operations.php
index 803abbd1b9..f9a560a1ca 100644
--- a/tbl_operations.php
+++ b/tbl_operations.php
@@ -14,6 +14,7 @@ require_once 'libraries/common.inc.php';
/**
* functions implementation for this script
*/
+require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/operations.lib.php';
$pma_table = new PMA_Table($GLOBALS['table'], $GLOBALS['db']);
@@ -55,7 +56,7 @@ require_once 'libraries/Partition.class.php';
$GLOBALS['dbi']->selectDb($GLOBALS['db']);
/**
- * Gets tables informations
+ * Gets tables information
*/
require 'libraries/tbl_info.inc.php';
@@ -109,7 +110,23 @@ if (isset($_REQUEST['submitoptions'])) {
$warning_messages = array();
if (isset($_REQUEST['new_name'])) {
+ // Get original names before rename operation
+ $oldTable = $pma_table->getName();
+ $oldDb = $pma_table->getDbName();
+
if ($pma_table->rename($_REQUEST['new_name'])) {
+ if (isset($_REQUEST['adjust_privileges'])
+ && ! empty($_REQUEST['adjust_privileges'])
+ ) {
+ PMA_AdjustPrivileges_renameOrMoveTable(
+ $oldDb, $oldTable, $_REQUEST['db'], $_REQUEST['new_name']
+ );
+ }
+
+ // Reselect the original DB
+ $GLOBALS['db'] = $oldDb;
+ $GLOBALS['dbi']->selectDb($oldDb);
+
$_message .= $pma_table->getLastMessage();
$result = true;
$GLOBALS['table'] = $pma_table->getName();
@@ -162,6 +179,16 @@ if (isset($_REQUEST['submitoptions'])) {
unset($table_alters);
$warning_messages = PMA_getWarningMessagesArray();
}
+
+ if (isset($_REQUEST['tbl_collation'])
+ && ! empty($_REQUEST['tbl_collation'])
+ && isset($_REQUEST['change_all_collations'])
+ && ! empty($_REQUEST['change_all_collations'])
+ ) {
+ PMA_changeAllColumnsCollation(
+ $GLOBALS['db'], $GLOBALS['table'], $_REQUEST['tbl_collation']
+ );
+ }
}
/**
* Reordering the table has been requested by the user
@@ -184,7 +211,7 @@ if (isset($_REQUEST['submit_partition'])
if ($reread_info) {
// to avoid showing the old value (for example the AUTO_INCREMENT) after
// a change, clear the cache
- PMA_Table::$cache = array();
+ $GLOBALS['dbi']->clearTableCache();
$page_checksum = $checksum = $delay_key_write = 0;
include 'libraries/tbl_info.inc.php';
}
@@ -410,7 +437,7 @@ if ($cfgRelation['relwork'] && ! $is_innodb) {
$GLOBALS['dbi']->selectDb($GLOBALS['db']);
$foreign = PMA_getForeigners($GLOBALS['db'], $GLOBALS['table'], '', 'internal');
- if ($foreign) {
+ if (! empty($foreign)) {
$response->addHTML(
PMA_getHtmlForReferentialIntegrityCheck($foreign, $url_params)
);
@@ -419,5 +446,3 @@ if ($cfgRelation['relwork'] && ! $is_innodb) {
} // end if (!empty($cfg['Server']['relation']))
$response->addHTML('</div>');
-
-?>
diff --git a/tbl_printview.php b/tbl_printview.php
deleted file mode 100644
index f8ca99d908..0000000000
--- a/tbl_printview.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-/* vim: set expandtab sw=4 ts=4 sts=4: */
-/**
- * Print view for table
- *
- * @package PhpMyAdmin
- */
-
-/**
- * include the common file
- */
-require_once 'libraries/common.inc.php';
-
-$response = PMA_Response::getInstance();
-$response->getHeader()->enablePrintView();
-
-require 'libraries/tbl_common.inc.php';
-
-// Check parameters
-
-if (! isset($the_tables) || ! is_array($the_tables)) {
- $the_tables = array();
-}
-
-/**
- * Gets the relations settings
- */
-require_once 'libraries/transformations.lib.php';
-require_once 'libraries/Index.class.php';
-require_once 'libraries/tbl_printview.lib.php';
-
-$cfgRelation = PMA_getRelationsParam();
-
-/**
- * Defines the url to return to in case of error in a sql statement
- */
-if (/*overload*/mb_strlen($table)) {
- $err_url = 'tbl_sql.php?' . PMA_URL_getCommon(
- array('db' => $db, 'table' => $table)
- );
-} else {
- $err_url = 'db_sql.php' . PMA_URL_getCommon(array('db' => $db));
-}
-
-
-/**
- * Selects the database
- */
-$GLOBALS['dbi']->selectDb($db);
-
-/**
- * Multi-tables printview
- */
-if (isset($_POST['selected_tbl']) && is_array($_POST['selected_tbl'])) {
- $the_tables = $_POST['selected_tbl'];
-} elseif (/*overload*/mb_strlen($table)) {
- $the_tables[] = $table;
-}
-
-$response->addHTML(PMA_getHtmlForTablesInfo($the_tables));
-$response->addHTML(
- PMA_getHtmlForTablesDetail(
- $the_tables, $db, $cfg, $cfgRelation,
- $cell_align_left
- )
-);
-
-/**
- * Displays the footer
- */
-$response->addHTML(PMA_getHtmlForPrintViewFooter());
-
-exit;
-?>
diff --git a/tbl_recent_favorite.php b/tbl_recent_favorite.php
index 1d647e03a6..9e64121573 100644
--- a/tbl_recent_favorite.php
+++ b/tbl_recent_favorite.php
@@ -16,4 +16,3 @@ PMA_RecentFavoriteTable::getInstance('favorite')
->removeIfInvalid($_REQUEST['db'], $_REQUEST['table']);
require 'sql.php';
-?> \ No newline at end of file
diff --git a/tbl_relation.php b/tbl_relation.php
index 974105d153..1c05c72441 100644
--- a/tbl_relation.php
+++ b/tbl_relation.php
@@ -15,142 +15,68 @@
*/
/**
- * Gets some core libraries
+ * Get the TableRelationController
*/
-require_once 'libraries/common.inc.php';
-require_once 'libraries/index.lib.php';
-require_once 'libraries/tbl_relation.lib.php';
-require_once 'libraries/structure.lib.php';
-
-$response = PMA_Response::getInstance();
-
-// Send table of column names to populate corresponding dropdowns depending
-// on the current selection
-if (isset($_REQUEST['getDropdownValues'])
- && $_REQUEST['getDropdownValues'] === 'true'
-) {
- PMA_sendHtmlForTableOrColumnDropdownList();
-}
+namespace PMA;
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('tbl_relation.js');
-$scripts->addFile('indexes.js');
+use PMA_Response;
+use PMA_Table;
+use PMA_Util;
-/**
- * Gets tables informations
- */
-require_once 'libraries/tbl_info.inc.php';
+require_once 'libraries/common.inc.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/controllers/TableRelationController.class.php';
+require_once 'libraries/Response.class.php';
+require_once 'libraries/Table.class.php';
+require_once 'libraries/Util.class.php';
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableRelationController');
+$container->alias(
+ 'TableRelationController', 'PMA\Controllers\Table\TableRelationController'
+);
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+/* Define dependencies for the concerned controller */
+$db = $container->get('db');
+$table = $container->get('table');
+$dbi = $container->get('dbi');
$options_array = array(
- 'CASCADE' => 'CASCADE',
- 'SET_NULL' => 'SET NULL',
+ 'CASCADE' => 'CASCADE',
+ 'SET_NULL' => 'SET NULL',
'NO_ACTION' => 'NO ACTION',
- 'RESTRICT' => 'RESTRICT',
+ 'RESTRICT' => 'RESTRICT',
);
-
-/**
- * Gets the relation settings
- */
$cfgRelation = PMA_getRelationsParam();
+$tbl_storage_engine = /*overload*/
+ mb_strtoupper(
+ $GLOBALS['dbi']->getTable($db, $table)->getStatusInfo('Engine')
+ );
+$upd_query = new PMA_Table($table, $db, $dbi);
-/**
- * Updates
- */
+$dependency_definitions = array(
+ "options_array" => $options_array,
+ "cfgRelation" => $cfgRelation,
+ "tbl_storage_engine" => $tbl_storage_engine,
+ "upd_query" => $upd_query
+);
if ($cfgRelation['relwork']) {
- $existrel = PMA_getForeigners($db, $table, '', 'internal');
+ $dependency_definitions['existrel'] = PMA_getForeigners(
+ $db, $table, '', 'internal'
+ );
}
if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
- $existrel_foreign = PMA_getForeigners($db, $table, '', 'foreign');
-}
-if ($cfgRelation['displaywork']) {
- $disp = PMA_getDisplayField($db, $table);
-} else {
- $disp = '';
-}
-
-// will be used in the logic for internal relations and foreign keys:
-$multi_edit_columns_name = isset($_REQUEST['fields_name'])
- ? $_REQUEST['fields_name']
- : null;
-
-
-$html_output = '';
-
-// u p d a t e s f o r I n t e r n a l r e l a t i o n s
-if (isset($_POST['destination_db']) && $cfgRelation['relwork']) {
- $html_output .= PMA_handleUpdatesForInternalRelations(
- $_POST['destination_db'], $multi_edit_columns_name,
- $_POST['destination_table'],
- $_POST['destination_column'], $cfgRelation, $db, $table,
- isset($existrel) ? $existrel : null
- );
-} // end if (updates for internal relations)
-
-$multi_edit_columns_name = isset($_REQUEST['foreign_key_fields_name'])
- ? $_REQUEST['foreign_key_fields_name']
- : null;
-
-// u p d a t e s f o r f o r e i g n k e y s
-// (for now, one index name only; we keep the definitions if the
-// foreign db is not the same)
-if (isset($_POST['destination_foreign_db'])) {
- $html_output .= PMA_handleUpdatesForForeignKeys(
- $_POST['destination_foreign_db'],
- $multi_edit_columns_name, $_POST['destination_foreign_table'],
- $_POST['destination_foreign_column'], $options_array, $table,
- isset($existrel_foreign) ? $existrel_foreign['foreign_keys_data'] : null
+ $dependency_definitions['existrel_foreign'] = PMA_getForeigners(
+ $db, $table, '', 'foreign'
);
-} // end if isset($destination_foreign)
-
-// U p d a t e s f o r d i s p l a y f i e l d
-if ($cfgRelation['displaywork'] && isset($_POST['display_field'])) {
- $html_output .= PMA_handleUpdateForDisplayField(
- $disp, $_POST['display_field'], $db, $table, $cfgRelation
- );
-} // end if
-
-// If we did an update, refresh our data
-if (isset($_POST['destination_db']) && $cfgRelation['relwork']) {
- $existrel = PMA_getForeigners($db, $table, '', 'internal');
-}
-if (isset($_POST['destination_foreign_db'])
- && PMA_Util::isForeignKeySupported($tbl_storage_engine)
-) {
- $existrel_foreign = PMA_getForeigners($db, $table, '', 'foreign');
}
-
if ($cfgRelation['displaywork']) {
- $disp = PMA_getDisplayField($db, $table);
-}
-
-
-// display secondary level tabs if necessary
-$engine = PMA_Table::sGetStatusInfo($db, $table, 'ENGINE');
-$response->addHTML(PMA_getStructureSecondaryTabs($engine));
-$response->addHTML('<div id="structure_content">');
-
-/**
- * Dialog
- */
-// Now find out the columns of our $table
-// need to use PMA_DatabaseInterface::QUERY_STORE with $GLOBALS['dbi']->numRows()
-// in mysqli
-$columns = $GLOBALS['dbi']->getColumns($db, $table);
-
-// common form
-$html_output .= PMA_getHtmlForCommonForm(
- $db, $table, $columns, $cfgRelation, $tbl_storage_engine,
- isset($existrel) ? $existrel : array(),
- isset($existrel_foreign) ? $existrel_foreign['foreign_keys_data'] : array(),
- $options_array
-);
-
-if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
- $html_output .= PMA_getHtmlForDisplayIndexes();
+ $dependency_definitions['disp'] = PMA_getDisplayField($db, $table);
+} else {
+ $dependency_definitions['disp'] = 'asas';
}
-// Render HTML output
-$response->addHTML($html_output);
-$response->addHTML('</div>');
-?>
+/** @var Controllers\Table\TableRelationController $controller */
+$controller = $container->get('TableRelationController', $dependency_definitions);
+$controller->indexAction();
diff --git a/tbl_replace.php b/tbl_replace.php
index a1238ab279..8209babc05 100644
--- a/tbl_replace.php
+++ b/tbl_replace.php
@@ -153,7 +153,7 @@ foreach ($loop_array as $rownumber => $where_clause) {
$multi_edit_columns_name
= isset($_REQUEST['fields_name']['multi_edit'][$rownumber])
? $_REQUEST['fields_name']['multi_edit'][$rownumber]
- : array();
+ : null;
$multi_edit_columns_prev
= isset($_REQUEST['fields_prev']['multi_edit'][$rownumber])
? $_REQUEST['fields_prev']['multi_edit'][$rownumber]
@@ -218,6 +218,7 @@ foreach ($loop_array as $rownumber => $where_clause) {
$classname = PMA_getTransformationClassName(
$mime_map[$column_name]['input_transformation']
);
+ /** @var IOTransformationsPlugin $transformation_plugin */
$transformation_plugin = new $classname();
$transformation_options = PMA_Transformation_getOptions(
$mime_map[$column_name]['input_transformation_options']
@@ -283,8 +284,7 @@ foreach ($loop_array as $rownumber => $where_clause) {
$value_sets[] = implode(', ', $query_values);
} else {
// build update query
- $query[] = 'UPDATE ' . PMA_Util::backquote($GLOBALS['db'])
- . '.' . PMA_Util::backquote($GLOBALS['table'])
+ $query[] = 'UPDATE ' . PMA_Util::backquote($GLOBALS['table'])
. ' SET ' . implode(', ', $query_values)
. ' WHERE ' . $where_clause
. ($_REQUEST['clause_is_unique'] ? '' : ' LIMIT 1');
@@ -424,9 +424,8 @@ if ($response->isAjax() && ! isset($_POST['ajax_page_request'])) {
);
/**Get the total row count of the table*/
- $extra_data['row_count'] = PMA_Table::countRecords(
- $_REQUEST['db'], $_REQUEST['table']
- );
+ $_table = new PMA_Table($_REQUEST['table'], $_REQUEST['db']);
+ $extra_data['row_count'] = $_table->countRecords();
$extra_data['sql_query']
= PMA_Util::getMessage($message, $GLOBALS['display_query']);
@@ -464,5 +463,3 @@ if (isset($_REQUEST['after_insert']) && 'new_insert' == $_REQUEST['after_insert'
*/
require '' . PMA_securePath($goto_include);
exit;
-
-?>
diff --git a/tbl_row_action.php b/tbl_row_action.php
index bc582caa22..bb2eb6d17a 100644
--- a/tbl_row_action.php
+++ b/tbl_row_action.php
@@ -37,6 +37,7 @@ if (! isset($submit_mult)) {
switch($submit_mult) {
case 'row_delete':
case 'row_edit':
+case 'row_copy':
case 'row_export':
// leave as is
break;
@@ -49,8 +50,12 @@ case 'delete':
$submit_mult = 'row_delete';
break;
-default:
+case 'copy':
+ $submit_mult = 'row_copy';
+ break;
+
case 'edit':
+default:
$submit_mult = 'row_edit';
break;
}
@@ -67,6 +72,9 @@ if (!empty($submit_mult)) {
}
switch($submit_mult) {
+ case 'row_copy':
+ $_REQUEST['default_action'] = 'insert';
+ // no break to allow for fallthough
case 'row_edit':
// As we got the rows to be edited from the
// 'rows_to_delete' checkbox, we use the index of it as the
@@ -147,10 +155,24 @@ if (!empty($submit_mult)) {
include_once 'libraries/parse_analyze.inc.php';
PMA_executeQueryAndSendQueryResponse(
- $analyzed_sql_results, false, $db, $table, null, null, null, false, null,
- null, null, $goto, $pmaThemeImage, null, null, null, $sql_query,
- null, null
+ $analyzed_sql_results, // analyzed_sql_results
+ false, // is_gotofile
+ $db, // db
+ $table, // table
+ null, // find_real_end
+ null, // sql_query_for_bookmark
+ null, // extra_data
+ null, // message_to_show
+ null, // message
+ null, // sql_data
+ $goto, // goto
+ $pmaThemeImage, // pmaThemeImage
+ null, // disp_query
+ null, // disp_message
+ null, // query_type
+ $sql_query, // sql_query
+ null, // selectedTables
+ null // complete_query
);
}
}
-?>
diff --git a/tbl_select.php b/tbl_select.php
index 93ed5789a4..cb4e195582 100644
--- a/tbl_select.php
+++ b/tbl_select.php
@@ -13,69 +13,28 @@
* Gets some core libraries
*/
require_once 'libraries/common.inc.php';
-require_once 'libraries/mysql_charsets.inc.php';
-require_once 'libraries/TableSearch.class.php';
-require_once 'libraries/sql.lib.php';
-require_once 'libraries/bookmark.lib.php';
-
-$response = PMA_Response::getInstance();
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('makegrid.js');
-$scripts->addFile('sql.js');
-$scripts->addFile('tbl_select.js');
-$scripts->addFile('tbl_change.js');
-$scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
-$scripts->addFile('jquery/jquery.uitablefilter.js');
-$scripts->addFile('gis_data_editor.js');
-
-$table_search = new PMA_TableSearch($db, $table, "normal");
-
-// Request to column min-max value.
-if (isset($_REQUEST['range_search'])) {
- $response = PMA_Response::getInstance();
- $min_max = $table_search->getColumnMinMax($_REQUEST['column']);
- $response->addJSON('column_data', $min_max);
- exit;
-}
-
-/**
- * No selection criteria received -> display the selection form
- */
-if (! isset($_POST['columnsToDisplay']) && ! isset($_POST['displayAllColumns'])) {
- // Gets some core libraries
- include_once 'libraries/tbl_common.inc.php';
- //$err_url = 'tbl_select.php' . $err_url;
- $url_query .= '&amp;goto=tbl_select.php&amp;back=tbl_select.php';
- /**
- * Gets table's information
- */
- include_once 'libraries/tbl_info.inc.php';
-
- if (! isset($goto)) {
- $goto = $GLOBALS['cfg']['DefaultTabTable'];
- }
- // Defines the url to return to in case of error in the next sql statement
- $err_url = $goto . PMA_URL_getCommon(array('db' => $db, 'table' => $table));
- // Displays the table search form
- $response->addHTML($table_search->getSecondaryTabs());
- $response->addHTML($table_search->getSelectionForm($goto));
-
-} else {
- /**
- * Selection criteria have been submitted -> do the work
- */
- $sql_query = $table_search->buildSqlQuery();
-
- /**
- * Parse and analyze the query
- */
- include_once 'libraries/parse_analyze.inc.php';
-
- PMA_executeQueryAndSendQueryResponse(
- $analyzed_sql_results, false, $db, $table, null, null, null, false,
- null, null, null, $GLOBALS['goto'], $pmaThemeImage, null,
- null, null, $sql_query, null, null
- );
-}
-?>
+require_once 'libraries/tbl_common.inc.php';
+require_once 'libraries/tbl_info.inc.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/Response.class.php';
+require_once 'libraries/controllers/TableSearchController.class.php';
+
+use PMA\DI;
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableSearchController');
+$container->alias(
+ 'TableSearchController', 'PMA\Controllers\Table\TableSearchController'
+);
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+
+/* Define dependencies for the concerned controller */
+$dependency_definitions = array(
+ 'searchType' => 'normal',
+ 'url_query' => &$url_query
+);
+
+/** @var PMA\Controllers\TableSearchController $controller */
+$controller = $container->get('TableSearchController', $dependency_definitions);
+$controller->indexAction();
diff --git a/tbl_sql.php b/tbl_sql.php
index 92c980d4d8..70dda87265 100644
--- a/tbl_sql.php
+++ b/tbl_sql.php
@@ -10,6 +10,9 @@
*
*/
require_once 'libraries/common.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+
+PMA_PageSettings::showGroup('Sql_queries');
/**
* Runs common work
@@ -48,5 +51,3 @@ $response->addHTML(
: ';'
)
);
-
-?>
diff --git a/tbl_structure.php b/tbl_structure.php
index b812bb60b2..a65748509a 100644
--- a/tbl_structure.php
+++ b/tbl_structure.php
@@ -7,204 +7,42 @@
* @package PhpMyAdmin
*/
-/**
- *
- */
-require_once 'libraries/common.inc.php';
-require_once 'libraries/mysql_charsets.inc.php';
+namespace PMA;
-/**
- * Function implementations for this script
- */
-require_once 'libraries/structure.lib.php';
-require_once 'libraries/index.lib.php';
-require_once 'libraries/sql.lib.php';
-require_once 'libraries/bookmark.lib.php';
+use PMA_Response;
-$response = PMA_Response::getInstance();
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('tbl_structure.js');
-$scripts->addFile('indexes.js');
-
-/**
- * Handle column moving
- */
-if (isset($_REQUEST['move_columns'])
- && is_array($_REQUEST['move_columns'])
- && $response->isAjax()
-) {
- PMA_moveColumns($db, $table);
- exit;
-}
-
-/**
- * handle MySQL reserved words columns check
- */
-if (isset($_REQUEST['reserved_word_check'])) {
- $response = PMA_Response::getInstance();
- if ($GLOBALS['cfg']['ReservedWordDisableWarning'] === false) {
- $columns_names = $_REQUEST['field_name'];
- $reserved_keywords_names = array();
- foreach ($columns_names as $column) {
- if (PMA_SQP_isKeyWord(trim($column))) {
- $reserved_keywords_names[] = trim($column);
- }
- }
- if (PMA_SQP_isKeyWord(trim($table))) {
- $reserved_keywords_names[] = trim($table);
- }
- if (count($reserved_keywords_names) == 0) {
- $response->isSuccess(false);
- }
- $response->addJSON(
- 'message', sprintf(
- _ngettext(
- 'The name \'%s\' is a MySQL reserved keyword.',
- 'The names \'%s\' are MySQL reserved keywords.',
- count($reserved_keywords_names)
- ),
- implode(',', $reserved_keywords_names)
- )
- );
- } else {
- $response->isSuccess(false);
- }
- exit;
-}
-/**
- * A click on Change has been made for one column
- */
-if (isset($_REQUEST['change_column'])) {
- PMA_displayHtmlForColumnChange($db, $table, null, 'tbl_structure.php');
- exit;
-}
-
-/**
- * handle multiple field commands if required
- *
- * submit_mult_*_x comes from IE if <input type="img" ...> is used
- */
-$submit_mult = PMA_getMultipleFieldCommandType();
-
-if (! empty($submit_mult)) {
- if (isset($_REQUEST['selected_fld'])) {
- if ($submit_mult == 'browse') {
- // browsing the table displaying only selected columns
- PMA_displayTableBrowseForSelectedColumns(
- $db, $table, $goto, $pmaThemeImage
- );
- } else {
- // handle multiple field commands
- // handle confirmation of deleting multiple columns
- $action = 'tbl_structure.php';
- include 'libraries/mult_submits.inc.php';
- /**
- * if $submit_mult == 'change', execution will have stopped
- * at this point
- */
-
- if (empty($message)) {
- $message = PMA_Message::success();
- }
- }
- } else {
- $response = PMA_Response::getInstance();
- $response->isSuccess(false);
- $response->addJSON('message', __('No column selected.'));
- }
-}
-
-// display secondary level tabs if necessary
-$engine = PMA_Table::sGetStatusInfo($db, $table, 'ENGINE');
-$response->addHTML(PMA_getStructureSecondaryTabs($engine));
-$response->addHTML('<div id="structure_content">');
-
-/**
- * Modifications have been submitted -> updates the table
- */
-if (isset($_REQUEST['do_save_data'])) {
- $regenerate = PMA_updateColumns($db, $table);
- if ($regenerate) {
- // This happens when updating failed
- // @todo: do something appropriate
- } else {
- // continue to show the table's structure
- unset($_REQUEST['selected']);
- }
-}
-
-/**
- * Adding indexes
- */
-if (isset($_REQUEST['add_key'])) {
- include 'sql.php';
- $GLOBALS['reload'] = true;
-}
-
-/**
- * Gets the relation settings
- */
-$cfgRelation = PMA_getRelationsParam();
-
-/**
- * Runs common work
- */
-require_once 'libraries/tbl_common.inc.php';
-$url_query .= '&amp;goto=tbl_structure.php&amp;back=tbl_structure.php';
-$url_params['goto'] = 'tbl_structure.php';
-$url_params['back'] = 'tbl_structure.php';
-
-/**
- * Prepares the table structure display
- */
-
-
-/**
- * Gets tables informations
- */
+require_once 'libraries/common.inc.php';
require_once 'libraries/tbl_info.inc.php';
-
-require_once 'libraries/Index.class.php';
-
-// 2. Gets table keys and retains them
-// @todo should be: $server->db($db)->table($table)->primary()
-$primary = PMA_Index::getPrimary($table, $db);
-
-$columns_with_unique_index = PMA_getColumnsWithUniqueIndex($db, $table);
-
-// 3. Get fields
-$fields = (array) $GLOBALS['dbi']->getColumns($db, $table, null, true);
-
-// Get more complete field information
-// For now, this is done just for MySQL 4.1.2+ new TIMESTAMP options
-// but later, if the analyser returns more information, it
-// could be executed for any MySQL version and replace
-// the info given by SHOW FULL COLUMNS FROM.
-//
-// We also need this to correctly learn if a TIMESTAMP is NOT NULL, since
-// SHOW FULL COLUMNS or INFORMATION_SCHEMA incorrectly says NULL
-// and SHOW CREATE TABLE says NOT NULL (tested
-// in MySQL 4.0.25 and 5.0.21, http://bugs.mysql.com/20910).
-
-$show_create_table = $GLOBALS['dbi']->fetchValue(
- 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.'
- . PMA_Util::backquote($table),
- 0, 1
+require_once 'libraries/mysql_charsets.inc.php';
+require_once 'libraries/config/page_settings.class.php';
+require_once 'libraries/bookmark.lib.php';
+require_once 'libraries/di/Container.class.php';
+require_once 'libraries/controllers/TableStructureController.class.php';
+require_once 'libraries/Response.class.php';
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\TableStructureController');
+$container->alias(
+ 'TableStructureController', 'PMA\Controllers\TableStructureController'
+);
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+
+global $db, $table, $db_is_system_schema, $tbl_is_view, $tbl_storage_engine,
+ $table_info_num_rows, $tbl_collation, $showtable;
+/* Define dependencies for the concerned controller */
+$dependency_definitions = array(
+ 'db' => $db,
+ 'table' => $table,
+ 'url_query' => &$GLOBALS['url_query'],
+ 'db_is_system_schema' => $db_is_system_schema,
+ 'tbl_is_view' => $tbl_is_view,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'table_info_num_rows' => $table_info_num_rows,
+ 'tbl_collation' => $tbl_collation,
+ 'showtable' => $showtable
);
-$analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table));
-
-/**
- * prepare table infos
- */
-// action titles (image or string)
-$titles = PMA_getActionTitlesArray();
-
-// hidden action titles (image and string)
-$hidden_titles = PMA_getHiddenTitlesArray();
-
-//display table structure
-require_once 'libraries/display_structure.inc.php';
-$response->addHTML('</div>');
-?>
+/** @var Controllers\TableStructureController $controller */
+$controller = $container->get('TableStructureController', $dependency_definitions);
+$controller->indexAction();
diff --git a/tbl_tracking.php b/tbl_tracking.php
index e82e6198e1..7f8c44613b 100644
--- a/tbl_tracking.php
+++ b/tbl_tracking.php
@@ -192,7 +192,8 @@ if ($last_version > 0) {
);
}
-$type = PMA_Table::isView($GLOBALS['db'], $GLOBALS['table']) ? 'view' : 'table';
+$type = $GLOBALS['dbi']->getTable($GLOBALS['db'], $GLOBALS['table'])
+ ->isView() ? 'view' : 'table';
$html .= PMA_getHtmlForDataDefinitionAndManipulationStatements(
'tbl_tracking.php' . $url_query,
$last_version,
@@ -205,5 +206,3 @@ $html .= '<br class="clearfloat"/>';
$response = PMA_Response::getInstance();
$response->addHTML($html);
-
-?>
diff --git a/tbl_triggers.php b/tbl_triggers.php
index 9c87e676dd..d96c922b15 100644
--- a/tbl_triggers.php
+++ b/tbl_triggers.php
@@ -7,4 +7,3 @@
*/
require_once './db_triggers.php';
-?>
diff --git a/tbl_zoom_select.php b/tbl_zoom_select.php
index 6b6096a15c..621aa07790 100644
--- a/tbl_zoom_select.php
+++ b/tbl_zoom_select.php
@@ -12,154 +12,28 @@
* Gets some core libraries
*/
require_once './libraries/common.inc.php';
-require_once './libraries/mysql_charsets.inc.php';
-require_once './libraries/TableSearch.class.php';
-require_once './libraries/tbl_info.inc.php';
-
-$response = PMA_Response::getInstance();
-$header = $response->getHeader();
-$scripts = $header->getScripts();
-$scripts->addFile('makegrid.js');
-$scripts->addFile('sql.js');
-$scripts->addFile('jqplot/jquery.jqplot.js');
-$scripts->addFile('jqplot/plugins/jqplot.canvasTextRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js');
-$scripts->addFile('jqplot/plugins/jqplot.highlighter.js');
-$scripts->addFile('jqplot/plugins/jqplot.cursor.js');
-$scripts->addFile('canvg/canvg.js');
-$scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
-$scripts->addFile('tbl_zoom_plot_jqplot.js');
-$scripts->addFile('tbl_change.js');
-
-$table_search = new PMA_TableSearch($db, $table, "zoom");
-
-/**
- * Handle AJAX request for data row on point select
- * @var post_params Object containing parameters for the POST request
- */
-
-if (isset($_REQUEST['get_data_row']) && $_REQUEST['get_data_row'] == true) {
- $extra_data = array();
- $row_info_query = 'SELECT * FROM `' . $_REQUEST['db'] . '`.`'
- . $_REQUEST['table'] . '` WHERE ' . $_REQUEST['where_clause'];
- $result = $GLOBALS['dbi']->query(
- $row_info_query . ";", null, PMA_DatabaseInterface::QUERY_STORE
- );
- $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result);
- while ($row = $GLOBALS['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') {
- $row[$col] = PMA_Util::printableBitValue(
- $val, $fields_meta[$i]->length
- );
- }
- $i++;
- }
- $extra_data['row_info'] = $row;
- }
- PMA_Response::getInstance()->addJSON($extra_data);
- exit;
-}
-
-/**
- * Handle AJAX request for changing field information
- * (value,collation,operators,field values) in input form
- * @var post_params Object containing parameters for the POST request
- */
-
-if (isset($_REQUEST['change_tbl_info']) && $_REQUEST['change_tbl_info'] == true) {
- $response = PMA_Response::getInstance();
- $field = $_REQUEST['field'];
- if ($field == 'pma_null') {
- $response->addJSON('field_type', '');
- $response->addJSON('field_collation', '');
- $response->addJSON('field_operators', '');
- $response->addJSON('field_value', '');
- exit;
- }
- $key = array_search($field, $table_search->getColumnNames());
- $properties = $table_search->getColumnProperties($_REQUEST['it'], $key);
- $response->addJSON('field_type', htmlspecialchars($properties['type']));
- $response->addJSON('field_collation', $properties['collation']);
- $response->addJSON('field_operators', $properties['func']);
- $response->addJSON('field_value', $properties['value']);
- exit;
-}
-
-// Gets some core libraries
-require_once './libraries/tbl_common.inc.php';
-$url_query .= '&amp;goto=tbl_select.php&amp;back=tbl_select.php';
-
-// Gets tables informations
-require_once './libraries/tbl_info.inc.php';
-
-if (! isset($goto)) {
- $goto = $GLOBALS['cfg']['DefaultTabTable'];
-}
-// Defines the url to return to in case of error in the next sql statement
-$err_url = $goto . PMA_URL_getCommon(array('db' => $db, 'table' => $table));
-
-//Set default datalabel if not selected
-if ( !isset($_POST['zoom_submit']) || $_POST['dataLabel'] == '') {
- $dataLabel = PMA_getDisplayField($db, $table);
-} else {
- $dataLabel = $_POST['dataLabel'];
-}
-
-// Displays the zoom search form
-$response->addHTML($table_search->getSecondaryTabs());
-$response->addHTML($table_search->getSelectionForm($goto, $dataLabel));
-
-/*
- * Handle the input criteria and generate the query result
- * Form for displaying query results
- */
-if (isset($_POST['zoom_submit'])
- && $_POST['criteriaColumnNames'][0] != 'pma_null'
- && $_POST['criteriaColumnNames'][1] != 'pma_null'
- && $_POST['criteriaColumnNames'][0] != $_POST['criteriaColumnNames'][1]
-) {
- //Query generation part
- $sql_query = $table_search->buildSqlQuery();
- $sql_query .= ' LIMIT ' . $_POST['maxPlotLimit'];
-
- //Query execution part
- $result = $GLOBALS['dbi']->query(
- $sql_query . ";", null, PMA_DatabaseInterface::QUERY_STORE
- );
- $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result);
- $data = array();
- while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
- //Need a row with indexes as 0,1,2 for the getUniqueCondition
- // hence using a temporary array
- $tmpRow = array();
- foreach ($row as $val) {
- $tmpRow[] = $val;
- }
- //Get unique condition on each row (will be needed for row update)
- $uniqueCondition = PMA_Util::getUniqueCondition(
- $result, count($table_search->getColumnNames()), $fields_meta, $tmpRow,
- true
- );
- //Append it to row array as where_clause
- $row['where_clause'] = $uniqueCondition[0];
-
- $tmpData = array(
- $_POST['criteriaColumnNames'][0] =>
- $row[$_POST['criteriaColumnNames'][0]],
- $_POST['criteriaColumnNames'][1] =>
- $row[$_POST['criteriaColumnNames'][1]],
- 'where_clause' => $uniqueCondition[0]
- );
- $tmpData[$dataLabel] = ($dataLabel) ? $row[$dataLabel] : '';
- $data[] = $tmpData;
- }
- unset($tmpData);
-
- //Displays form for point data and scatter plot
- $response->addHTML($table_search->getZoomResultsForm($goto, $data));
-}
-?>
+require_once 'libraries/tbl_common.inc.php';
+require_once 'libraries/tbl_info.inc.php';
+require_once './libraries/di/Container.class.php';
+require_once './libraries/Response.class.php';
+require_once './libraries/controllers/TableSearchController.class.php';
+
+use PMA\DI;
+
+$container = DI\Container::getDefaultContainer();
+$container->factory('PMA\Controllers\Table\TableSearchController');
+$container->alias(
+ 'TableSearchController', 'PMA\Controllers\Table\TableSearchController'
+);
+$container->set('PMA_Response', PMA_Response::getInstance());
+$container->alias('response', 'PMA_Response');
+
+/* Define dependencies for the concerned controller */
+$dependency_definitions = array(
+ 'searchType' => 'zoom',
+ 'url_query' => &$url_query
+);
+
+/** @var PMA\Controllers\Table\TableSearchController $controller */
+$controller = $container->get('TableSearchController', $dependency_definitions);
+$controller->indexAction();
diff --git a/templates/columns_definitions/column_adjust_privileges.phtml b/templates/columns_definitions/column_adjust_privileges.phtml
new file mode 100644
index 0000000000..6b90eff0d2
--- /dev/null
+++ b/templates/columns_definitions/column_adjust_privileges.phtml
@@ -0,0 +1,18 @@
+<?php if ($privs_available) : ?>
+ <input name="field_adjust_privileges[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ checked="checked"
+ type="checkbox"
+ value="NULL"
+ class="allow_null"/>
+
+<?php else : ?>
+ <input name="field_adjust_privileges[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ disabled
+ type="checkbox"
+ value="NULL"
+ class="allow_null"
+ title="<?php echo __('You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details');?>"/>
+<?php endif; ?> \ No newline at end of file
diff --git a/templates/columns_definitions/column_attribute.phtml b/templates/columns_definitions/column_attribute.phtml
new file mode 100644
index 0000000000..a489c8f6a0
--- /dev/null
+++ b/templates/columns_definitions/column_attribute.phtml
@@ -0,0 +1,28 @@
+<?php
+$attribute_types = $GLOBALS['PMA_Types']->getAttributes();
+$cnt_attribute_types = count($attribute_types);
+
+$attribute = '';
+if (isset($submit_attribute) && $submit_attribute != false) {
+ $attribute = $submit_attribute;
+} elseif (isset($columnMeta['Extra'])
+ && $columnMeta['Extra'] == 'on update CURRENT_TIMESTAMP') {
+ $attribute = 'on update CURRENT_TIMESTAMP';
+} elseif (isset($extracted_columnspec['attribute'])) {
+ $attribute = $extracted_columnspec['attribute'];
+}
+
+$attribute = mb_strtoupper($attribute);
+?>
+<select style="width: 7em;"
+ name="field_attribute[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>">
+ <?php for ($j = 0; $j < $cnt_attribute_types; $j++): ?>
+ <option value="<?php echo $attribute_types[$j];?>"
+ <?php if ($attribute == /*overload*/mb_strtoupper($attribute_types[$j])): ?>
+ selected="selected"
+ <?php endif; ?>>
+ <?php echo $attribute_types[$j]; ?>
+ </option>
+ <?php endfor; ?>
+</select>
diff --git a/templates/columns_definitions/column_attributes.phtml b/templates/columns_definitions/column_attributes.phtml
new file mode 100644
index 0000000000..d01cfe686b
--- /dev/null
+++ b/templates/columns_definitions/column_attributes.phtml
@@ -0,0 +1,232 @@
+<?php
+// Cell index: If certain fields get left out, the counter shouldn't change.
+$ci = 0;
+
+// Every time a cell shall be left out the STRG-jumping feature, $ci_offset
+// has to be incremented ($ci_offset++)
+$ci_offset = -1;
+?>
+
+<td class="center">
+ <!-- column name -->
+ <?php echo PMA\Template::get('columns_definitions/column_name')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null,
+ 'cfgRelation' => $cfgRelation
+ )); ?>
+</td>
+<td class="center">
+ <!-- column type -->
+ <?php echo PMA\Template::get('columns_definitions/column_type')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'type_upper' => $type_upper,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null
+ )); ?>
+</td>
+<td class="center">
+ <!-- column length -->
+ <?php echo PMA\Template::get('columns_definitions/column_length')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'length_values_input_size' => $length_values_input_size,
+ 'length_to_display' => $length
+ )); ?>
+</td>
+<td class="center">
+ <!-- column default -->
+ <?php echo PMA\Template::get('columns_definitions/column_default')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'type_upper' => isset($type_upper) ? $type_upper : null,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null
+ )); ?>
+</td>
+<td class="center">
+ <!-- column collation -->
+ <?php $tmp_collation = empty($columnMeta['Collation']) ? null : $columnMeta['Collation']; ?>
+ <?php echo PMA_generateCharsetDropdownBox(
+ PMA_CSDROPDOWN_COLLATION,
+ 'field_collation[' . $columnNumber . ']',
+ 'field_' . $columnNumber . '_' . ($ci - $ci_offset),
+ $tmp_collation,
+ false
+ ); ?>
+</td>
+<td class="center">
+ <!-- column attribute -->
+ <?php echo PMA\Template::get('columns_definitions/column_attribute')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'extracted_columnspec' => isset($extracted_columnspec) ? $extracted_columnspec : null,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null,
+ 'submit_attribute' => isset($submit_attribute) ? $submit_attribute : null,
+ )); ?>
+</td>
+<td class="center">
+ <!-- column NULL -->
+ <?php echo PMA\Template::get('columns_definitions/column_null')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null
+ )); ?>
+</td>
+<?php if (isset($_REQUEST['change_column']) && !empty($_REQUEST['change_column']) && ! PMA_DRIZZLE): ?>
+ <!-- column Adjust privileges, Only for 'Edit' Column(s) -->
+ <td class="center">
+ <?php $privs_available = isset($GLOBALS['col_priv']) && $GLOBALS['col_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']; ?>
+ <?php echo PMA\Template::get('columns_definitions/column_adjust_privileges')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'privs_available' => $privs_available
+ )); ?>
+ </td>
+<?php endif; ?>
+<?php if (!$is_backup): ?>
+ <!-- column indexes, See my other comment about this 'if'. -->
+ <td class="center">
+ <?php echo PMA\Template::get('columns_definitions/column_indexes')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => $columnMeta
+ )); ?>
+ </td>
+<?php endif; ?>
+<td class="center">
+ <!-- column auto_increment -->
+ <?php echo PMA\Template::get('columns_definitions/column_auto_increment')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => $columnMeta
+ )); ?>
+</td>
+<td class="center">
+ <!-- column comments -->
+ <?php echo PMA\Template::get('columns_definitions/column_comment')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null,
+ 'comments_map' => $comments_map
+ )); ?>
+</td>
+ <!-- column virtuality -->
+<?php if (PMA_Util::isVirtualColumnsSupported()): ?>
+ <td class="center">
+ <?php echo PMA\Template::get('columns_definitions/column_virtuality')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => isset($columnMeta) ? $columnMeta : null
+ )); ?>
+ </td>
+<?php endif; ?>
+<!-- move column -->
+<?php if (isset($fields_meta)): ?>
+ <?php $current_index = 0;
+ for ($mi = 0, $cols = count($move_columns); $mi < $cols; $mi++) {
+ if ($move_columns[$mi]->name == $columnMeta['Field']) {
+ $current_index = $mi;
+ break;
+ }
+ } ?>
+
+ <td class="center">
+ <?php echo PMA\Template::get('columns_definitions/move_column')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => $columnMeta,
+ 'move_columns' => $move_columns,
+ 'current_index' => $current_index
+ )); ?>
+ </td>
+<?php endif; ?>
+
+<?php if ($cfgRelation['mimework'] && $GLOBALS['cfg']['BrowseMIME'] && $cfgRelation['commwork']): ?>
+ <td class="center">
+ <!-- Column Mime-type -->
+ <?php echo PMA\Template::get('columns_definitions/mime_type')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'available_mime' => $available_mime,
+ 'columnMeta' => $columnMeta,
+ 'mime_map' => $mime_map
+ )); ?>
+ </td>
+ <td class="center">
+ <!-- Column Browser transformation -->
+ <?php echo PMA\Template::get('columns_definitions/transformation')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'available_mime' => $available_mime,
+ 'columnMeta' => $columnMeta,
+ 'mime_map' => $mime_map,
+ 'type' => 'transformation'
+ )); ?>
+ </td>
+ <td class="center">
+ <!-- column Transformation options -->
+ <?php echo PMA\Template::get('columns_definitions/transformation_option')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => $columnMeta,
+ 'mime_map' => $mime_map,
+ 'type_prefix' => '',
+ )); ?>
+ </td>
+ <td class="center">
+ <!-- Column Input transformation -->
+ <?php echo PMA\Template::get('columns_definitions/transformation')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'available_mime' => $available_mime,
+ 'columnMeta' => $columnMeta,
+ 'mime_map' => $mime_map,
+ 'type' => 'input_transformation'
+ )); ?>
+ </td>
+ <td class="center">
+ <!-- column Input transformation options -->
+ <?php echo PMA\Template::get('columns_definitions/transformation_option')
+ ->render(array(
+ 'columnNumber' => $columnNumber,
+ 'ci' => $ci++,
+ 'ci_offset' => $ci_offset,
+ 'columnMeta' => $columnMeta,
+ 'mime_map' => $mime_map,
+ 'type_prefix' => 'input_',
+ )); ?>
+ </td>
+<?php endif; ?> \ No newline at end of file
diff --git a/templates/columns_definitions/column_auto_increment.phtml b/templates/columns_definitions/column_auto_increment.phtml
new file mode 100644
index 0000000000..f4d0b80aa2
--- /dev/null
+++ b/templates/columns_definitions/column_auto_increment.phtml
@@ -0,0 +1,8 @@
+<input name="field_extra[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber?>_<?php echo ($ci - $ci_offset); ?>"
+ <?php if (isset($columnMeta['Extra'])
+ && /*overload*/mb_strtolower($columnMeta['Extra']) == 'auto_increment'): ?>
+ checked="checked"
+ <?php endif; ?>
+ type="checkbox"
+ value="AUTO_INCREMENT" /> \ No newline at end of file
diff --git a/templates/columns_definitions/column_comment.phtml b/templates/columns_definitions/column_comment.phtml
new file mode 100644
index 0000000000..0cebce0f1d
--- /dev/null
+++ b/templates/columns_definitions/column_comment.phtml
@@ -0,0 +1,10 @@
+<input id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ type="text"
+ name="field_comments[<?php echo $columnNumber; ?>]"
+ size="12"
+ maxlength="<?php echo PMA_MYSQL_INT_VERSION >= 50503 ? 1024 : 255; ?>"
+ value="<?php if (isset($columnMeta['Field'])
+ && is_array($comments_map)
+ && isset($comments_map[$columnMeta['Field']]))
+ echo htmlspecialchars($comments_map[$columnMeta['Field']]); ?>"
+ class="textfield" /> \ No newline at end of file
diff --git a/templates/columns_definitions/column_default.phtml b/templates/columns_definitions/column_default.phtml
new file mode 100644
index 0000000000..e7c2694824
--- /dev/null
+++ b/templates/columns_definitions/column_default.phtml
@@ -0,0 +1,51 @@
+<?php
+// here we put 'NONE' as the default value of drop-down; otherwise
+// users would have problems if they forget to enter the default
+// value (example, for an INT)
+$default_options = array(
+ 'NONE' => _pgettext('for default', 'None'),
+ 'USER_DEFINED' => __('As defined:'),
+ 'NULL' => 'NULL',
+ 'CURRENT_TIMESTAMP' => 'CURRENT_TIMESTAMP',
+);
+
+// for a TIMESTAMP, do not show the string "CURRENT_TIMESTAMP" as a default
+// value
+$defaultValue = '';
+if (isset($columnMeta['DefaultValue'])) {
+ $defaultValue = $columnMeta['DefaultValue'];
+}
+if ($type_upper == 'BIT') {
+ $defaultValue = PMA_Util::convertBitDefaultValue($columnMeta['DefaultValue']);
+} elseif ($type_upper == 'BINARY' || $type_upper == 'VARBINARY') {
+ $defaultValue = bin2hex($columnMeta['DefaultValue']);
+}
+?>
+
+<select name="field_default_type[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo($ci - $ci_offset); ?>"
+ class="default_type">
+ <?php foreach ($default_options as $key => $value): ?>
+ <option value="<?php echo $key; ?>"
+ <?php if (isset($columnMeta['DefaultType']) && $columnMeta['DefaultType'] == $key): ?>
+ selected="selected"
+ <?php endif; ?>>
+ <?php echo $value; ?>
+ </option>
+ <?php endforeach; ?>
+</select>
+<br />
+<?php if ($GLOBALS['cfg']['CharEditing'] == 'textarea'): ?>
+ <textarea name="field_default_value[<?php echo $columnNumber; ?>]"
+ cols="15"
+ class="textfield
+ default_value">
+ <?php echo htmlspecialchars($defaultValue); ?>
+ </textarea>
+<?php else: ?>
+ <input type="text"
+ name="field_default_value[<?php echo $columnNumber; ?>]"
+ size="12"
+ value="<?php echo htmlspecialchars($defaultValue); ?>"
+ class="textfield default_value" />
+<?php endif; ?> \ No newline at end of file
diff --git a/templates/columns_definitions/column_definitions_form.phtml b/templates/columns_definitions/column_definitions_form.phtml
new file mode 100644
index 0000000000..5d0fea7ba9
--- /dev/null
+++ b/templates/columns_definitions/column_definitions_form.phtml
@@ -0,0 +1,169 @@
+<form method="post"
+ action="<?php echo $action; ?>"
+ class="<?php echo ($action == 'tbl_create.php' ? 'create_table' : 'append_fields'); ?>_form ajax lock-page">
+ <?php echo PMA_URL_getHiddenInputs($form_params); ?>
+ <input type="hidden"
+ name="primary_indexes"
+ value="<?php if (! empty($_REQUEST['primary_indexes'])) {
+ // happens when an index has been set on a column,
+ // and a column is added to the table creation dialog
+ //
+ // this contains a JSON-encoded string
+ echo htmlspecialchars($_REQUEST['primary_indexes']);
+ } else echo '[]'; ?>">
+ <input type="hidden"
+ name="unique_indexes"
+ value="<?php if (! empty($_REQUEST['unique_indexes'])) {
+ echo htmlspecialchars($_REQUEST['unique_indexes']);
+ } else echo '[]'; ?>">
+ <input type="hidden"
+ name="indexes"
+ value="<?php if (! empty($_REQUEST['indexes'])) {
+ echo htmlspecialchars($_REQUEST['indexes']);
+ } else echo '[]'; ?>">
+ <input type="hidden"
+ name="fulltext_indexes"
+ value="<?php if (! empty($_REQUEST['fulltext_indexes'])) {
+ echo htmlspecialchars($_REQUEST['fulltext_indexes']);
+ } else echo '[]'; ?>">
+ <input type="hidden"
+ name="spatial_indexes"
+ value="<?php if (! empty($_REQUEST['spatial_indexes'])) {
+ echo htmlspecialchars($_REQUEST['spatial_indexes']);
+ } else echo '[]'; ?>">
+
+ <?php if ($action == 'tbl_create.php'): ?>
+ <div id="table_name_col_no_outer">
+ <table id="table_name_col_no">
+ <tr class="vmiddle floatleft">
+ <td><?php echo __('Table name'); ?>:&nbsp;
+ <input type="text"
+ name="table"
+ size="40"
+ maxlength="64"
+ value="<?php echo (isset($_REQUEST['table']) ? htmlspecialchars($_REQUEST['table']) : ''); ?>"
+ class="textfield" autofocus required />
+ </td>
+ <td>
+ Add
+ <input type="number"
+ id="added_fields"
+ name="added_fields"
+ size="2"
+ value="1"
+ min="1"
+ onfocus="this.select()" />
+ column(s)
+ <input type="button"
+ name="submit_num_fields"
+ value="<?php echo __('Go'); ?>" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ <?php endif; ?>
+ <?php if (is_array($content_cells)): ?>
+ <?php echo PMA\Template::get(
+ 'columns_definitions/table_fields_definitions'
+ )->render(array(
+ 'is_backup' => $is_backup,
+ 'fields_meta' => $fields_meta,
+ 'mimework' => $mimework,
+ 'content_cells' => $content_cells
+ )); ?>
+ <?php endif; ?>
+ <?php if ($action == 'tbl_create.php'): ?>
+ <table>
+ <tr class="vtop">
+ <th>
+ <?php echo __('Table comments:'); ?>
+ </th>
+ <td width="25">&nbsp;</td>
+ <th>
+ <?php echo __('Collation:'); ?>
+ </th>
+ <td width="25">&nbsp;</td>
+ <th>
+ <?php echo __('Storage Engine:'); ?>
+ <?php echo PMA_Util::showMySQLDocu('Storage_engines'); ?>
+ </th>
+ <td width="25">&nbsp;</td>
+ <th>
+ <?php echo __('Connection:'); ?>
+ <?php echo PMA_Util::showMySQLDocu('federated-create-connection'); ?>
+ </th>
+ </tr>
+ <tr>
+ <td>
+ <input type="text"
+ name="comment"
+ size="40"
+ maxlength="60"
+ value="<?php echo (isset($_REQUEST['comment']) ? htmlspecialchars($_REQUEST['comment']): ''); ?>"
+ class="textfield" />
+ </td>
+ <td width="25">&nbsp;</td>
+ <td>
+ <?php echo PMA_generateCharsetDropdownBox(
+ PMA_CSDROPDOWN_COLLATION,
+ 'tbl_collation',
+ null,
+ isset($_REQUEST['tbl_collation']) ? $_REQUEST['tbl_collation'] : null,
+ false
+ ); ?>
+ </td>
+ <td width="25">&nbsp;</td>
+ <td>
+ <?php echo PMA_StorageEngine::getHtmlSelect(
+ 'tbl_storage_engine',
+ null,
+ (isset($_REQUEST['tbl_storage_engine']) ? $_REQUEST['tbl_storage_engine'] : null)
+ ); ?>
+ </td>
+ <td width="25">&nbsp;</td>
+ <td>
+ <input type="text"
+ name="connection"
+ size="40"
+ value="<?php echo (isset($_REQUEST['connection']) ? htmlspecialchars($_REQUEST['connection']) : ''); ?>"
+ placeholder="scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name"
+ class="textfield"
+ required="required" />
+ </td>
+ </tr>
+ <?php if (PMA_Partition::havePartitioning()): ?>
+ <tr class="vtop">
+ <th>
+ <?php echo __('PARTITION definition:'); ?>
+ &nbsp;
+ <?php echo PMA_Util::showMySQLDocu('Partitioning'); ?>
+ </th>
+ </tr>
+ <tr>
+ <td>
+ <textarea name="partition_definition"
+ id="partitiondefinition"
+ cols="<?php echo $GLOBALS['cfg']['TextareaCols']; ?>"
+ rows="<?php echo $GLOBALS['cfg']['TextareaRows']; ?>"
+ dir="<?php echo $GLOBALS['text_dir']; ?>">
+
+ <?php echo (isset($_REQUEST['partition_definition']) ? htmlspecialchars($_REQUEST['partition_definition']) : ''); ?>
+
+ </textarea>
+ </td>
+ </tr>
+ <?php endif; ?>
+ </table>
+ <br />
+ <?php endif; ?>
+ <fieldset class="tblFooters">
+ <input type="button"
+ class="preview_sql"
+ value="<?php echo __('Preview SQL') ?>" />
+ <input type="submit"
+ name="do_save_data"
+ value="<?php echo __('Save'); ?>" />
+ </fieldset>
+ <div id="properties_message">
+ </div>
+</form>
diff --git a/templates/columns_definitions/column_extra.phtml b/templates/columns_definitions/column_extra.phtml
new file mode 100644
index 0000000000..8c8a2907d7
--- /dev/null
+++ b/templates/columns_definitions/column_extra.phtml
@@ -0,0 +1,7 @@
+<input name="col_extra[<?php echo $columnNumber;?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ <?php if (! empty($columnMeta['Extra']) && $columnMeta['Extra'] == 'auto_increment'): ?>
+ checked="checked"
+ <?php endif; ?>
+ type="checkbox"
+ value="auto_increment" /> \ No newline at end of file
diff --git a/templates/columns_definitions/column_indexes.phtml b/templates/columns_definitions/column_indexes.phtml
new file mode 100644
index 0000000000..01cd219b6b
--- /dev/null
+++ b/templates/columns_definitions/column_indexes.phtml
@@ -0,0 +1,32 @@
+<select name="field_key[<?php echo $columnNumber;?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset);?>"
+ data-index="">
+ <option value="none_<?php echo $columnNumber; ?>">---</option>
+ <option value="primary_<?php echo $columnNumber; ?>"
+ title="<?php echo __("Primary"); ?>"
+ <?php echo ((isset($columnMeta['Key']) && $columnMeta['Key'] == 'PRI') ? 'selected="selected"' : '');?>>
+ PRIMARY
+ </option>
+ <option value="unique_<?php echo $columnNumber; ?>"
+ title="<?php echo __("Unique"); ?>"
+ <?php echo ((isset($columnMeta['Key']) && $columnMeta['Key'] == 'UNI') ? 'selected="selected"' : '');?>>
+ UNIQUE
+ </option>
+ <option value="index_<?php echo $columnNumber; ?>"
+ title="<?php echo __("Index"); ?>"
+ <?php echo ((isset($columnMeta['Key']) && $columnMeta['Key'] == 'MUL') ? 'selected="selected"' : '');?>>
+ INDEX
+ </option>
+ <?php if (!PMA_DRIZZLE): ?>
+ <option value="fulltext_<?php echo $columnNumber; ?>"
+ title="<?php echo __("Fulltext"); ?>"
+ <?php echo ((isset($columnMeta['Key']) && $columnMeta['Key'] == 'FULLTEXT') ? 'selected="selected"' : '');?>>
+ FULLTEXT
+ </option>
+ <option value="spatial_<?php echo $columnNumber; ?>"
+ title="<?php echo __("Spatial"); ?>"
+ <?php echo ((isset($columnMeta['Key']) && $columnMeta['Key'] == 'SPATIAL') ? 'selected="selected"' : '');?>>
+ SPATIAL
+ </option>
+ <?php endif; ?>
+</select> \ No newline at end of file
diff --git a/templates/columns_definitions/column_length.phtml b/templates/columns_definitions/column_length.phtml
new file mode 100644
index 0000000000..aa237293a1
--- /dev/null
+++ b/templates/columns_definitions/column_length.phtml
@@ -0,0 +1,11 @@
+<input id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ type="text"
+ name="field_length[<?php echo $columnNumber; ?>]"
+ size="<?php echo $length_values_input_size ?>"
+ value="<?php echo htmlspecialchars($length_to_display); ?>"
+ class="textfield" />
+<p class="enum_notice" id="enum_notice_<?php echo $columnNumber ?>_<?php echo ($ci - $ci_offset); ?>">
+ <a href="#" class="open_enum_editor">
+ <?php echo __('Edit ENUM/SET values'); ?>
+ </a>
+</p> \ No newline at end of file
diff --git a/templates/columns_definitions/column_name.phtml b/templates/columns_definitions/column_name.phtml
new file mode 100644
index 0000000000..4706e17a38
--- /dev/null
+++ b/templates/columns_definitions/column_name.phtml
@@ -0,0 +1,47 @@
+<?php
+$title = '';
+if (isset($columnMeta['column_status'])) {
+ if ($columnMeta['column_status']['isReferenced']) {
+ $title .= sprintf(
+ __('Referenced by %s.'),
+ implode(",", $columnMeta['column_status']['references'])
+ );
+ }
+ if ($columnMeta['column_status']['isForeignKey']) {
+ if (!empty($title)) {
+ $title .= "\n";
+ }
+ $title .= __('Is a foreign key.');
+ }
+}
+if (empty($title)) {
+ $title = __('Column');
+}
+?>
+<input id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ <?php if (isset($columnMeta['column_status'])
+ && !$columnMeta['column_status']['isEditable']): ?>
+ disabled="disabled"
+ <?php endif; ?>
+ type="text"
+ name="field_name[<?php echo $columnNumber; ?>]"
+ maxlength="64"
+ class="textfield"
+ title="<?php echo $title; ?>"
+ size="10"
+ value="<?php if (isset($columnMeta['Field']))
+ echo htmlspecialchars($columnMeta['Field']); ?>" />
+
+<?php if ($cfgRelation['centralcolumnswork']
+ && !(isset($columnMeta['column_status'])
+ && !$columnMeta['column_status']['isEditable'])
+): ?>
+ <p style="font-size:80%;margin:5px 2px"
+ id="central_columns_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>">
+ <a data-maxrows="<?php echo $GLOBALS['cfg']['MaxRows']; ?>"
+ href="#"
+ class="central_columns_dialog">
+ <?php echo __('Pick from Central Columns'); ?>
+ </a>
+ </p>
+<?php endif; ?> \ No newline at end of file
diff --git a/templates/columns_definitions/column_null.phtml b/templates/columns_definitions/column_null.phtml
new file mode 100644
index 0000000000..5902f13ff0
--- /dev/null
+++ b/templates/columns_definitions/column_null.phtml
@@ -0,0 +1,8 @@
+<input name="field_null[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ <?php if (! empty($columnMeta['Null']) && $columnMeta['Null'] != 'NO' && $columnMeta['Null'] != 'NOT NULL'): ?>
+ checked="checked"
+ <?php endif; ?>
+ type="checkbox"
+ value="NULL"
+ class="allow_null"/> \ No newline at end of file
diff --git a/templates/columns_definitions/column_type.phtml b/templates/columns_definitions/column_type.phtml
new file mode 100644
index 0000000000..a32c1732aa
--- /dev/null
+++ b/templates/columns_definitions/column_type.phtml
@@ -0,0 +1,7 @@
+<select class="column_type"
+ name="field_type[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ <?php if (isset($columnMeta['column_status']) && !$columnMeta['column_status']['isEditable'])
+ echo 'disabled="disabled"'; ?>>
+ <?php echo PMA_Util::getSupportedDatatypes(true, $type_upper); ?>
+</select> \ No newline at end of file
diff --git a/templates/columns_definitions/column_virtuality.phtml b/templates/columns_definitions/column_virtuality.phtml
new file mode 100644
index 0000000000..ac4f2dfdf0
--- /dev/null
+++ b/templates/columns_definitions/column_virtuality.phtml
@@ -0,0 +1,48 @@
+<?php
+$options = array(
+ '' => '',
+ 'VIRTUAL' => 'VIRTUAL',
+);
+$serverType = PMA_Util::getServerType();
+if ($serverType == 'MariaDB') {
+ $options['PERSISTENT'] = 'PERSISTENT';
+} else {
+ $options['STORED'] = 'STORED';
+}
+
+$expression = '';
+if (isset($columnMeta['Expression'])) {
+ $expression = $columnMeta['Expression'];
+}
+?>
+
+<select name="field_virtuality[<?php echo $columnNumber; ?>]"
+ id="field_<?php echo $columnNumber; ?>_<?php echo($ci - $ci_offset); ?>"
+ class="virtuality">
+ <?php foreach ($options as $key => $value): ?>
+ <option value="<?php echo $key; ?>"
+ <?php if (isset($columnMeta['Extra'])
+ && $key != ''
+ && strpos($columnMeta['Extra'], $key) === 0): ?>
+ selected="selected"
+ <?php endif; ?>>
+ <?php echo $value; ?>
+ </option>
+ <?php endforeach; ?>
+</select>
+<br />
+<?php if ($GLOBALS['cfg']['CharEditing'] == 'textarea'): ?>
+ <textarea name="field_expression[<?php echo $columnNumber; ?>]"
+ cols="15"
+ class="textfield
+ expression">
+ <?php echo htmlspecialchars($expression); ?>
+ </textarea>
+<?php else: ?>
+ <input type="text"
+ name="field_expression[<?php echo $columnNumber; ?>]"
+ size="12"
+ value="<?php echo htmlspecialchars($expression); ?>"
+ placeholder="<?php echo __('Expression'); ?>"
+ class="textfield expression" />
+<?php endif; ?> \ No newline at end of file
diff --git a/templates/columns_definitions/mime_type.phtml b/templates/columns_definitions/mime_type.phtml
new file mode 100644
index 0000000000..9f81e67d61
--- /dev/null
+++ b/templates/columns_definitions/mime_type.phtml
@@ -0,0 +1,17 @@
+<select id="field_<?php echo $columnNumber;?>_<?php echo($ci - $ci_offset); ?>"
+ size="1"
+ name="field_mimetype[<?php echo $columnNumber; ?>]">
+ <option value="">&nbsp;</option>
+ <?php if (isset($available_mime['mimetype'])
+ && is_array($available_mime['mimetype'])): ?>
+ <?php foreach ($available_mime['mimetype'] as $mimetype): ?>
+ <?php $checked = (isset($columnMeta['Field'])
+ && isset($mime_map[$columnMeta['Field']]['mimetype'])
+ && ($mime_map[$columnMeta['Field']]['mimetype'] == str_replace('/', '_', $mimetype))
+ ? 'selected ' : '');?>
+ <option value="<?php echo str_replace('/', '_', $mimetype)?>" <?php echo $checked; ?>>
+ <?php echo htmlspecialchars(strtolower($mimetype)); ?>
+ </option>
+ <?php endforeach; ?>
+ <?php endif; ?>
+</select> \ No newline at end of file
diff --git a/templates/columns_definitions/move_column.phtml b/templates/columns_definitions/move_column.phtml
new file mode 100644
index 0000000000..70d49d9291
--- /dev/null
+++ b/templates/columns_definitions/move_column.phtml
@@ -0,0 +1,15 @@
+<select id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ name="field_move_to[<?php echo $columnNumber; ?>]"
+ size="1"
+ width="5em">
+ <option value="" selected="selected">&nbsp;</option>
+ <option value="-first" <?php echo ($current_index == 0 ? ' disabled="disabled"' : ''); ?>>
+ <?php echo __('first'); ?>
+ </option>
+ <?php for ($mi = 0, $cols = count($move_columns); $mi < $cols; $mi++): ?>
+ <option value="<?php echo htmlspecialchars($move_columns[$mi]->name); ?>"
+ <?php echo (($current_index == $mi || $current_index == $mi + 1) ? ' disabled="disabled"' : '');?>>
+ <?php echo sprintf(__('after %s'), PMA_Util::backquote(htmlspecialchars($move_columns[$mi]->name))); ?>
+ </option>
+ <?php endfor; ?>
+</select> \ No newline at end of file
diff --git a/templates/columns_definitions/table_fields_definitions.phtml b/templates/columns_definitions/table_fields_definitions.phtml
new file mode 100644
index 0000000000..46981922e7
--- /dev/null
+++ b/templates/columns_definitions/table_fields_definitions.phtml
@@ -0,0 +1,133 @@
+<table id="table_columns" class="noclick">
+ <caption class="tblHeaders">
+ <?php echo __('Structure'); ?>
+ <?php echo PMA_Util::showMySQLDocu('CREATE_TABLE'); ?>
+ </caption>
+ <tr>
+ <th>
+ <?php echo __('Name'); ?>
+ </th>
+ <th>
+ <?php echo __('Type') . PMA_Util::showMySQLDocu('data-types'); ?>
+ </th>
+ <th>
+ <?php echo __('Length/Values') . PMA_Util::showHint(
+ __(
+ 'If column type is "enum" or "set", please enter the values using'
+ . ' this format: \'a\',\'b\',\'c\'…<br />If you ever need to put'
+ . ' a backslash ("\") or a single quote ("\'") amongst those'
+ . ' values, precede it with a backslash (for example \'\\\\xyz\''
+ . ' or \'a\\\'b\').'
+ )
+ ); ?>
+ </th>
+ <th>
+ <?php echo __('Default') . PMA_Util::showHint(
+ __(
+ 'For default values, please enter just a single value,'
+ . ' without backslash escaping or quotes, using this format: a'
+ )
+ ); ?>
+ </th>
+ <th>
+ <?php echo __('Collation'); ?>
+ </th>
+ <th>
+ <?php echo __('Attributes'); ?>
+ </th>
+ <th>
+ <?php echo __('Null'); ?>
+ </th>
+
+ <!-- Only for 'Edit' Column(s) -->
+ <?php if (isset($_REQUEST['change_column'])
+ && ! empty($_REQUEST['change_column'])
+ ): ?>
+ <th>
+ <?php echo __('Adjust privileges') . PMA_Util::showDocu('faq', 'faq6-39'); ?>
+ </th>
+ <?php endif; ?>
+
+ <?php
+ // We could remove this 'if' and let the key information be shown and
+ // editable. However, for this to work, structure.lib.php must be modified
+ // to use the key fields, as tbl_addfield does.
+ if (!$is_backup): ?>
+ <th>
+ <?php echo __('Index'); ?>
+ </th>
+ <?php endif; ?>
+
+ <th>
+ <abbr title="AUTO_INCREMENT">A_I</abbr>
+ </th>
+ <th>
+ <?php echo __('Comments'); ?>
+ </th>
+
+ <?php if (PMA_Util::isVirtualColumnsSupported()): ?>
+ <th>
+ <?php echo __('Virtuality'); ?>
+ </th>
+ <?php endif; ?>
+
+ <?php if (isset($fields_meta)): ?>
+ <th>
+ <?php echo __('Move column'); ?>
+ </th>
+ <?php endif; ?>
+
+ <?php if ($mimework && $GLOBALS['cfg']['BrowseMIME']): ?>
+ <th>
+ <?php echo __('MIME type'); ?>
+ </th>
+ <th>
+ <a href="transformation_overview.php<?php echo PMA_URL_getCommon(); ?>#transformation"
+ title="<?php echo __('List of available transformations and their options'); ?>"
+ target="_blank">
+ <?php echo __('Browser display transformation'); ?>
+ </a>
+ </th>
+ <th>
+ <?php echo __('Browser display transformation options'); ?>
+ <?php echo PMA_Util::showHint(
+ __(
+ 'Please enter the values for transformation options using this'
+ . ' format: \'a\', 100, b,\'c\'…<br />If you ever need to put'
+ . ' a backslash ("\") or a single quote ("\'") amongst those'
+ . ' values, precede it with a backslash (for example \'\\\\xyz\''
+ . ' or \'a\\\'b\').'
+ )
+ ); ?>
+ </th>
+ <th>
+ <a href="transformation_overview.php<?php echo PMA_URL_getCommon(); ?>#input_transformation"
+ title="<?php echo __('List of available transformations and their options'); ?>"
+ target="_blank">
+ <?php echo __('Input transformation'); ?>
+ </a>
+ </th>
+ <th>
+ <?php echo __('Input transformation options'); ?>
+ <?php echo PMA_Util::showHint(
+ __(
+ 'Please enter the values for transformation options using this'
+ . ' format: \'a\', 100, b,\'c\'…<br />If you ever need to put'
+ . ' a backslash ("\") or a single quote ("\'") amongst those'
+ . ' values, precede it with a backslash (for example \'\\\\xyz\''
+ . ' or \'a\\\'b\').'
+ )
+ ); ?>
+ </th>
+ <?php endif; ?>
+ </tr>
+ <?php $odd_row = true;?>
+ <?php foreach($content_cells as $content_row): ?>
+ <tr class="<?php echo ($odd_row ? 'odd' : 'even'); ?>">
+ <?php $odd_row = !$odd_row; ?>
+ <?php echo PMA\Template::get('columns_definitions/column_attributes')
+ ->render($content_row); ?>
+ </tr>
+ <?php endforeach; ?>
+</table>
+<br /> \ No newline at end of file
diff --git a/templates/columns_definitions/transformation.phtml b/templates/columns_definitions/transformation.phtml
new file mode 100644
index 0000000000..292ee67d0e
--- /dev/null
+++ b/templates/columns_definitions/transformation.phtml
@@ -0,0 +1,27 @@
+<select id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ size="1"
+ name="field_<?php echo $type;?>[<?php echo $columnNumber;?>]">
+ <option value="" title="<?php echo __('None'); ?>"></option>
+ <?php if (isset($available_mime[$type]) && is_array($available_mime[$type])): ?>
+ <?php foreach ($available_mime[$type] as $mimekey => $transform): ?>
+ <?php
+ $checked = isset($columnMeta['Field'])
+ && isset($mime_map[$columnMeta['Field']][$type])
+ && preg_match('@' . preg_quote($available_mime[$type . '_file'][$mimekey]) . '3?@i',
+ $mime_map[$columnMeta['Field']][$type]) ? 'selected ' : '';
+ $tooltip = PMA_getTransformationDescription(
+ $available_mime[$type . '_file'][$mimekey]
+ );
+ $parts = explode(":", $transform);
+ $name = PMA_getTransformationName(
+ $available_mime[$type . '_file'][$mimekey]
+ ) . ' (' . strtolower($parts[0]) . ":" . $parts[1] . ')';
+ ?>
+ <option value="<?php echo $available_mime[$type . '_file'][$mimekey]; ?>"
+ <?php echo $checked; ?>
+ title="<?php echo htmlspecialchars($tooltip); ?>">
+ <?php echo htmlspecialchars($name); ?>
+ </option>
+ <?php endforeach; ?>
+ <?php endif; ?>
+</select> \ No newline at end of file
diff --git a/templates/columns_definitions/transformation_option.phtml b/templates/columns_definitions/transformation_option.phtml
new file mode 100644
index 0000000000..e5ad1d3fbf
--- /dev/null
+++ b/templates/columns_definitions/transformation_option.phtml
@@ -0,0 +1,12 @@
+<?php $options_key = $type_prefix . 'transformation_options'; ?>
+<input id="field_<?php echo $columnNumber; ?>_<?php echo ($ci - $ci_offset); ?>"
+ type="text"
+ name="field_<?php echo $options_key; ?>[<?php echo $columnNumber; ?>]"
+ size="16"
+ class="textfield"
+ value="<?php if (isset($columnMeta['Field'])
+ && isset($mime_map[$columnMeta['Field']][$options_key]))
+ echo htmlspecialchars(
+ $mime_map[$columnMeta['Field']]
+ [$options_key]
+ ); ?>" /> \ No newline at end of file
diff --git a/templates/components/error_message.phtml b/templates/components/error_message.phtml
new file mode 100644
index 0000000000..0e2ddc6c37
--- /dev/null
+++ b/templates/components/error_message.phtml
@@ -0,0 +1,4 @@
+<div class="error">
+ <img src="themes/dot.gif" title="" alt="" class="icon ic_s_error" />
+ <?php echo $msg; ?>
+</div> \ No newline at end of file
diff --git a/templates/database/create_table.phtml b/templates/database/create_table.phtml
new file mode 100644
index 0000000000..a4820c9e80
--- /dev/null
+++ b/templates/database/create_table.phtml
@@ -0,0 +1,23 @@
+<form id="create_table_form_minimal" method="post" action="tbl_create.php" class="lock-page">
+ <fieldset>
+ <legend>
+ <?php if (PMA_Util::showIcons('ActionLinksMode')): ?>
+ <?php echo PMA_Util::getImage('b_table_add.png'); ?>&nbsp
+ <?php endif; ?>
+ <?php echo __('Create table'); ?>
+ </legend>
+ <?php echo PMA_URL_getHiddenInputs($db); ?>
+ <div class="formelement">
+ <?php echo __('Name'); ?>:
+ <input type="text" name="table" maxlength="64" size="30" required="required" />
+ </div>
+ <div class="formelement">
+ <?php echo __('Number of columns'); ?>:
+ <input type="number" min="1" name="num_fields" value="4" required="required" />
+ </div>
+ <div class="clearfloat"></div>
+ </fieldset>
+ <fieldset class="tblFooters">
+ <input type="submit" value="<?php echo __('Go'); ?>" />
+ </fieldset>
+</form>
diff --git a/templates/database/designer/aggregate_query_panel.phtml b/templates/database/designer/aggregate_query_panel.phtml
new file mode 100644
index 0000000000..cac8d1f82e
--- /dev/null
+++ b/templates/database/designer/aggregate_query_panel.phtml
@@ -0,0 +1,84 @@
+<table id="query_Aggregate" style="display:none;"width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%" >
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="168" class="center" cellpadding="2" cellspacing="0">
+ <thead>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <strong>
+ <?php echo __('Aggregate'); ?>
+ </strong>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Operator'); ?>
+ </td>
+ <td width="102">
+ <select name="operator" id="e_operator">
+ <option value="---" selected="selected">
+ ---
+ </option>
+ <option value="sum" >
+ SUM
+ </option>
+ <option value="min">
+ MIN
+ </option>
+ <option value="max">
+ MAX
+ </option>
+ <option value="avg">
+ AVG
+ </option>
+ <option value="count">
+ COUNT
+ </option>
+ </select>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <input type="button" id="ok_edit_Aggr" class="butt" name="Button" value="<?php echo __('OK'); ?>" />
+ <input type="button"
+ class="butt"
+ name="Button"
+ value="<?php echo __('Cancel'); ?>"
+ onclick="document.getElementById('query_Aggregate').style.display = 'none';" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/designer/canvas.phtml b/templates/database/designer/canvas.phtml
new file mode 100644
index 0000000000..5110ccc0a7
--- /dev/null
+++ b/templates/database/designer/canvas.phtml
@@ -0,0 +1,3 @@
+<div id="osn_tab">
+ <canvas class="pmd" id="canvas" width="100" height="100" ></canvas>
+</div> \ No newline at end of file
diff --git a/templates/database/designer/database_tables.phtml b/templates/database/designer/database_tables.phtml
new file mode 100644
index 0000000000..9f4803329b
--- /dev/null
+++ b/templates/database/designer/database_tables.phtml
@@ -0,0 +1,140 @@
+<?php for ($i = 0; $i < count($GLOBALS['PMD']["TABLE_NAME"]); $i++) :
+ $t_n = $GLOBALS['PMD']["TABLE_NAME"][$i];
+ $t_n_url = $GLOBALS['PMD_URL']["TABLE_NAME"][$i]; ?>
+ <input name="t_x[<?php echo $t_n_url; ?>]" type="hidden" id="t_x_<?php echo $t_n_url; ?>_" />
+ <input name="t_y[<?php echo $t_n_url; ?>]" type="hidden" id="t_y_<?php echo $t_n_url; ?>_" />
+ <input name="t_v[<?php echo $t_n_url; ?>]" type="hidden" id="t_v_<?php echo $t_n_url; ?>_" />
+ <input name="t_h[<?php echo $t_n_url; ?>]" type="hidden" id="t_h_<?php echo $t_n_url; ?>_" />
+ <!-- Why should we put styles here?! -->
+ <table id="<?php echo $t_n_url; ?>"
+ cellpadding="0"
+ cellspacing="0"
+ class="pmd_tab"
+ style="position:absolute; left:<?php echo (isset($tab_pos[$t_n]) ? $tab_pos[$t_n]["X"] : rand(20, 700)); ?>px; top:<?php echo (isset($tab_pos[$t_n]) ? $tab_pos[$t_n]["Y"] : rand(20, 550)); ?>px; display:<?php echo (isset($tab_pos[$t_n]) || $display_page == -1) ? 'block;' : 'none';?>; z-index: 1;">
+ <thead>
+ <tr class="header">
+ <?php if (isset($_REQUEST['query'])) : ?>
+ <td class="select_all">
+ <input class="select_all_1"
+ type="checkbox"
+ style="margin: 0;"
+ value="select_all_<?php echo htmlspecialchars($t_n_url); ?>"
+ id="select_all_<?php echo htmlspecialchars($t_n_url); ?>"
+ title="select all"
+ pmd_url_table_name="<?php echo htmlspecialchars($t_n_url); ?>"
+ pmd_out_owner="<?php echo htmlspecialchars($GLOBALS['PMD_OUT']['OWNER'][$i]); ?>">
+ </td>
+ <?php endif; ?>
+ <td class="small_tab"
+ title="<?php echo __('Show/hide columns'); ?>"
+ id="id_hide_tbody_<?php echo $t_n_url; ?>"
+ table_name="<?php echo htmlspecialchars($t_n_url); ?>"
+ onmouseover="this.className='small_tab2';"
+ onmouseout="this.className='small_tab';" ><?php echo (! isset($tab_pos[$t_n]) || ! empty($tab_pos[$t_n]["V"])) ? 'v' : '&gt;'; ?>
+ </td>
+ <td class="small_tab_pref small_tab_pref_1"
+ table_name_small="<?php echo $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i]; ?>"
+ onmouseover="this.className='small_tab_pref2 small_tab_pref_1';"
+ onmouseout="this.className='small_tab_pref small_tab_pref_1';" >
+ <img src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/exec_small.png'); ?>"
+ title="<?php echo __('See table structure'); ?>" />
+ </td>
+ <td id="id_zag_<?php echo htmlspecialchars($t_n_url); ?>"
+ class="tab_zag nowrap tab_zag_noquery"
+ onmousedown="cur_click=document.getElementById('<?php echo $t_n_url; ?>');"
+ table_name="<?php echo htmlspecialchars($t_n_url); ?>"
+ query_set="<?php echo isset($_REQUEST['query']) ? 1 : 0 ; ?>" >
+ <span class="owner">
+ <?php echo $GLOBALS['PMD_OUT']["OWNER"][$i]; ?>
+ </span>
+ <?php echo $GLOBALS['PMD_OUT']['TABLE_NAME_SMALL'][$i]; ?>
+ </td>
+ <?php if (isset($_REQUEST['query'])) : ?>
+ <td class="tab_zag tab_zag_query"
+ id="id_zag_<?php echo htmlspecialchars($t_n_url); ?>_2"
+ table_name="<?php echo htmlspecialchars($t_n_url); ?>"
+ onmousedown="cur_click=document.getElementById('<?php echo htmlspecialchars($t_n_url); ?>');">
+ </td>
+ <?php endif; ?>
+ </tr>
+ </thead>
+ <tbody id="id_tbody_<?php echo $t_n_url; ?>" style="<?php echo (isset($tab_pos[$t_n]) && empty($tab_pos[$t_n]["V"])) ? 'display: none' : ''; ?>">
+ <?php $display_field = PMA_getDisplayField(
+ $_GET['db'],
+ $GLOBALS['PMD']["TABLE_NAME_SMALL"][$i]
+ );
+ for ($j = 0, $id_cnt = count($tab_column[$t_n]["COLUMN_ID"]); $j < $id_cnt; $j++) :
+ $tmpColumn = $t_n . "." . $tab_column[$t_n]["COLUMN_NAME"][$j];
+ $click_field_param = array(
+ $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i],
+ urlencode($tab_column[$t_n]["COLUMN_NAME"][$j])
+ );
+ if (!PMA_Util::isForeignKeySupported($GLOBALS['PMD']['TABLE_TYPE'][$i])) {
+ $click_field_param[] = isset($tables_pk_or_unique_keys[$tmpColumn]) ? 1 : 0;
+ } else {
+ // if foreign keys are supported, it's not necessary that the
+ // index is a primary key
+ $click_field_param[] = isset($tables_all_keys[$tmpColumn]) ? 1 : 0;
+ }
+ ?>
+ <tr id="id_tr_<?php echo $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i]; ?>.<?php echo urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]); ?>"
+ <?php echo ($display_field == $tab_column[$t_n]["COLUMN_NAME"][$j]) ? 'class="tab_field_3"' : 'class="tab_field"'; ?>
+ onmouseover="old_class = this.className; this.className = 'tab_field_2';"
+ onmouseout="this.className = old_class;"
+ click_field_param="<?php echo implode($click_field_param, ','); ?>">
+ <?php if (isset($_REQUEST['query'])) : ?>
+ <td class="select_all">
+ <input class="select_all_store_col"
+ value="<?php echo htmlspecialchars($t_n_url) . urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]); ?>"
+ type="checkbox"
+ id="select_<?php echo htmlspecialchars($t_n_url); ?>._<?php echo urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]); ?>"
+ style="margin: 0;"
+ title="select_<?php echo urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]); ?>"
+ store_column_param="<?php echo urlencode($GLOBALS['PMD_OUT']["TABLE_NAME_SMALL"][$i]); ?>,<?php echo htmlspecialchars($GLOBALS['PMD_OUT']["OWNER"][$i]); ?>,<?php echo urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]); ?>">
+ </td>
+ <?php endif; ?>
+ <td width="10px" colspan="3" id="<?php echo $t_n_url; ?>.<?php echo urlencode($tab_column[$t_n]["COLUMN_NAME"][$j]); ?>">
+ <div class="nowrap">
+ <?php if (isset($tables_pk_or_unique_keys[$t_n . "." . $tab_column[$t_n]["COLUMN_NAME"][$j]])) : ?>
+ <img src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/FieldKey_small.png'); ?>" alt="*" />
+ <?php else :
+ $type = 'pmd/Field_small';
+ if (strstr($tab_column[$t_n]["TYPE"][$j], 'char')
+ || strstr($tab_column[$t_n]["TYPE"][$j], 'text')
+ ) {
+ $type .= '_char';
+ } elseif (strstr($tab_column[$t_n]["TYPE"][$j], 'int')
+ || strstr($tab_column[$t_n]["TYPE"][$j], 'float')
+ || strstr($tab_column[$t_n]["TYPE"][$j], 'double')
+ || strstr($tab_column[$t_n]["TYPE"][$j], 'decimal')
+ ) {
+ $type .= '_int';
+ } elseif (strstr($tab_column[$t_n]["TYPE"][$j], 'date')
+ || strstr($tab_column[$t_n]["TYPE"][$j], 'time')
+ || strstr($tab_column[$t_n]["TYPE"][$j], 'year')
+ ) {
+ $type .= '_date';
+ }
+ ?>
+ <img src="<?php echo $_SESSION['PMA_Theme']->getImgPath($type); ?>.png" alt="*" />
+ <?php endif; ?>
+ <?php echo htmlspecialchars(
+ $tab_column[$t_n]["COLUMN_NAME"][$j] . " : "
+ . $tab_column[$t_n]["TYPE"][$j],
+ ENT_QUOTES
+ ); ?>
+ </div>
+ </td>
+ <?php if (isset($_REQUEST['query'])) : ?>
+ <td class="small_tab_pref small_tab_pref_click_opt"
+ onmouseover="this.className='small_tab_pref2 small_tab_pref_click_opt'"
+ onmouseout="this.className='small_tab_pref small_tab_pref_click_opt'"
+ Click_option_param="pmd_optionse,<?php echo urlencode($tab_column[$t_n]['COLUMN_NAME'][$j]); ?>,<?php echo $GLOBALS['PMD_OUT']['TABLE_NAME_SMALL'][$i]; ?>" >
+ <img src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/exec_small.png'); ?>" title="options" />
+ </td>
+ <?php endif; ?>
+ </tr>
+ <?php endfor; ?>
+ </tbody>
+ </table>
+<?php endfor; ?>
diff --git a/templates/database/designer/delete_relation_panel.phtml b/templates/database/designer/delete_relation_panel.phtml
new file mode 100644
index 0000000000..6394251c0b
--- /dev/null
+++ b/templates/database/designer/delete_relation_panel.phtml
@@ -0,0 +1,47 @@
+<table id="layer_upd_relation" style="display:none;" width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%">
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="100%" class="center" cellpadding="2" cellspacing="0">
+ <tr>
+ <td colspan="3" class="center nowrap">
+ <strong>
+ <?php echo __('Delete relation'); ?>
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" class="center nowrap">
+ <input id="del_button" name="Button" type="button" class="butt" value="<?php echo __('Delete'); ?>" />
+ <input id="cancel_button" type="button" class="butt" name="Button" value="<?php echo __('Cancel'); ?>" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/designer/edit_delete_pages.phtml b/templates/database/designer/edit_delete_pages.phtml
new file mode 100644
index 0000000000..7560b15abd
--- /dev/null
+++ b/templates/database/designer/edit_delete_pages.phtml
@@ -0,0 +1,11 @@
+<?php $cfgRelation = PMA_getRelationsParam(); ?>
+<form action="db_designer.php" method="post" name="edit_delete_pages" id="edit_delete_pages" class="ajax">
+ <?php echo PMA_URL_getHiddenInputs($db); ?>
+ <fieldset id="page_edit_delete_options">
+ <input type="hidden" name="operation" value="<?php echo $operation; ?>" />
+ <label for="selected_page">
+ <?php echo $operation == 'editPage' ? __("Page to open") : __("Page to delete"); ?>:
+ </label>
+ <?php echo PMA_getHtmlForPageSelector($cfgRelation, $db); ?>
+ </fieldset>
+</form> \ No newline at end of file
diff --git a/templates/database/designer/having_query_panel.phtml b/templates/database/designer/having_query_panel.phtml
new file mode 100644
index 0000000000..a478680f7c
--- /dev/null
+++ b/templates/database/designer/having_query_panel.phtml
@@ -0,0 +1,138 @@
+<table id="query_having" style="display:none;" width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%" >
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="168" class="center" cellpadding="2" cellspacing="0">
+ <thead>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <strong>
+ HAVING
+ </strong>
+ </td>
+ </tr>
+ </thead>
+ <tbody id="rename_to">
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Operator'); ?>
+ </td>
+ <td width="102">
+ <select name="hoperator" id="hoperator">
+ <option value="---" selected="selected">
+ ---
+ </option>
+ <option value="None" >
+ None
+ </option>
+ <option value="sum" >
+ SUM
+ </option>
+ <option value="min">
+ MIN
+ </option>
+ <option value="max">
+ MAX
+ </option>
+ <option value="avg">
+ AVG
+ </option>
+ <option value="count">
+ COUNT
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Operator'); ?>
+ </td>
+ <td width="102">
+ <select name="hrel_opt" id="hrel_opt">
+ <option value="--" selected="selected">
+ --
+ </option>
+ <option value="=">
+ =
+ </option>
+ <option value="&gt;">
+ &gt;
+ </option>
+ <option value="&lt;">
+ &lt;
+ </option>
+ <option value="&gt;=">
+ &gt;=
+ </option>
+ <option value="&lt;=">
+ &lt;=
+ </option>
+ <option value="NOT">
+ NOT
+ </option>
+ <option value="IN">
+ IN
+ </option>
+ <option value="EXCEPT">
+ <?php echo __('Except'); ?>
+ </option>
+ <option value="NOT IN">
+ NOT IN
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="nowrap">
+ <?php echo __('Value'); ?>
+ <br />
+ <?php echo __('subquery'); ?>
+ </td>
+ <td>
+ <textarea id="hQuery" value="" cols="18">
+ </textarea>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <input type="button" id="ok_edit_having" class="butt" name="Button" value="<?php echo __('OK'); ?>" />
+ <input type="button"
+ class="butt"
+ name="Button"
+ value="<?php echo __('Cancel'); ?>"
+ onclick="document.getElementById('query_having').style.display = 'none';" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/designer/js_fields.phtml b/templates/database/designer/js_fields.phtml
new file mode 100644
index 0000000000..7187ff8187
--- /dev/null
+++ b/templates/database/designer/js_fields.phtml
@@ -0,0 +1,10 @@
+<?php $cfgRelation = PMA_getRelationsParam(); ?>
+<!-- Do not expand HTML here, invisible characters will make javascript crash -->
+<div id="script_server" class="hide"><?php echo htmlspecialchars($GLOBALS['server']); ?></div>
+<div id="script_db" class="hide"><?php echo htmlspecialchars($_GET['db']); ?></div>
+<div id="script_token" class="hide"><?php echo htmlspecialchars($_GET['token']); ?></div>
+<div id="script_tables" class="hide"><?php echo htmlspecialchars(json_encode($script_tables)); ?></div>
+<div id="script_contr" class="hide"><?php echo htmlspecialchars(json_encode($script_contr)); ?></div>
+<div id="script_display_field" class="hide"><?php echo htmlspecialchars(json_encode($script_display_field)); ?></div>
+<div id="script_display_page" class="hide"><?php echo htmlspecialchars($display_page); ?></div>
+<div id="pmd_tables_enabled" class="hide"><?php echo htmlspecialchars($cfgRelation['pdfwork']); ?></div> \ No newline at end of file
diff --git a/templates/database/designer/new_relation_panel.phtml b/templates/database/designer/new_relation_panel.phtml
new file mode 100644
index 0000000000..59672f74c2
--- /dev/null
+++ b/templates/database/designer/new_relation_panel.phtml
@@ -0,0 +1,108 @@
+<table id="layer_new_relation" style="display:none;" width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%" >
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="168" class="center" cellpadding="2" cellspacing="0">
+ <thead>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <strong>
+ <?php echo __('Create relation'); ?>
+ </strong>
+ </td>
+ </tr>
+ </thead>
+ <tbody id="foreign_relation">
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <strong>
+ FOREIGN KEY
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ on delete
+ </td>
+ <td width="102">
+ <select name="on_delete" id="on_delete">
+ <option value="nix" selected="selected">
+ --
+ </option>
+ <option value="CASCADE">
+ CASCADE
+ </option>
+ <option value="SET NULL">
+ SET NULL
+ </option>
+ <option value="NO ACTION">
+ NO ACTION
+ </option>
+ <option value="RESTRICT">
+ RESTRICT
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="nowrap">
+ on update
+ </td>
+ <td>
+ <select name="on_update" id="on_update">
+ <option value="nix" selected="selected">
+ --
+ </option>
+ <option value="CASCADE">
+ CASCADE
+ </option>
+ <option value="SET NULL">
+ SET NULL
+ </option>
+ <option value="NO ACTION">
+ NO ACTION
+ </option>
+ <option value="RESTRICT">
+ RESTRICT
+ </option>
+ </select>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <input type="button" id="ok_new_rel_panel" class="butt" name="Button" value="<?php echo __('OK'); ?>" />
+ <input type="button" id="cancel_new_rel_panel" class="butt" name="Button" value="<?php echo __('Cancel'); ?>" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/designer/options_panel.phtml b/templates/database/designer/options_panel.phtml
new file mode 100644
index 0000000000..c4937329d4
--- /dev/null
+++ b/templates/database/designer/options_panel.phtml
@@ -0,0 +1,273 @@
+<table id="pmd_optionse" style="display:none;" width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%" >
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="168" class="center" cellpadding="2" cellspacing="0">
+ <thead>
+ <tr>
+ <td colspan="2" rowspan="2" id="option_col_name" class="center nowrap">
+ </td>
+ </tr>
+ </thead>
+ <tbody id="where">
+ <tr>
+ <td class="center nowrap">
+ <b>
+ WHERE
+ </b>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Relation operator'); ?>
+ </td>
+ <td width="102">
+ <select name="rel_opt" id="rel_opt">
+ <option value="--" selected="selected">
+ --
+ </option>
+ <option value="=">
+ =
+ </option>
+ <option value="&gt;">
+ &gt;
+ </option>
+ <option value="&lt;">
+ &lt;
+ </option>
+ <option value="&gt;=">
+ &gt;=
+ </option>
+ <option value="&lt;=">
+ &lt;=
+ </option>
+ <option value="NOT">
+ NOT
+ </option>
+ <option value="IN">
+ IN
+ </option>
+ <option value="EXCEPT">
+ <?php echo __('Except'); ?>
+ </option>
+ <option value="NOT IN">
+ NOT IN
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="nowrap">
+ <?php echo __('Value'); ?>
+ <br />
+ <?php echo __('subquery'); ?>
+ </td>
+ <td>
+ <textarea id="Query" value="" cols="18">
+ </textarea>
+ </td>
+ </tr>
+ <tr>
+ <td class="center nowrap">
+ <b>
+ <?php echo __('Rename to'); ?>
+ </b>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('New name'); ?>
+ </td>
+ <td width="102">
+ <input type="text" value="" id="new_name"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="center nowrap">
+ <b>
+ <?php echo __('Aggregate'); ?>
+ </b>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Operator'); ?>
+ </td>
+ <td width="102">
+ <select name="operator" id="operator">
+ <option value="---" selected="selected">
+ ---
+ </option>
+ <option value="sum" >
+ SUM
+ </option>
+ <option value="min">
+ MIN
+ </option>
+ <option value="max">
+ MAX
+ </option>
+ <option value="avg">
+ AVG
+ </option>
+ <option value="count">
+ COUNT
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="center nowrap">
+ <b>
+ GROUP BY
+ </b>
+ </td>
+ <td>
+ <input type="checkbox" value="groupby" id="groupby"/>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="center nowrap">
+ <b>
+ ORDER BY
+ </b>
+ </td>
+ <td>
+ <select name="orderby" id="orderby">
+ <option value="---" selected="selected">
+ ---
+ </option>
+ <option value="ASC" >
+ ASC
+ </option>
+ <option value="DESC">
+ DESC
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="center nowrap">
+ <b>
+ HAVING
+ </b>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Operator'); ?>
+ </td>
+ <td width="102">
+ <select name="h_operator" id="h_operator">
+ <option value="---" selected="selected">
+ ---
+ </option>
+ <option value="None" >
+ <?php echo __('None'); ?>
+ </option>
+ <option value="sum" >
+ SUM
+ </option>
+ <option value="min">
+ MIN
+ </option>
+ <option value="max">
+ MAX
+ </option>
+ <option value="avg">
+ AVG
+ </option>
+ <option value="count">
+ COUNT
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Relation operator'); ?>
+ </td>
+ <td width="102">
+ <select name="h_rel_opt" id="h_rel_opt">
+ <option value="--" selected="selected">
+ --
+ </option>
+ <option value="=">
+ =
+ </option>
+ <option value="&gt;">
+ &gt;
+ </option>
+ <option value="&lt;">
+ &lt;
+ </option>
+ <option value="&gt;=">
+ &gt;=
+ </option>
+ <option value="&lt;=">
+ &lt;=
+ </option>
+ <option value="NOT">
+ NOT
+ </option>
+ <option value="IN">
+ IN
+ </option>
+ <option value="EXCEPT">
+ <?php echo __('Except'); ?>
+ </option>
+ <option value="NOT IN">
+ NOT IN
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Value'); ?>
+ <br/>
+ <?php echo __('subquery'); ?>
+ </td>
+ <td width="102">
+ <textarea id="having" value="" cols="18">
+ </textarea>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <input type="button" id="ok_add_object" class="butt" name="Button" value="<?php echo __('OK'); ?>" />
+ <input type="button" id="cancel_close_option" class="butt" name="Button" value="<?php echo __('Cancel'); ?>" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/designer/page_save_as.phtml b/templates/database/designer/page_save_as.phtml
new file mode 100644
index 0000000000..8394915d24
--- /dev/null
+++ b/templates/database/designer/page_save_as.phtml
@@ -0,0 +1,33 @@
+<?php
+$cfgRelation = PMA_getRelationsParam();
+$choices = array(
+ 'same' => __('Save to selected page'),
+ 'new' => __('Create a page and save to it')
+);
+?>
+<form action="db_designer.php" method="post" name="save_as_pages" id="save_as_pages" class="ajax">
+ <?php echo PMA_URL_getHiddenInputs($db); ?>
+ <fieldset id="page_save_as_options">
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <input type="hidden" name="operation" value="savePage" />
+ <?php echo PMA_getHtmlForPageSelector($cfgRelation, $db); ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <?php echo PMA_Util::getRadioFields('save_page', $choices, 'same', true); ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label for="selected_value"><?php echo __('New page name'); ?></label>
+ <input type="text" name="selected_value" id="selected_value" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+</form> \ No newline at end of file
diff --git a/templates/database/designer/page_selector.phtml b/templates/database/designer/page_selector.phtml
new file mode 100644
index 0000000000..6195f87941
--- /dev/null
+++ b/templates/database/designer/page_selector.phtml
@@ -0,0 +1,10 @@
+<select name="selected_page" id="selected_page">
+ <option value="0">-- <?php echo __('Select page'); ?> --</option>
+ <?php if ($cfgRelation['pdfwork']) : $pages = PMA_getPageIdsAndNames($db); ?>
+ <?php foreach ($pages as $nr => $desc) : ?>
+ <option value="<?php echo $nr; ?>">
+ <?php echo htmlspecialchars($desc); ?>
+ </option>
+ <?php endforeach; ?>
+ <?php endif; ?>
+</select> \ No newline at end of file
diff --git a/templates/database/designer/query_details.phtml b/templates/database/designer/query_details.phtml
new file mode 100644
index 0000000000..ffae53a2b4
--- /dev/null
+++ b/templates/database/designer/query_details.phtml
@@ -0,0 +1,19 @@
+<div class="panel">
+ <div style="clear:both;">
+ </div>
+ <div id="ab">
+ </div>
+ <div style="clear:both;">
+ </div>
+</div>
+<a class="trigger" href="#">
+ <?php echo __('Active options'); ?>
+</a>
+<div id="box">
+ <form method="post" action="db_qbe.php" id="vqb_form">
+ <textarea cols="80" name="sql_query" id="textSqlquery" rows="15">
+ </textarea>
+ <input type="hidden" name="submit_sql" value="true">
+ <?php echo PMA_URL_getHiddenInputs($_GET['db']); ?>
+ </form>
+</div> \ No newline at end of file
diff --git a/templates/database/designer/rename_to_panel.phtml b/templates/database/designer/rename_to_panel.phtml
new file mode 100644
index 0000000000..41d7c059f7
--- /dev/null
+++ b/templates/database/designer/rename_to_panel.phtml
@@ -0,0 +1,66 @@
+
+<table id="query_rename_to" style="display:none;" width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%" >
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="168" class="center" cellpadding="2" cellspacing="0">
+ <thead>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <strong>
+ <?php echo __('Rename to'); ?>
+ </strong>
+ </td>
+ </tr>
+ </thead>
+ <tbody id="rename_to">
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('New name'); ?>
+ </td>
+ <td width="102">
+ <input type="text" value="" id="e_rename"/>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <input type="button" id="ok_edit_rename" class="butt" name="Button" value="<?php echo __('OK'); ?>" />
+ <input type="button"
+ class="butt"
+ name="Button"
+ value="<?php echo __('Cancel'); ?>"
+ onclick="document.getElementById('query_rename_to').style.display = 'none';" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/designer/schema_export.phtml b/templates/database/designer/schema_export.phtml
new file mode 100644
index 0000000000..59240ab482
--- /dev/null
+++ b/templates/database/designer/schema_export.phtml
@@ -0,0 +1,11 @@
+<form method="post" action="schema_export.php" class="disableAjax" id="id_export_pages">
+ <fieldset>
+ <?php echo PMA_URL_getHiddenInputs($db); ?>
+ <label><?php echo __('Select Export Relational Type'); ?></label><br/>
+ <?php echo PMA_pluginGetChoice(
+ 'Schema', 'export_type', $export_list, 'format'
+ ); ?>
+ <input type="hidden" name="page_number" value="<?php echo htmlspecialchars($page); ?>" />
+ <?php echo PMA_pluginGetOptions('Schema', $export_list); ?>
+ </fieldset>
+</form> \ No newline at end of file
diff --git a/templates/database/designer/side_menu.phtml b/templates/database/designer/side_menu.phtml
new file mode 100644
index 0000000000..7abc394f56
--- /dev/null
+++ b/templates/database/designer/side_menu.phtml
@@ -0,0 +1,189 @@
+<?php
+function getImg($path)
+{
+ return $_SESSION['PMA_Theme']->getImgPath($path);
+}
+?>
+<?php if (!$visualBuilder) : ?>
+ <div id="name-panel" style="overflow:hidden">
+ <span id="page_name" style="border:none">
+ <?php echo $selected_page == null ? __("Untitled") : htmlspecialchars($selected_page); ?>
+ </span>
+ <span id="saved_state" style="border:none">
+ <?php echo $selected_page == null ? '*' : ''; ?>
+ </span>
+ </div>
+<?php endif; ?>
+<div class="pmd_header side-menu" id="side_menu">
+ <a class="M_butt" id="key_Show_left_menu" href="#">
+ <img title="<?php echo __('Show/Hide tables list'); ?>"
+ alt="v"
+ src="<?php echo getImg('pmd/downarrow2_m.png'); ?>"
+ data-down="<?php echo getImg('pmd/downarrow2_m.png'); ?>"
+ data-up="<?php echo getImg('pmd/uparrow2_m.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Show/Hide tables list'); ?>
+ </span>
+ </a>
+ <a href="#" id="toggleFullscreen" class="M_butt">
+ <img title="<?php echo __('View in fullscreen'); ?>"
+ src="<?php echo getImg('pmd/viewInFullscreen.png'); ?>"
+ data-enter="<?php echo getImg('pmd/viewInFullscreen.png'); ?>"
+ data-exit="<?php echo getImg('pmd/exitFullscreen.png'); ?>" />
+ <span class="hide hidable"
+ data-exit="<?php echo __('Exit fullscreen'); ?>"
+ data-enter="<?php echo __('View in fullscreen'); ?>">
+ <?php echo __('View in fullscreen'); ?>
+ </span>
+ </a>
+ <?php if (! $visualBuilder) : ?>
+ <a id="newPage" href="#" class="M_butt">
+ <img title="<?php echo __('New page'); ?>"
+ alt=""
+ src="<?php echo getImg('pmd/page_add.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('New page'); ?>
+ </span>
+ </a>
+ <a href="#" id="editPage" class="M_butt ajax">
+ <img title="<?php echo __('Open page'); ?>"
+ src="<?php echo getImg('pmd/page_edit.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Open page'); ?>
+ </span>
+ </a>
+ <a href="#" id="savePos" class="M_butt">
+ <img title="<?php echo __('Save page'); ?>"
+ src="<?php echo getImg('pmd/save.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Save page'); ?>
+ </span>
+ </a>
+ <a href="#" id="SaveAs" class="M_butt ajax">
+ <img title="<?php echo __('Save page as'); ?>"
+ src="<?php echo getImg('pmd/save_as.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Save page as'); ?>
+ </span>
+ </a>
+ <a href="#" id="delPages" class="M_butt ajax">
+ <img title="<?php echo __('Delete pages'); ?>"
+ src="<?php echo getImg('pmd/page_delete.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Delete pages'); ?>
+ </span>
+ </a>
+ <a href="#" id="StartTableNew" class="M_butt">
+ <img title="<?php echo __('Create table'); ?>"
+ src="<?php echo getImg('pmd/table.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Create table'); ?>
+ </span>
+ </a>
+ <a href="#" class="M_butt" id="rel_button">
+ <img title="<?php echo __('Create relation'); ?>"
+ src="<?php echo getImg('pmd/relation.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Create relation'); ?>
+ </span>
+ </a>
+ <a href="#" class="M_butt" id="display_field_button">
+ <img title="<?php echo __('Choose column to display'); ?>"
+ src="<?php echo getImg('pmd/display_field.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Choose column to display'); ?>
+ </span>
+ </a>
+ <a href="#" id="reloadPage" class="M_butt">
+ <img title="<?php echo __('Reload'); ?>"
+ src="<?php echo getImg('pmd/reload.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Reload'); ?>
+ </span>
+ </a>
+ <a href="<?php echo PMA_Util::getDocuLink('faq', 'faq6-31'); ?>"
+ target="documentation"
+ class="M_butt">
+ <img title="<?php echo __('Help'); ?>"
+ src="<?php echo getImg('pmd/help.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Help'); ?>
+ </span>
+ </a>
+ <?php endif; ?>
+ <a href="#" class="<?php echo $params_array['angular_direct']; ?>" id="angular_direct_button">
+ <img title="<?php echo __('Angular links'); ?> / <?php echo __('Direct links'); ?>"
+ src="<?php echo getImg('pmd/ang_direct.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Angular links'); ?> / <?php echo __('Direct links'); ?>
+ </span>
+ </a>
+ <a href="#" class="<?php echo $params_array['snap_to_grid']; ?>" id="grid_button">
+ <img title="<?php echo __('Snap to grid'); ?>" src="<?php echo getImg('pmd/grid.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Snap to grid'); ?>
+ </span>
+ </a>
+ <a href="#" class="<?php echo $params_array['small_big_all']; ?>" id="key_SB_all">
+ <img title="<?php echo __('Small/Big All'); ?>"
+ alt="v"
+ src="<?php echo getImg('pmd/downarrow1.png'); ?>"
+ data-down="<?php echo getImg('pmd/downarrow1.png'); ?>"
+ data-right="<?php echo getImg('pmd/rightarrow1.png') ?>" />
+ <span class="hide hidable">
+ <?php echo __('Small/Big All'); ?>
+ </span>
+ </a>
+ <a href="#" id="SmallTabInvert" class="M_butt" >
+ <img title="<?php echo __('Toggle small/big'); ?>"
+ src="<?php echo getImg('pmd/bottom.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Toggle small/big'); ?>
+ </span>
+ </a>
+ <a href="#" id="relLineInvert" class="<?php echo $params_array['relation_lines']; ?>" >
+ <img title="<?php echo __('Toggle relation lines'); ?>"
+ src="<?php echo getImg('pmd/toggle_lines.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Toggle relation lines'); ?>
+ </span>
+ </a>
+ <?php if (! $visualBuilder) : ?>
+ <a href="#" id="exportPages" class="M_butt" >
+ <img title="<?php echo __('Export schema'); ?>"
+ src="<?php echo getImg('pmd/export.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Export schema'); ?>
+ </span>
+ </a>
+ <?php else: ?>
+ <a class="M_butt"
+ href="#"
+ onclick="build_query('SQL Query on Database', 0)"
+ onmousedown="return false;"
+ class="M_butt">
+ <img title="<?php echo __('Build Query'); ?>"
+ src="<?php echo getImg('pmd/query_builder.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Build Query'); ?>
+ </span>
+ </a>
+ <?php endif; ?>
+ <a href="#" class="<?php echo $params_array['side_menu']; ?>" id="key_Left_Right">
+ <img title="<?php echo __('Move Menu'); ?>" alt=">"
+ data-right="<?php echo getImg('pmd/2leftarrow_m.png'); ?>"
+ src="<?php echo getImg('pmd/2rightarrow_m.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Move Menu'); ?>
+ </span>
+ </a>
+ <a href="#" class="<?php echo $params_array['pin_text']; ?>" id="pin_Text">
+ <img title="<?php echo __('Pin text'); ?>"
+ alt=">"
+ data-right="<?php echo getImg('pmd/anchor.png'); ?>"
+ src="<?php echo getImg('pmd/anchor.png'); ?>" />
+ <span class="hide hidable">
+ <?php echo __('Pin text'); ?>
+ </span>
+ </a>
+</div> \ No newline at end of file
diff --git a/templates/database/designer/table_list.phtml b/templates/database/designer/table_list.phtml
new file mode 100644
index 0000000000..ca8511e386
--- /dev/null
+++ b/templates/database/designer/table_list.phtml
@@ -0,0 +1,69 @@
+<div id="layer_menu" style="display:none;">
+ <div class="center">
+ <a href="#" class="M_butt" target="_self" >
+ <img title="<?php echo __('Hide/Show all'); ?>"
+ alt="v"
+ id="key_HS_all"
+ src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow1.png'); ?>"
+ data-down="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow1.png'); ?>"
+ data-right="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow1.png'); ?>" />
+ </a>
+ <a href="#" class="M_butt" target="_self" >
+ <img alt="v"
+ id="key_HS"
+ title="<?php echo __('Hide/Show Tables with no relation'); ?>"
+ src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow2.png'); ?>"
+ data-down="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/downarrow2.png'); ?>"
+ data-right="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/rightarrow2.png'); ?>" />
+ </a>
+ </div>
+ <div id="id_scroll_tab" class="scroll_tab">
+ <table width="100%" style="padding-left: 3px;">
+ <?php $name_cnt = count($GLOBALS['PMD']['TABLE_NAME']);
+ for ($i = 0; $i < $name_cnt; $i++) :
+ $checked = (isset($tab_pos[$GLOBALS['PMD']["TABLE_NAME"][$i]])
+ && $tab_pos[$GLOBALS['PMD']["TABLE_NAME"][$i]]["H"])
+ || $display_page == -1; ?>
+ <tr>
+ <td title="<?php echo __('Structure'); ?>"
+ width="1px"
+ onmouseover="this.className='L_butt2_2'"
+ onmouseout="this.className='L_butt2_1'"
+ class="L_butt2_1">
+ <img alt=""
+ table_name="<?php echo $GLOBALS['PMD_URL']['TABLE_NAME_SMALL'][$i]; ?>"
+ class="scroll_tab_struct"
+ src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/exec.png'); ?>"/>
+ </td>
+ <td width="1px">
+ <input class="scroll_tab_checkbox"
+ title="<?php echo __('Hide'); ?>"
+ id="check_vis_<?php echo $GLOBALS['PMD_URL']["TABLE_NAME"][$i]; ?>"
+ style="margin:0;"
+ type="checkbox"
+ value="<?php echo $GLOBALS['PMD_URL']["TABLE_NAME"][$i]; ?>"
+ <?php if ($checked) : ?>checked="checked"<?php endif; ?> />
+ </td>
+ <td class="pmd_Tabs"
+ onmouseover="this.className='pmd_Tabs2'"
+ onmouseout="this.className='pmd_Tabs'"
+ pmd_url_table_name="<?php echo $GLOBALS['PMD_URL']['TABLE_NAME'][$i]; ?>">
+ <?php echo $GLOBALS['PMD_OUT']["TABLE_NAME"][$i]; ?>
+ </td>
+ </tr>
+ <?php endfor; ?>
+ </table>
+ </div>
+ <!-- end id_scroll_tab -->
+ <div class="center">
+ <?php echo __('Number of tables:'); ?> <?php echo $name_cnt; ?>
+ </div>
+ <div id="layer_menu_sizer" onmousedown="layer_menu_cur_click=1">
+ <div class="floatleft">
+ <img class="icon"
+ data-right="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/resizeright.png'); ?>"
+ src="<?php echo $_SESSION['PMA_Theme']->getImgPath('pmd/resize.png'); ?>"/>
+ </div>
+ </div>
+</div>
+<!-- end layer_menu --> \ No newline at end of file
diff --git a/templates/database/designer/where_query_panel.phtml b/templates/database/designer/where_query_panel.phtml
new file mode 100644
index 0000000000..5e28885ab0
--- /dev/null
+++ b/templates/database/designer/where_query_panel.phtml
@@ -0,0 +1,103 @@
+<table id="query_where" style="display:none;"width="5%" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="frams1" width="10px">
+ </td>
+ <td class="frams5" width="99%" >
+ </td>
+ <td class="frams2" width="10px">
+ <div class="bor">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td class="frams8">
+ </td>
+ <td class="input_tab">
+ <table width="168" class="center" cellpadding="2" cellspacing="0">
+ <thead>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <strong>
+ WHERE
+ </strong>
+ </td>
+ </tr>
+ </thead>
+ <tbody id="rename_to">
+ <tr>
+ <td width="58" class="nowrap">
+ <?php echo __('Operator'); ?>
+ </td>
+ <td width="102">
+ <select name="erel_opt" id="erel_opt">
+ <option value="--" selected="selected">
+ --
+ </option>
+ <option value="=" >
+ =
+ </option>
+ <option value="&gt;">
+ &gt;
+ </option>
+ <option value="&lt;">
+ &lt;
+ </option>
+ <option value="&gt;=">
+ &gt;=
+ </option>
+ <option value="&lt;=">
+ &lt;=
+ </option>
+ <option value="NOT">
+ NOT
+ </option>
+ <option value="IN">
+ IN
+ </option>
+ <option value="EXCEPT">
+ <?php echo __('Except'); ?>
+ </option>
+ <option value="NOT IN">
+ NOT IN
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="nowrap">
+ <?php echo __('Value'); ?>
+ <br />
+ <?php echo __('subquery'); ?>
+ </td>
+ <td>
+ <textarea id="eQuery" value="" cols="18">
+ </textarea>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td colspan="2" class="center nowrap">
+ <input type="button" id="ok_edit_where" class="butt" name="Button" value="<?php echo __('OK'); ?>" />
+ <input type="button" class="butt" name="Button" value="<?php echo __('Cancel'); ?>" onclick="document.getElementById('query_where').style.display = 'none'" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td class="frams6">
+ </td>
+ </tr>
+ <tr>
+ <td class="frams4">
+ <div class="bor">
+ </div>
+ </td>
+ <td class="frams7">
+ </td>
+ <td class="frams3">
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/templates/database/structure/body_for_table_summary.phtml b/templates/database/structure/body_for_table_summary.phtml
new file mode 100644
index 0000000000..8ece47c2da
--- /dev/null
+++ b/templates/database/structure/body_for_table_summary.phtml
@@ -0,0 +1,93 @@
+<tbody id="tbl_summary_row">
+<tr>
+<th class="print_ignore"></th>
+<th class="tbl_num nowrap">
+ <?php
+ printf(_ngettext('%s table', '%s tables', $num_tables),
+ PMA_Util::formatNumber($num_tables, 0)); ?>
+</th>
+<?php if ($server_slave_status): ?>
+ <th> <?php echo __('Replication'); ?> </th>
+<?php endif; ?>
+<?php
+$sum_colspan = ($db_is_system_schema ? 4 : 7);
+if ($GLOBALS['cfg']['NumFavoriteTables'] == 0) {
+ $sum_colspan--;
+} ?>
+<th colspan="<?php echo $sum_colspan; ?>" class="print_ignore" ><?php echo __('Sum'); ?></th>
+<?php
+$row_count_sum = PMA_Util::formatNumber($sum_entries, 0);
+// If a table shows approximate rows count, display update-all-real-count anchor.
+$row_sum_url = array();
+if (isset($approx_rows)) {
+ $row_sum_url = array(
+ 'ajax_request' => true,
+ 'db' => $GLOBALS['db'],
+ 'real_row_count' => 'true',
+ 'real_row_count_all' => 'true'
+ );
+}
+$cell_text = ($approx_rows)
+ ? '<a href="db_structure.php' . PMA_URL_getCommon($row_sum_url)
+ . '" class="ajax row_count_sum">' . '~' . $row_count_sum . '</a>'
+ : $row_count_sum;
+?>
+<th class="value tbl_rows"><?php echo $cell_text; ?></th>
+<?php if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)): ?>
+ <?php
+ // MySQL <= 5.5.2
+ $default_engine = $GLOBALS['dbi']->fetchValue(
+ "SELECT @@storage_engine;"
+ );
+ if (empty($default_engine)) {
+ // MySQL >= 5.5.3
+ $default_engine = $GLOBALS['dbi']->fetchValue(
+ "SELECT @@default_storage_engine;"
+ );
+ }
+ ?>
+ <th class="center">
+ <dfn title="<?php printf(__('%s is the default storage engine on this MySQL server.'),
+ $default_engine); ?>"><?php echo $default_engine; ?></dfn>
+ </th>
+ <th>
+ <?php if (! empty($db_collation)): ?>
+ <dfn title="<?php echo PMA_getCollationDescr($db_collation) . ' (' . __('Default'). ')'; ?>">
+ <?php echo $db_collation; ?>
+ </dfn>
+ <?php endif; ?>
+ </th>
+<?php endif; ?>
+<?php if ($is_show_stats): ?>
+ <?php
+ list($sum_formatted, $unit) = PMA_Util::formatByteDown(
+ $sum_size, 3, 1
+ );
+ list($overhead_formatted, $overhead_unit)
+ = PMA_Util::formatByteDown($overhead_size, 3, 1);
+ ?>
+ <th class="value tbl_size"><?php echo $sum_formatted . ' ' . $unit; ?></th>
+ <th class="value tbl_overhead"><?php echo $overhead_formatted . ' ' . $overhead_unit; ?></th>
+<?php endif; ?>
+<?php if ($GLOBALS['cfg']['ShowDbStructureComment']): ?>
+ <th></th>
+<?php endif; ?>
+<?php if ($GLOBALS['cfg']['ShowDbStructureCreation']): ?>
+ <th class="value tbl_creation">
+ <?php echo ($create_time_all
+ ? PMA_Util::localisedDate(strtotime($create_time_all))
+ : '-'); ?>
+ </th>
+<?php endif; ?>
+<?php if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']): ?>
+ <th class="value tbl_last_update"><?php echo ($update_time_all
+ ? PMA_Util::localisedDate(strtotime($update_time_all))
+ : '-'); ?></th>
+<?php endif; ?>
+<?php if ($GLOBALS['cfg']['ShowDbStructureLastCheck']): ?>
+ <th class="value tbl_last_check"><?php echo ($check_time_all
+ ? PMA_Util::localisedDate(strtotime($check_time_all))
+ : '-');?></th>
+<?php endif; ?>
+</tr>
+</tbody> \ No newline at end of file
diff --git a/templates/database/structure/browse_table.phtml b/templates/database/structure/browse_table.phtml
new file mode 100644
index 0000000000..87068febc9
--- /dev/null
+++ b/templates/database/structure/browse_table.phtml
@@ -0,0 +1,3 @@
+<a href="sql.php<?php echo $tbl_url_query; ?>&amp;pos=0">
+ <?php echo $title; ?>
+</a>
diff --git a/templates/database/structure/browse_table_label.phtml b/templates/database/structure/browse_table_label.phtml
new file mode 100644
index 0000000000..0bde3f928a
--- /dev/null
+++ b/templates/database/structure/browse_table_label.phtml
@@ -0,0 +1,3 @@
+<a href="sql.php<?php echo $tbl_url_query; ?>&amp;pos=0" title="<?php echo $title; ?>">
+ <?php echo $truename; ?>
+</a>
diff --git a/templates/database/structure/check_all_tables.phtml b/templates/database/structure/check_all_tables.phtml
new file mode 100644
index 0000000000..a6866118a0
--- /dev/null
+++ b/templates/database/structure/check_all_tables.phtml
@@ -0,0 +1,43 @@
+<div class="clearfloat print_ignore">
+ <img class="selectallarrow" src="<?php echo $pmaThemeImage . 'arrow_' . $text_dir . '.png'; ?>" width="38" height="22" alt="<?php __('With selected:'); ?>" />
+ <input type="checkbox" id="tablesForm_checkall" class="checkall_box" title="<?php echo __('Check all'); ?>" />
+ <label for="tablesForm_checkall"><?php echo __('Check all'); ?></label>
+ <?php if ($overhead_check != ''): ?>
+ / <a href="#" onclick="unMarkAllRows('tablesForm'); <?php echo $overhead_check; ?> return false;"><?php echo __('Check tables having overhead'); ?></a>
+ <?php endif; ?>
+ <select name="submit_mult" class="autosubmit" style="margin: 0 3em 0 3em;">
+ <option value="<?php echo __('With selected:'); ?>" selected="selected"><?php echo __('With selected:'); ?></option>
+ <option value="show_create" ><?php echo __('Show create'); ?></option>
+ <option value="export" ><?php echo __('Export'); ?></option>
+ <?php if (!$db_is_system_schema
+ && !$GLOBALS['cfg']['DisableMultiTableMaintenance']): ?>
+ <optgroup label="<?php echo __('Delete data or table'); ?>">
+ <option value="empty_tbl" ><?php echo __('Empty'); ?></option>
+ <option value="drop_tbl" ><?php echo __('Drop'); ?></option>
+ </optgroup>
+ <optgroup label="<?php echo __('Table maintenance'); ?>">
+ <option value="analyze_tbl" ><?php echo __('Analyze table'); ?></option>
+ <option value="check_tbl" ><?php echo __('Check table'); ?></option>
+ <?php if (!PMA_DRIZZLE): ?>
+ <option value="checksum_tbl" ><?php echo __('Checksum table'); ?></option>
+ <option value="optimize_tbl" ><?php echo __('Optimize table'); ?></option>
+ <option value="repair_tbl" ><?php echo __('Repair table'); ?></option>
+ <?php endif; ?>
+ </optgroup>
+ <optgroup label="<?php echo __('Prefix'); ?>">
+ <option value="add_prefix_tbl" ><?php echo __('Add prefix to table'); ?></option>
+ <option value="replace_prefix_tbl" ><?php echo __('Replace table prefix'); ?></option>
+ <option value="copy_tbl_change_prefix" ><?php echo __('Copy table with prefix'); ?></option>
+ </optgroup>
+ <?php endif; ?>
+ <?php if (isset($GLOBALS['cfgRelation']['centralcolumnswork'])
+ && $GLOBALS['cfgRelation']['centralcolumnswork']): ?>
+ <optgroup label="<?php echo __('Central columns'); ?>">
+ <option value="sync_unique_columns_central_list" ><?php echo __('Add columns to central list'); ?></option>
+ <option value="delete_unique_columns_central_list" ><?php echo __('Remove columns from central list'); ?></option>
+ <option value="make_consistent_with_central_list" ><?php echo __('Make consistent with central list'); ?></option>
+ </optgroup>
+ <?php endif; ?>
+ </select>
+ <?php echo implode("\n", $hidden_fields); ?>
+</div> \ No newline at end of file
diff --git a/templates/database/structure/empty_table.phtml b/templates/database/structure/empty_table.phtml
new file mode 100644
index 0000000000..329895c2b4
--- /dev/null
+++ b/templates/database/structure/empty_table.phtml
@@ -0,0 +1,3 @@
+<a class="truncate_table_anchor ajax" href="sql.php<?php echo $tbl_url_query; ?>&amp;sql_query=<?php echo $sql_query; ?>&amp;message_to_show=<?php echo $message_to_show; ?>">
+ <?php echo $title; ?>
+</a>
diff --git a/templates/database/structure/favorite_anchor.phtml b/templates/database/structure/favorite_anchor.phtml
new file mode 100644
index 0000000000..491ca89a29
--- /dev/null
+++ b/templates/database/structure/favorite_anchor.phtml
@@ -0,0 +1,15 @@
+<?php
+// Check if current table is already in favorite list.
+$fav_params = array('db' => $db,
+ 'ajax_request' => true,
+ 'favorite_table' => $current_table['TABLE_NAME'],
+ (($already_favorite ? 'remove' : 'add') . '_favorite') => true
+);
+?>
+<a id="<?php echo md5($current_table['TABLE_NAME']); ?>_favorite_anchor"
+ class="ajax favorite_table_anchor"
+ href="<?php echo 'db_structure.php' . PMA_URL_getCommon($fav_params); ?>"
+ title="<?php echo $already_favorite ? __("Remove from Favorites") : __("Add to Favorites"); ?>"
+ data-favtargets="<?php echo md5($db . "." . $current_table['TABLE_NAME']); ?>" >
+ <?php echo !$already_favorite ? $titles['NoFavorite'] : $titles['Favorite']; ?>
+</a>
diff --git a/templates/database/structure/print_view_data_dictionary_link.phtml b/templates/database/structure/print_view_data_dictionary_link.phtml
new file mode 100644
index 0000000000..aaaa227d1e
--- /dev/null
+++ b/templates/database/structure/print_view_data_dictionary_link.phtml
@@ -0,0 +1,7 @@
+<p class="print_ignore">
+ <a href="#" id="printView">
+ <?php echo PMA_Util::getIcon('b_print.png', __('Print view'), true); ?>
+ </a>
+ <a href="db_datadict.php<?php echo $url_query; ?>" target="print_view">
+ <?php echo PMA_Util::getIcon('b_tblanalyse.png', __('Data dictionary'), true); ?></a>
+</p> \ No newline at end of file
diff --git a/templates/database/structure/search_table.phtml b/templates/database/structure/search_table.phtml
new file mode 100644
index 0000000000..20040454ed
--- /dev/null
+++ b/templates/database/structure/search_table.phtml
@@ -0,0 +1,3 @@
+<a href="tbl_select.php<?php echo $tbl_url_query; ?>">
+ <?php echo $title; ?>
+</a>
diff --git a/templates/database/structure/show_create.phtml b/templates/database/structure/show_create.phtml
new file mode 100644
index 0000000000..7b36d13ca4
--- /dev/null
+++ b/templates/database/structure/show_create.phtml
@@ -0,0 +1,37 @@
+<div class="show_create_results">
+ <h2><?php echo __('Showing create queries'); ?></h2>
+ <?php
+ $views = array();
+ $tables = array();
+ foreach ($db_objects as $object) {
+ if ($GLOBALS['dbi']->getTable($db, $object)->isView()) {
+ $views [] = $object;
+ } else {
+ $tables [] = $object;
+ }
+ }
+ ?>
+ <?php if (! empty($tables)): ?>
+ <?php
+ echo PMA\Template::get('database/structure/show_create_row')->render(
+ array(
+ 'title' => __('Tables'),
+ 'raw_title' => 'Table',
+ 'db_objects' => $tables
+ )
+ );
+ ?>
+ <?php endif; ?>
+
+ <?php if (! empty($views)): ?>
+ <?php
+ echo PMA\Template::get('database/structure/show_create_row')->render(
+ array(
+ 'title' => __('Views'),
+ 'raw_title' => 'View',
+ 'db_objects' => $views
+ )
+ );
+ ?>
+ <?php endif; ?>
+</div> \ No newline at end of file
diff --git a/templates/database/structure/show_create_row.phtml b/templates/database/structure/show_create_row.phtml
new file mode 100644
index 0000000000..fee7bd10c0
--- /dev/null
+++ b/templates/database/structure/show_create_row.phtml
@@ -0,0 +1,22 @@
+<fieldset>
+ <legend><?php echo $title; ?></legend>
+ <table class="show_create">
+ <thead>
+ <tr>
+ <th><?php echo $raw_title; ?></th>
+ <th>Create <?php echo $raw_title; ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php $odd = true; ?>
+ <?php foreach ($db_objects as $object): ?>
+ <?php $row_class = ($odd) ? 'odd' : 'even'; ?>
+ <tr class="<?php echo $row_class; ?>">
+ <td><strong><?php echo PMA_mimeDefaultFunction($object); ?></strong></td>
+ <td><?php echo PMA_mimeDefaultFunction($GLOBALS['dbi']->getTable($db, $object)->showCreate()); ?></td>
+ </tr>
+ <?php $odd = ! $odd; ?>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+</fieldset>
diff --git a/templates/database/structure/sortable_header.phtml b/templates/database/structure/sortable_header.phtml
new file mode 100644
index 0000000000..d3cec6fd63
--- /dev/null
+++ b/templates/database/structure/sortable_header.phtml
@@ -0,0 +1,66 @@
+<?php
+$requested_sort = 'table';
+$requested_sort_order = $future_sort_order = $initial_sort_order;
+// If the user requested a sort
+if (isset($_REQUEST['sort'])) {
+ $requested_sort = $_REQUEST['sort'];
+ if (isset($_REQUEST['sort_order'])) {
+ $requested_sort_order = $_REQUEST['sort_order'];
+ }
+}
+$order_img = '';
+$order_link_params = array();
+$order_link_params['title'] = __('Sort');
+// If this column was requested to be sorted.
+if ($requested_sort == $sort) {
+ if ($requested_sort_order == 'ASC') {
+ $future_sort_order = 'DESC';
+ // current sort order is ASC
+ $order_img = ' ' . PMA_Util::getImage(
+ 's_asc.png',
+ __('Ascending'),
+ array('class' => 'sort_arrow', 'title' => '')
+ );
+ $order_img .= ' ' . PMA_Util::getImage(
+ 's_desc.png',
+ __('Descending'),
+ array('class' => 'sort_arrow hide', 'title' => '')
+ );
+ // but on mouse over, show the reverse order (DESC)
+ $order_link_params['onmouseover'] = "$('.sort_arrow').toggle();";
+ // on mouse out, show current sort order (ASC)
+ $order_link_params['onmouseout'] = "$('.sort_arrow').toggle();";
+ } else {
+ $future_sort_order = 'ASC';
+ // current sort order is DESC
+ $order_img = ' ' . PMA_Util::getImage(
+ 's_asc.png',
+ __('Ascending'),
+ array('class' => 'sort_arrow hide', 'title' => '')
+ );
+ $order_img .= ' ' . PMA_Util::getImage(
+ 's_desc.png',
+ __('Descending'),
+ array('class' => 'sort_arrow', 'title' => '')
+ );
+ // but on mouse over, show the reverse order (ASC)
+ $order_link_params['onmouseover'] = "$('.sort_arrow').toggle();";
+ // on mouse out, show current sort order (DESC)
+ $order_link_params['onmouseout'] = "$('.sort_arrow').toggle();";
+ }
+}
+$_url_params = array(
+ 'db' => $_REQUEST['db'],
+);
+$url = 'db_structure.php' . PMA_URL_getCommon($_url_params);
+// We set the position back to 0 every time they sort.
+$url .= "&amp;pos=0&amp;sort=$sort&amp;sort_order=$future_sort_order";
+if (! empty($_REQUEST['tbl_type'])) {
+ $url .= "&amp;tbl_type=" . $_REQUEST['tbl_type'];
+}
+if (! empty($_REQUEST['tbl_group'])) {
+ $url .= "&amp;tbl_group=" . $_REQUEST['tbl_group'];
+}
+echo PMA_Util::linkOrButton(
+ $url, $title . $order_img, $order_link_params
+); \ No newline at end of file
diff --git a/templates/database/structure/structure_table_row.phtml b/templates/database/structure/structure_table_row.phtml
new file mode 100644
index 0000000000..63df1a0b5e
--- /dev/null
+++ b/templates/database/structure/structure_table_row.phtml
@@ -0,0 +1,187 @@
+<tr class="<?php echo $odd_row ? 'odd' : 'even'; ?> <?php if ($table_is_view) echo 'is_view'; ?>"
+ id="row_tbl_<?php echo $curr; ?>">
+ <td class="center print_ignore">
+ <input type="checkbox"
+ name="selected_tbl[]"
+ class="checkall"
+ value="<?php echo htmlspecialchars($current_table['TABLE_NAME']); ?>"
+ id="checkbox_tbl_<?php echo $curr; ?>" />
+ </td>
+ <th>
+ <?php echo $browse_table_label . $tracking_icon; ?>
+ </th>
+ <?php if ($server_slave_status): ?>
+ <td class="center">
+ <?php echo ($ignored ? PMA_Util::getImage('s_cancel.png', __('Not replicated')) : ''); ?>
+ <?php echo ($do ? PMA_Util::getImage('s_success.png', __('Replicated')) : ''); ?>
+ </td>
+ <?php endif; ?>
+
+ <?php
+ //Favorite table anchor.
+ ?>
+ <?php if ($GLOBALS['cfg']['NumFavoriteTables'] > 0): ?>
+ <td class="center print_ignore">
+ <?php echo PMA\Template::get('database/structure/favorite_anchor')->render(
+ array(
+ 'db' => $db,
+ 'current_table' => $current_table,
+ 'titles' => $titles,
+ 'already_favorite' => $already_favorite
+ )
+ ); ?>
+ </td>
+ <?php endif; ?>
+
+ <td class="center print_ignore">
+ <?php echo $browse_table; ?>
+ </td>
+ <td class="center print_ignore">
+ <a href="tbl_structure.php<?php echo $tbl_url_query; ?>">
+ <?php echo $titles['Structure']; ?>
+ </a>
+ </td>
+ <td class="center print_ignore">
+ <?php echo $search_table; ?>
+ </td>
+
+ <?php if (!$db_is_system_schema): ?>
+ <td class="insert_table center print_ignore">
+ <a href="tbl_change.php<?php echo $tbl_url_query; ?>"><?php echo $titles['Insert']; ?></a>
+ </td>
+ <td class="center print_ignore"><?php echo $empty_table; ?></td>
+ <td class="center print_ignore">
+ <a class="ajax drop_table_anchor <?php if ($table_is_view || $current_table['ENGINE'] == null) echo 'view'; ?>"
+ href="sql.php<?php echo $tbl_url_query; ?>&amp;reload=1&amp;purge=1&amp;sql_query=<?php echo urlencode($drop_query); ?>&amp;message_to_show=<?php echo urlencode($drop_message); ?>" >
+ <?php echo $titles['Drop']; ?>
+ </a>
+ </td>
+ <?php endif; ?>
+
+ <?php if (isset($current_table['TABLE_ROWS']) &&
+ ($current_table['ENGINE'] != null || $table_is_view)): ?>
+
+ <?php
+ // Get the row count.
+ $row_count = PMA_Util::formatNumber($current_table['TABLE_ROWS'], 0);
+
+ // Content to be appended into 'tbl_rows' cell.
+ // If row count is approximate, display it as an anchor to get real count.
+ ?>
+ <td class="value tbl_rows"
+ data-table="<?php echo htmlspecialchars($current_table['TABLE_NAME']); ?>">
+ <?php if ($approx_rows): ?>
+ <a href="db_structure.php<?php echo PMA_URL_getCommon(
+ array(
+ 'ajax_request' => true,
+ 'db' => $GLOBALS['db'],
+ 'table' => $current_table['TABLE_NAME'],
+ 'real_row_count' => 'true'
+ )
+ ); ?>" class="ajax real_row_count">
+ <bdi>
+ ~<?php echo $row_count; ?>
+ </bdi>
+ </a>
+ <?php else: ?>
+ <?php echo $row_count; ?>
+ <?php endif; ?>
+ <?php echo $show_superscript; ?>
+ </td>
+
+ <?php if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)): ?>
+ <td class="nowrap">
+ <?php if (!empty($current_table['ENGINE'])): ?>
+ <?php echo $current_table['ENGINE']; ?>
+ <?php elseif ($table_is_view): ?>
+ <?php echo __('View'); ?>
+ <?php endif; ?>
+ </td>
+ <?php if (/*overload*/mb_strlen($collation)): ?>
+ <td class="nowrap">
+ <?php echo $collation; ?>
+ </td>
+ <?php endif; ?>
+ <?php endif; ?>
+
+ <?php if ($is_show_stats): ?>
+ <td class="value tbl_size">
+ <a href="tbl_structure.php<?php echo $tbl_url_query ?>#showusage">
+ <span><?php echo $formatted_size; ?></span>
+ <span class="unit"><?php echo $unit; ?></span>
+ </a>
+ </td>
+ <td class="value tbl_overhead">
+ <?php echo $overhead; ?>
+ </td>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureComment']): ?>
+ <?php $comment = $current_table['Comment']; ?>
+ <td>
+ <?php if (/*overload*/mb_strlen($comment) > $GLOBALS['cfg']['LimitChars']): ?>
+ <abbr title="<?php echo htmlspecialchars($comment); ?>">
+ <?php echo htmlspecialchars(
+ /*overload*/mb_substr(
+ $comment, 0, $GLOBALS['cfg']['LimitChars']
+ )
+ ); ?>
+ ...
+ </abbr>
+ <?php else: ?>
+ <?php echo htmlspecialchars($comment); ?>
+ <?php endif; ?>
+ </td>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureCreation']): ?>
+ <td class="value tbl_creation">
+ <?php echo $create_time ? PMA_Util::localisedDate(strtotime($create_time)) : '-'; ?>
+ </td>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']): ?>
+ <td class="value tbl_last_update">
+ <?php echo $update_time ? PMA_Util::localisedDate(strtotime($update_time)) : '-'; ?>
+ </td>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureLastCheck']): ?>
+ <td class="value tbl_last_check">
+ <?php echo $check_time ? PMA_Util::localisedDate(strtotime($check_time)) : '-'; ?>
+ </td>
+ <?php endif; ?>
+
+ <?php elseif ($table_is_view): ?>
+
+ <td class="value tbl_rows">-</td>
+ <td class="nowrap">
+ <?php echo __('View'); ?>
+ </td>
+ <td class="nowrap">---</td>
+ <?php if ($is_show_stats): ?>
+ <td class="value tbl_size">-</td>
+ <td class="value tbl_overhead">-</td>
+ <?php endif; ?>
+ <?php if ($GLOBALS['cfg']['ShowDbStructureComment']): ?>
+ <td></td>
+ <?php endif; ?>
+ <?php if ($GLOBALS['cfg']['ShowDbStructureCreation']): ?>
+ <td class="value tbl_creation">-</td>
+ <?php endif; ?>
+ <?php if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']): ?>
+ <td class="value tbl_last_update">-</td>
+ <?php endif; ?>
+ <?php if ($GLOBALS['cfg']['ShowDbStructureLastCheck']): ?>
+ <td class="value tbl_last_check">-</td>
+ <?php endif; ?>
+
+ <?php else: ?>
+
+ <td colspan="<?php echo $colspan_for_structure - ($db_is_system_schema ? 6 : 9); ?>"
+ class="center">
+ <?php echo __('in use'); ?>
+ </td>
+
+ <?php endif; ?>
+</tr>
diff --git a/templates/database/structure/table_header.phtml b/templates/database/structure/table_header.phtml
new file mode 100644
index 0000000000..22a90ba61d
--- /dev/null
+++ b/templates/database/structure/table_header.phtml
@@ -0,0 +1,127 @@
+<?php
+$cnt = 0; // Let's count the columns...
+
+if ($db_is_system_schema) {
+ $action_colspan = 3;
+} else {
+ $action_colspan = 6;
+}
+if ($GLOBALS['cfg']['NumFavoriteTables'] > 0) {
+ $action_colspan++;
+}
+?>
+<form method="post" action="db_structure.php" name="tablesForm" id="tablesForm">
+<?php echo PMA_URL_getHiddenInputs($db); ?>
+<table class="data">
+ <thead>
+ <tr>
+ <th class="print_ignore"></th>
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Table'),
+ 'sort' => 'table',
+ 'initial_sort_order' => 'ASC'
+ )
+ ); ?></th>
+ <?php if ($replication): ?>
+ <th><?php echo __('Replication'); ?></th>
+ <?php endif; ?>
+ <th colspan="<?php echo $action_colspan; ?>" class="print_ignore">
+ <?php echo __('Action'); ?>
+ </th>
+ <!-- larger values are more interesting so default sort order is DESC-->
+ <th>
+ <?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Rows'),
+ 'sort' => 'records',
+ 'initial_sort_order' => 'DESC'
+ )
+ ); ?>
+ <?php echo PMA_Util::showHint(PMA_sanitize(
+ __('May be approximate. Click on the number to get the exact'
+ . ' count. See [doc@faq3-11]FAQ 3.11[/doc].'))); ?>
+ </th>
+ <?php if (!($GLOBALS['cfg']['PropertiesNumColumns'] > 1)): ?>
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Type'),
+ 'sort' => 'type',
+ 'initial_sort_order' => 'ASC'
+ )
+ ); $cnt++; ?></th>
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Collation'),
+ 'sort' => 'collation',
+ 'initial_sort_order' => 'ASC'
+ )
+ ); $cnt++; ?></th>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['is_show_stats']): ?>
+ <!-- larger values are more interesting so default sort order is DESC -->
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Size'),
+ 'sort' => 'size',
+ 'initial_sort_order' => 'DESC'
+ )
+ ); $cnt++; ?></th>
+ <!-- larger values are more interesting so default sort order is DESC -->
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Overhead'),
+ 'sort' => 'overhead',
+ 'initial_sort_order' => 'DESC'
+ )
+ ); $cnt++; ?></th>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureComment']): ?>
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Comment'),
+ 'sort' => 'comment',
+ 'initial_sort_order' => 'ASC'
+ )
+ ); $cnt++; ?></th>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureCreation']): ?>
+ <!-- newer values are more interesting so default sort order is DESC -->
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Creation'),
+ 'sort' => 'creation',
+ 'initial_sort_order' => 'DESC'
+ )
+ ); $cnt++; ?></th>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']): ?>
+ <!-- newer values are more interesting so default sort order is DESC -->
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Last update'),
+ 'sort' => 'last_update',
+ 'initial_sort_order' => 'DESC'
+ )
+ ); $cnt++; ?></th>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfg']['ShowDbStructureLastCheck']): ?>
+ <!-- newer values are more interesting so default sort order is DESC -->
+ <th><?php echo PMA\Template::get('database/structure/sortable_header')->render(
+ array(
+ 'title' => __('Last check'),
+ 'sort' => 'last_check',
+ 'initial_sort_order' => 'DESC'
+ )
+ ); $cnt++; ?></th>
+ <?php endif; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <?php $GLOBALS['colspan_for_structure'] = $cnt + $action_colspan + 3; ?>
+
diff --git a/templates/database/structure/tracking_icon.phtml b/templates/database/structure/tracking_icon.phtml
new file mode 100644
index 0000000000..7ea3e9791f
--- /dev/null
+++ b/templates/database/structure/tracking_icon.phtml
@@ -0,0 +1,11 @@
+<a href="tbl_tracking.php<?php echo $url_query; ?>&amp;table=<?php echo $truename; ?>">
+ <?php if ($is_tracked): ?>
+ <?php echo PMA_Util::getImage(
+ 'eye.png', __('Tracking is active.')
+ ); ?>
+ <?php else: ?>
+ <?php echo PMA_Util::getImage(
+ 'eye_grey.png', __('Tracking is not active.')
+ ); ?>
+ <?php endif; ?>
+</a> \ No newline at end of file
diff --git a/templates/error/report_form.phtml b/templates/error/report_form.phtml
new file mode 100644
index 0000000000..afca5a3148
--- /dev/null
+++ b/templates/error/report_form.phtml
@@ -0,0 +1,35 @@
+<form action="error_report.php" method="post" name="report_frm" id="report_frm"
+ class="ajax">
+ <fieldset style="padding-top:0">
+
+ <p>
+ <?php echo __(
+ 'phpMyAdmin has encountered an error. We have collected data about'
+ . ' this error as well as information about relevant configuration'
+ . ' settings to send to the phpMyAdmin team to help us in'
+ . ' debugging the problem.'
+ ) ?>
+ </p>
+
+ <div class="label"><label><p>
+ <?php echo __('You may examine the data in the error report:') ?>
+ </p></label></div>
+ <pre class="report-data"><?php echo htmlspecialchars($report_data) ?></pre>
+
+ <div class="label"><label><p>
+ <?php echo __('Please explain the steps that lead to the error:') ?>
+ </p></label>
+ </div>
+ <textarea class="report-description" name="description"
+ id="report_description"></textarea>
+
+ <input type="checkbox" name="always_send" id="always_send_checkbox" />
+ <label for="always_send_checkbox">
+ <?php echo __('Automatically send report next time') ?>
+ </label>
+
+ </fieldset>
+
+ <?php echo $hidden_inputs ?>
+ <?php echo $hidden_fields ?>
+</form> \ No newline at end of file
diff --git a/templates/header_location.phtml b/templates/header_location.phtml
new file mode 100644
index 0000000000..6e8246569d
--- /dev/null
+++ b/templates/header_location.phtml
@@ -0,0 +1,32 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Manage HTML redirection
+ *
+ * @package PhpMyAdmin-template
+ *
+ * @param string $uri Redirection location
+ */
+$uri = isset($uri) ? $uri : null;
+?>
+<html>
+<head>
+ <title>- - -</title>
+ <meta http-equiv="expires" content="0">
+ <meta http-equiv="Pragma" content="no-cache">
+ <meta http-equiv="Cache-Control" content="no-cache">
+ <meta http-equiv="Refresh" content="0;url=<?php echo htmlspecialchars($uri) ?>">
+ <script type="text/javascript">
+ //<![CDATA[
+ setTimeout("window.location = decodeURI('<?php echo PMA_escapeJsString($uri) ?>')", 2000);
+ //]]>
+ </script>
+</head>
+<body>
+<script type="text/javascript">
+ //<![CDATA[
+ document.write('<p><a href="<?php echo htmlspecialchars($uri) ?>"><?php echo __('Go') ?></a></p>');
+ //]]>
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/templates/javascript/display.phtml b/templates/javascript/display.phtml
new file mode 100644
index 0000000000..8a8be7c621
--- /dev/null
+++ b/templates/javascript/display.phtml
@@ -0,0 +1,7 @@
+<script type="text/javascript">
+if (typeof configInlineParams === "undefined" || !Array.isArray(configInlineParams)) configInlineParams = [];
+configInlineParams.push(function() {
+<?php echo implode(";\n", $js_array); ?>;
+});
+if (typeof configScriptLoaded !== "undefined" && configInlineParams) loadInlineConfig();
+</script> \ No newline at end of file
diff --git a/templates/list/item.phtml b/templates/list/item.phtml
new file mode 100644
index 0000000000..8c1403e904
--- /dev/null
+++ b/templates/list/item.phtml
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Display item of a list.
+ *
+ * $content - mandatory string - Content to display
+ * $id - optional string - Contains the id of li tag
+ * $class - optional string - Contains the class name(s) of li tag
+ * $mysql_help_page - optional string - Related help page
+ * $url - optional array: - href - optional string - Destination page or anchor
+ * - target - optional string - Target of link
+ * - class - optional string - Class of link
+ * - title - optional string - Title of link
+ */
+?>
+<li<?php
+echo !empty($id) ? ' id="' . $id . '"' : null;
+echo !empty($class) ? ' class="' . $class . '"' : null;
+?>>
+ <?php
+ if (!empty($url) && is_array($url)) : ?>
+ <a<?php echo !empty($url['href']) ? ' href="' . $url['href'] . '"' : null ?>"
+ <?php
+ echo !empty($url['target'])
+ ? ' target="' . $url['target'] . '"'
+ : null;
+ ?>
+ <?php echo !empty($url['id']) ? ' id="' . $url['id'] . '"' : null; ?>
+ <?php
+ echo !empty($url['class'])
+ ? ' class="' . $url['class'] . '"'
+ : null;
+ ?>
+ <?php
+ echo !empty($url['title'])
+ ? ' title="' . $url['title'] . '"'
+ : null;
+ ?>>
+ <?php
+ endif;
+ echo $content;
+ if (!empty($url) && is_array($url)) : ?>
+ </a>
+ <?php
+ endif;
+ if (!empty($mysql_help_page)) :
+ echo PMA_Util::showMySQLDocu($mysql_help_page);
+ endif;
+ ?>
+</li> \ No newline at end of file
diff --git a/templates/list/unordered.phtml b/templates/list/unordered.phtml
new file mode 100644
index 0000000000..0d8557dade
--- /dev/null
+++ b/templates/list/unordered.phtml
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Display unordered list.
+ *
+ * $class - optional string - Contains the class name(s) of ul tag
+ * $id - optional string - Contains the id of ul tag
+ * $item - mandatory string|array - If string, this is the content
+ * - Else, see templates/list/item.phtml
+ * $content - mandatory string - Content to display if $item is empty
+ */
+?>
+<ul<?php
+echo !empty($class) ? ' class="' . $class . '"' : null;
+echo !empty($id) ? ' id="' . $id . '"' : null;
+?>>
+ <?php
+ if (!empty($items)) :
+ foreach ($items as $item) :
+ if (!is_array($item)) {
+ $item = array('content' => $item);
+ }
+ echo PMA\Template::get('list/item')
+ ->render($item);
+ endforeach;
+ elseif (!empty($content)) :
+ echo $content;
+ endif;
+ ?>
+</ul> \ No newline at end of file
diff --git a/templates/navigation/logo.phtml b/templates/navigation/logo.phtml
new file mode 100644
index 0000000000..f18db13b88
--- /dev/null
+++ b/templates/navigation/logo.phtml
@@ -0,0 +1,44 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Manage logo display
+ *
+ * @package PhpMyAdmin-template
+ *
+ * @param bool $displayLogo Display logo or not
+ * @param bool $useLogoLink Use link on logo or not
+ * @param string $logoLink Destination of link on logo
+ * @param string $linkAttribs Link's attributes
+ */
+$displayLogo = isset($displayLogo) ? $displayLogo : true;
+$useLogoLink = isset($useLogoLink) ? $useLogoLink : false;
+$logoLink = isset($logoLink) ? $logoLink : '#';
+$linkAttribs = isset($linkAttribs) ? $linkAttribs : null;
+if (!isset($logo)) {
+ $logo = null;
+ if (isset($GLOBALS['pmaThemeImage'])) {
+ $imgTag = '<img src="' . $GLOBALS['pmaThemeImage'] . '%s" '
+ . 'alt="phpMyAdmin" id="imgpmalogo" />';
+ if (@file_exists($GLOBALS['pmaThemeImage'] . 'logo_left.png')) {
+ $logo = sprintf($imgTag, 'logo_left.png');
+ } elseif (@file_exists($GLOBALS['pmaThemeImage'] . 'pma_logo2.png')) {
+ $logo = sprintf($imgTag, 'pma_logo2.png');
+ }
+ }
+}
+?>
+<!-- LOGO START -->
+<?php if (false === $displayLogo) : ?>
+ <!-- LOGO END -->
+ <?php return; ?>
+<?php endif; ?>
+<div id="pmalogo">
+ <?php if (true === $useLogoLink) : ?>
+ <a href="<?php echo $logoLink; ?>"<?php echo isset($linkAttribs) ? ' ' . $linkAttribs : null; ?>>
+ <?php endif; ?>
+ <?php echo $logo; ?>
+ <?php if (true === $useLogoLink) : ?>
+ </a>
+ <?php endif; ?>
+</div>
+<!-- LOGO END --> \ No newline at end of file
diff --git a/templates/prefs_autoload.phtml b/templates/prefs_autoload.phtml
new file mode 100644
index 0000000000..bfd7d3f64a
--- /dev/null
+++ b/templates/prefs_autoload.phtml
@@ -0,0 +1,17 @@
+<div id="prefs_autoload" class="notice print_ignore" style="display:none">
+ <form action="prefs_manage.php" method="post" class="disableAjax">
+ <?php echo $hiddenInputs; ?>
+ <input type="hidden" name="json" value="" />
+ <input type="hidden" name="submit_import" value="1" />
+ <input type="hidden" name="return_url" value="<?php echo $return_url ?>" />
+ <?php
+ echo __(
+ 'Your browser has phpMyAdmin configuration for this domain. '
+ . 'Would you like to import it for current session?'
+ );
+ ?>
+ <br />
+ <a href="#yes"><?php echo __('Yes') ?></a>
+ / <a href="#no"><?php echo __('No') ?></a>
+ </form>
+</div> \ No newline at end of file
diff --git a/templates/preview_sql.phtml b/templates/preview_sql.phtml
new file mode 100644
index 0000000000..4529b0f76b
--- /dev/null
+++ b/templates/preview_sql.phtml
@@ -0,0 +1,11 @@
+<div class="preview_sql">
+ <?php if (empty($query_data)): ?>
+ <?php echo __('No change'); ?>
+ <?php elseif (is_array($query_data)): ?>
+ <?php foreach ($query_data as $query): ?>
+ <?php echo PMA_Util::formatSql($query); ?>
+ <?php endforeach; ?>
+ <?php else: ?>
+ <?php echo PMA_Util::formatSql($query_data); ?>
+ <?php endif; ?>
+</div>
diff --git a/templates/secondary_tabs.phtml b/templates/secondary_tabs.phtml
new file mode 100644
index 0000000000..166a1d9ce3
--- /dev/null
+++ b/templates/secondary_tabs.phtml
@@ -0,0 +1,6 @@
+<ul id="topmenu2">
+ <?php foreach ($sub_tabs as $tab): ?>
+ <?php echo PMA_Util::getHtmlTab($tab, $url_params); ?>
+ <?php endforeach; ?>
+</ul>
+<div class="clearfloat"></div>
diff --git a/templates/startAndNumberOfRowsPanel.phtml b/templates/startAndNumberOfRowsPanel.phtml
new file mode 100644
index 0000000000..eb7cc1747b
--- /dev/null
+++ b/templates/startAndNumberOfRowsPanel.phtml
@@ -0,0 +1,20 @@
+<fieldset>
+ <div>
+ <label for="pos"><?php echo __('Start row:'); ?></label>
+ <input type="number" name="pos" min="0" required="required"
+ <?php if ($unlim_num_rows > 0) : ?>
+ max="<?php echo ($unlim_num_rows - 1); ?>"
+ <?php endif; ?>
+ value="<?php echo htmlspecialchars($pos); ?>" />
+
+ <label for="session_max_rows"><?php echo __('Number of rows:'); ?></label>
+ <input type="number" name="session_max_rows" min="1"
+ value="<?php echo htmlspecialchars($rows); ?>" required="required" />
+ <input type="submit" name="submit" class="Go"
+ value="<?php echo __('Go'); ?>" />
+ <input type="hidden" name="sql_query"
+ value="<?php echo htmlspecialchars($sql_query); ?>" />
+ <input type="hidden" name="unlim_num_rows"
+ value="<?php echo htmlspecialchars($unlim_num_rows); ?>" />
+ </div>
+</fieldset> \ No newline at end of file
diff --git a/templates/table/chart/tbl_chart.phtml b/templates/table/chart/tbl_chart.phtml
new file mode 100644
index 0000000000..ee17eaa582
--- /dev/null
+++ b/templates/table/chart/tbl_chart.phtml
@@ -0,0 +1,158 @@
+<?php require_once 'libraries/url_generating.lib.php'; ?>
+<script type="text/javascript">
+ pma_token = '<?php echo $_SESSION[' PMA_token ']; ?>';
+ url_query = '<?php echo $url_query; ?>';
+</script>
+<!-- Display Chart options -->
+<div id="div_view_options">
+ <form method="post" id="tblchartform" action="tbl_chart.php" class="ajax">
+ <?php echo PMA_URL_getHiddenInputs($url_params); ?>
+ <fieldset>
+ <legend>
+ <?php echo __('Display chart'); ?>
+ </legend>
+ <div class="chartOption">
+ <div class="formelement">
+ <input type="radio" name="chartType" value="bar" id="radio_bar" />
+ <label for ="radio_bar"><?php echo _pgettext('Chart type', 'Bar') ?></label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="column" id="radio_column" />
+ <label for ="radio_column"><?php echo _pgettext('Chart type', 'Column') ?></label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="line" id="radio_line" checked="checked" />
+ <label for ="radio_line"><?php echo _pgettext('Chart type', 'Line') ?></label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="spline" id="radio_spline" />
+ <label for ="radio_spline"><?php echo _pgettext('Chart type', 'Spline') ?></label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="area" id="radio_area" />
+ <label for ="radio_area"><?php echo _pgettext('Chart type', 'Area') ?></label>
+ </div>
+ <span class="span_pie" style="display:none;">
+ <input type="radio" name="chartType" value="pie" id="radio_pie" />
+ <label for ="radio_pie"><?php echo _pgettext('Chart type', 'Pie') ?></label>
+ </span>
+ <span class="span_timeline" style="display:none;">
+ <input type="radio" name="chartType" value="timeline" id="radio_timeline" />
+ <label for ="radio_timeline"><?php echo _pgettext('Chart type', 'Timeline') ?></label>
+ </span>
+ <span class="span_scatter" style="display:none;">
+ <input type="radio" name="chartType" value="scatter" id="radio_scatter" />
+ <label for ="radio_scatter"><?php echo _pgettext('Chart type', 'Scatter') ?></label>
+ </span>
+ <br /><br />
+ <span class="barStacked" style="display:none;">
+ <input type="checkbox" name="barStacked" value="1" id="checkbox_barStacked" />
+ <label for ="checkbox_barStacked"><?php echo __('Stacked') ?></label>
+ </span>
+ <br /><br />
+ <input type="text" name="chartTitle" value="<?php echo __('Chart title'); ?>">
+ </div>
+ <?php $xaxis = null; ?>
+ <div class="chartOption">
+ <label for="select_chartXAxis"><?php echo __('X-Axis:'); ?></label>
+ <select name="chartXAxis" id="select_chartXAxis">
+ <?php foreach ($keys as $idx => $key) : ?>
+ <?php if ($xaxis === null) : ?>
+ <?php $xaxis = $idx; ?>
+ <?php endif; ?>
+ <?php if ($xaxis === $idx) : ?>
+ <option value="<?php echo htmlspecialchars($idx); ?>" selected="selected"><?php echo htmlspecialchars($key); ?></option>
+ <?php else : ?>
+ <option value="<?php echo htmlspecialchars($idx); ?>"><?php echo htmlspecialchars($key); ?></option>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <label for="select_chartSeries">
+ <?php echo __('Series:'); ?>
+ </label>
+ <select name="chartSeries" id="select_chartSeries" multiple="multiple">
+ <?php foreach ($keys as $idx => $key) : ?>
+ <?php if (in_array($fields_meta[$idx]->type, $numeric_types)) : ?>
+ <?php if ($idx == $xaxis && $numeric_column_count > 1) : ?>
+ <option value="<?php echo htmlspecialchars($idx); ?>"><?php echo htmlspecialchars($key); ?></option>
+ <?php else : ?>
+ <option value="<?php echo htmlspecialchars($idx); ?>" selected="selected"><?php echo htmlspecialchars($key); ?></option>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach;?>
+ </select>
+ <input type="hidden" name="dateTimeCols" value="<?php $date_time_types = array('date', 'datetime', 'timestamp');
+ foreach ($keys as $idx => $key) {
+ if (in_array($fields_meta[$idx]->type, $date_time_types)) {
+ echo $idx . ' ';
+ }
+ }?>"
+ />
+ <input type="hidden" name="numericCols" value="<?php
+ foreach ($keys as $idx => $key) {
+ if (in_array($fields_meta[$idx]->type, $numeric_types)) {
+ echo $idx . ' ';
+ }
+ }?>"
+ />
+ </div>
+ <div class="chartOption">
+ <label for="xaxis_panel">
+ <?php echo __('X-Axis label:'); ?>
+ </label>
+ <input style="margin-top:0;" type="text" name="xaxis_label" id="xaxis_label" value="<?php echo (($xaxis == -1) ? __('X Values') : htmlspecialchars($keys[$xaxis])); ?>" />
+ <br />
+ <label for="yaxis_label">
+ <?php echo __('Y-Axis label:'); ?>
+ </label>
+ <input type="text" name="yaxis_label" id="yaxis_label" value="<?php echo __('Y Values'); ?>" />
+ <br />
+ </div>
+ <p style="clear:both;">&nbsp;</p>
+ <div>
+ <input type="checkbox" id="chkAlternative" name="chkAlternative" value="alternativeFormat" />
+ <label for="chkAlternative"><?php echo __('Series names are in a column'); ?></label>
+ <br />
+ <label for="select_seriesColumn">
+ <?php echo __('Series column:'); ?>
+ </label>
+ <select name="chartSeriesColumn" id="select_seriesColumn" disabled>
+ <?php foreach ($keys as $idx => $key) : ?>
+ <option value="<?php echo htmlspecialchars($idx);
+ if ($idx == 1) : echo ' selected="selected"'; endif;
+ $seriesColumn = $idx; ?>">
+ <?php echo htmlspecialchars($key); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ <label for="select_valueColumn">
+ <?php echo __('Value Column:'); ?>
+ </label>
+ <select name="chartValueColumn" id="select_valueColumn" disabled>
+ <?php $selected = false;
+ foreach ($keys as $idx => $key) : ?>
+ <?php if (in_array($fields_meta[$idx]->type, $numeric_types)) : ?>
+ <?php if (! $selected && $idx != $xaxis && $idx != $seriesColumn) : ?>
+ <option value="<?php echo htmlspecialchars($idx); ?>" selected="selected"><?php echo htmlspecialchars($key); $selected = true; ?></option>
+ <?php else: ?>
+ <option value="<?php echo htmlspecialchars($idx); ?>"><?php echo htmlspecialchars($key); ?></option>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ </select>
+ </div>
+ <?php echo PMA_Util::getStartAndNumberOfRowsPanel($sql_query); ?>
+ <p style="clear:both;">&nbsp;</p>
+ <div id="resizer" style="width:600px; height:400px;">
+ <div style="position: absolute; right: 10px; top: 10px; cursor: pointer; z-index: 1000;">
+ <a class="disableAjax" id="saveChart" href="#" download="chart.png">
+ <?php echo PMA_Util::getImage('b_saveimage', __('Save chart as image')); ?>
+ </a>
+ </div>
+ <div id="querychart" dir="ltr">
+ </div>
+ </div>
+ </fieldset>
+ </form>
+</div> \ No newline at end of file
diff --git a/templates/table/gis_visualization/gis_visualization.phtml b/templates/table/gis_visualization/gis_visualization.phtml
new file mode 100644
index 0000000000..60a8b5ec70
--- /dev/null
+++ b/templates/table/gis_visualization/gis_visualization.phtml
@@ -0,0 +1,84 @@
+<div id="div_view_options">
+ <fieldset>
+ <legend><?php echo __('Display GIS Visualization'); ?></legend>
+ <div id="gis_div" style="position:relative;">
+ <form method="post" action="tbl_gis_visualization.php">
+ <?php echo PMA_URL_getHiddenInputs($url_params); ?>
+ <label for="labelColumn">
+ <?php echo __("Label column"); ?>
+ </label>
+ <select name="visualizationSettings[labelColumn]" id="labelColumn" class="autosubmit">
+ <option value=""><?php echo __("-- None --"); ?></option>
+ <?php foreach ($labelCandidates as $value): ?>
+ <option value="<?php echo $value; ?>" <?php echo ($value == $visualizationSettings['labelColumn'] ? 'selected="selected"' : ''); ?>>
+ <?php echo $value; ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ <label for="spatialColumn">
+ <?php echo __("Spatial column"); ?>
+ </label>
+ <select name="visualizationSettings[spatialColumn]" id="spatialColumn" class="autosubmit">
+ <?php foreach ($spatialCandidates as $value): ?>
+ <option value="<?php echo $value; ?>" <?php echo ($value == $visualizationSettings['spatialColumn'] ? 'selected="selected"' : ''); ?>>
+ <?php echo $value; ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ <input type="hidden" name="displayVisualization" value="redraw">
+ <?php if (! $GLOBALS['PMA_Config']->isHttps()): ?>
+ <tr>
+ <td class="choice" colspan="2">
+ <input type="checkbox"
+ name="visualizationSettings[choice]"
+ id="choice" value="useBaseLayer"
+ <?php if (isset($visualizationSettings['choice'])) echo 'checked="checked"' ?>/>
+ <label for="choice">
+ <?php echo __("Use OpenStreetMaps as Base Layer"); ?>
+ </label>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php echo PMA_Util::getStartAndNumberOfRowsPanel($sql_query); ?>
+ </form>
+
+ <div class="pma_quick_warp" style="width: 50px; position: absolute; right: 0; top: 0; cursor: pointer;">
+ <div class="drop_list">
+ <span class="drop_button" style="padding: 0; border: 0;">
+ <?php echo PMA_Util::getImage('b_saveimage', __('Save')); ?>
+ </span>
+ <ul>
+ <li class="warp_link">
+ <a href="<?php echo $downloadUrl . '&fileFormat=png'; ?>" class="disableAjax">PNG</a>
+ </li>
+ <li class="warp_link">
+ <a href="<?php echo $downloadUrl . '&fileFormat=pdf'; ?>" class="disableAjax">PDF</a>
+ </li>
+ <?php if ($svgSupport): ?>
+ <li class="warp_link">
+ <a href="<?php echo $downloadUrl . '&fileFormat=svg'; ?>" class="disableAjax">SVG</a>
+ </li>
+ <?php endif; ?>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <div style="clear:both;">&nbsp;</div>
+
+ <div id="placeholder"
+ style="width:<?php echo htmlspecialchars($visualizationSettings['width']); ?>px;height:<?php echo htmlspecialchars($visualizationSettings['height']); ?>px;">
+ <?php echo $visualization; ?>
+ </div>
+ <div id="openlayersmap"></div>
+ <input type="hidden" id="pmaThemeImage" value="<?php echo $GLOBALS['pmaThemeImage']; ?>" />
+ <script language="javascript" type="text/javascript">
+ function drawOpenLayers()
+ {
+ <?php if (! $GLOBALS['PMA_Config']->isHttps()): ?>
+ <?php echo $drawOl; ?>
+ <?php endif; ?>
+ }
+ </script>
+ </fieldset>
+</div> \ No newline at end of file
diff --git a/templates/table/index_form.phtml b/templates/table/index_form.phtml
new file mode 100644
index 0000000000..05fb346218
--- /dev/null
+++ b/templates/table/index_form.phtml
@@ -0,0 +1,240 @@
+<form action="tbl_indexes.php"
+ method="post"
+ name="index_frm"
+ id="index_frm"
+ class="ajax"
+ onsubmit="if (typeof(this.elements['index[Key_name]'].disabled) != 'undefined') this.elements['index[Key_name]'].disabled = false;">
+
+ <?php echo PMA_URL_getHiddenInputs($form_params); ?>
+
+ <fieldset id="index_edit_fields">
+ <div class="index_info">
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_index_name">
+ <?php echo __('Index name:') . PMA_Util::showHint(
+ PMA_Message::notice(
+ __(
+ '"PRIMARY" <b>must</b> be the name of and <b>only of</b> a primary key!'
+ )
+ )
+ ); ?>
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Key_name]"
+ id="input_index_name"
+ size="25"
+ maxlength="64"
+ value="<?php echo htmlspecialchars($index->getName()); ?>"
+ onfocus="this.select()" />
+ </div>
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="select_index_choice">
+ <?php echo __('Index choice:') . PMA_Util::showMySQLDocu('ALTER_TABLE'); ?>
+ </label>
+ </strong>
+ </div>
+
+ <?php echo $index->generateIndexChoiceSelector(isset($_REQUEST['create_edit_table'])); ?>
+ </div>
+
+ <?php echo PMA_Util::getDivForSliderEffect(
+ 'indexoptions', __('Options')
+ ); ?>
+
+ <div>
+
+ <div class="label">
+ <strong>
+ <label for="input_key_block_size">
+ <?php echo __('Key block size:'); ?>
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Key_block_size]"
+ id="input_key_block_size"
+ size="30"
+ value="<?php echo htmlspecialchars($index->getKeyBlockSize()) ?>" />
+ </div>
+
+ <div>
+
+ <div class="label">
+ <strong>
+ <label for="select_index_type">
+ <?php echo __('Index type:') . PMA_Util::showMySQLDocu('ALTER_TABLE'); ?>
+ </label>
+ </strong>
+ </div>
+
+ <?php echo $index->generateIndexTypeSelector(); ?>
+ </div>
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_parser">
+ <?php echo __('Parser:'); ?>
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Parser]"
+ id="input_parse"
+ size="30"
+ value="<?php echo htmlspecialchars($index->getParser()) ?>" />
+ </div>
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_index_comment">
+ <?php echo __('Comment:'); ?>
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Index_comment]"
+ id="input_index_comment"
+ size="30"
+ maxlength="1024"
+ value="<?php echo htmlspecialchars($index->getComment()) ?>" />
+ </div>
+ </div>
+ <!-- end of indexoptions div -->
+
+ <div class="clearfloat"></div>
+
+ <table id="index_columns">
+ <thead>
+ <tr>
+ <th></th>
+ <th>
+ <?php echo __('Column') ?>
+ </th>
+ <th>
+ <?php echo __('Size') ?>
+ </th>
+ </tr>
+ </thead>
+ <?php $odd_row = true;
+ $spatial_types = array(
+ 'geometry',
+ 'point',
+ 'linestring',
+ 'polygon',
+ 'multipoint',
+ 'multilinestring',
+ 'multipolygon',
+ 'geomtrycollection'
+ ); ?>
+ <tbody>
+
+ <?php /* @var $column PMA_Index_Column */
+ foreach ($index->getColumns() as $column): ?>
+
+ <tr class="<?php echo $odd_row ? 'odd' : 'even'; ?>noclick">
+ <td>
+ <span class="drag_icon" title="<?php echo __('Drag to reorder') ?>"></span>
+ </td>
+ <td>
+ <select name="index[columns][names][]">
+ <option value="">
+ -- <?php echo __('Ignore'); ?> --
+ </option>
+
+ <?php
+ foreach ($fields as $field_name => $field_type):
+ if (($index->getChoice() != 'FULLTEXT'
+ || preg_match('/(char|text)/i', $field_type))
+ && ($index->getChoice() != 'SPATIAL'
+ || in_array($field_type, $spatial_types))): ?>
+
+ <option value="<?php echo htmlspecialchars($field_name) ?>"
+ <?php if ($field_name == $column->getName()) echo 'selected="selected"'; ?>>
+
+ <?php echo htmlspecialchars($field_name); ?> [<?php echo htmlspecialchars($field_type); ?>]
+ </option>
+ <?php endif;
+ endforeach; ?>
+ </select>
+ </td>
+ <td>
+ <input type="text"
+ size="5"
+ onfocus="this.select()"name="index[columns][sub_parts][]"
+ value="<?php if ($index->getChoice() != 'SPATIAL') echo $column->getSubPart(); ?>"/>
+ </td>
+ </tr>
+
+ <?php
+ $odd_row = !$odd_row;
+
+ endforeach;
+
+ for ($i = 0; $i < $add_fields; $i++): ?>
+
+ <tr class="<?php echo $odd_row ? 'odd' : 'even'; ?>noclick">
+ <td>
+ <span class="drag_icon" title="<?php echo __('Drag to reorder') ?>"></span>
+ </td>
+ <td>
+ <select name="index[columns][names][]">
+ <option value="">-- <?php echo __('Ignore') ?> --</option>
+
+ <?php
+ $j = 0;
+ foreach ($fields as $field_name => $field_type):
+ if (isset($_REQUEST['create_edit_table'])) {
+ $col_index = $field_type[1];
+ $field_type = $field_type[0];
+ } ?>
+
+ <option value="<?php echo htmlspecialchars((isset($col_index)) ? $col_index : $field_name); ?>"
+ <?php echo ($j++ == $i ? 'selected="selected"' : ''); ?>>
+ <?php echo htmlspecialchars($field_name) ?> [<?php echo htmlspecialchars($field_type); ?>]
+ </option>
+ <?php echo "\n";
+ endforeach; ?>
+ </select>
+ </td>
+ <td>
+ <input type="text"
+ size="5"
+ onfocus="this.select()"
+ name="index[columns][sub_parts][]"
+ value="" />
+ </td>
+ </tr>
+ <?php
+ $odd_row = !$odd_row;
+ endfor; ?>
+
+ </tbody>
+ </table>
+ <div class="add_more">
+
+ <div class="slider"></div>
+ <div class="add_fields hide">
+ <input type="submit"
+ id="add_fields"
+ value="<?php echo sprintf(__('Add %s column(s) to index'), 1); ?>" />
+ </div>
+ </div>
+ </fieldset>
+ <fieldset class="tblFooters">
+ <button type="submit" id="preview_index_frm"><?php echo __('Preview SQL'); ?></button>
+ <input type="submit" id="save_index_frm" value="<?php echo __('Go'); ?>" />
+ </fieldset>
+</form>
diff --git a/templates/table/relation/common_form.phtml b/templates/table/relation/common_form.phtml
new file mode 100644
index 0000000000..a5d9b5c719
--- /dev/null
+++ b/templates/table/relation/common_form.phtml
@@ -0,0 +1,111 @@
+<form method="post" action="tbl_relation.php">
+ <?php echo PMA_URL_getHiddenInputs($db, $table); ?>
+ <?php if ($cfgRelation['relwork']): ?>
+ <?php $save_row = array_values($columns);
+ $saved_row_cnt = count($save_row);?>
+ <fieldset>
+ <legend><?php echo __('Internal relations'); ?></legend>
+ <table id="internal_relations" class="relationalTable">
+ <tr>
+ <th><?php echo __('Column'); ?></th>
+ <th><?php echo __('Internal relation'); ?>
+ <?php if (PMA_Util::isForeignKeySupported($tbl_storage_engine)): ?>
+ <?php echo PMA_Util::showHint(__(
+ 'An internal relation is not necessary when a corresponding'
+ . ' FOREIGN KEY relation exists.')); ?>
+ <?php endif; ?>
+ </th>
+ <?php $odd_row = true; ?>
+ <?php for ($i = 0; $i < $saved_row_cnt; $i++): ?>
+ <?php echo PMA\Template::get('table/relation/internal_relational_row')->render(
+ array(
+ 'save_row' => $save_row,
+ 'i' => $i,
+ 'odd_row' => $odd_row,
+ 'existrel' => $existrel,
+ 'db' => $db
+ )
+ );
+ $odd_row = ! $odd_row; ?>
+ <?php endfor; ?>
+ </table>
+ </fieldset>
+ <?php endif; ?>
+ <!-- InnoDB -->
+ <?php if (PMA_Util::isForeignKeySupported($tbl_storage_engine)): ?>
+ <fieldset>
+ <legend><?php echo __('Foreign key constraints'); ?></legend>
+ <table id="foreign_keys" class="relationalTable">
+ <tr>
+ <th><?php echo __('Actions'); ?></th>
+ <th><?php echo __('Constraint properties'); ?></th>
+ <th><?php
+ echo __('Column') . PMA_Util::showHint(__(
+ 'Only columns with index will be displayed. You can define an'
+ . ' index below.'
+ )) ?>
+ </th>
+ <th colspan="3">
+ <?php echo __('Foreign key constraint'); ?> (<?php echo $tbl_storage_engine; ?>)
+ </th>
+ </tr>
+ <?php $odd_row = true; $i = 0; ?>
+ <?php if (! empty($existrel_foreign)): ?>
+ <?php foreach ($existrel_foreign as $key => $one_key): ?>
+ <?php echo PMA\Template::get('table/relation/foreign_key_row')->render(
+ array(
+ 'one_key' => $one_key,
+ 'odd_row' => $odd_row,
+ 'columns' => $columns,
+ 'i' => $i++,
+ 'options_array' => $options_array,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'db' => $db
+ )
+ );
+ $odd_row = ! $odd_row;?>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ <?php echo PMA\Template::get('table/relation/foreign_key_row')->render(
+ array(
+ 'one_key' => array(),
+ 'odd_row' => $odd_row,
+ 'columns' => $columns,
+ 'i' => $i++,
+ 'options_array' => $options_array,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'db' => $db
+ )
+ ); ?>
+ <tr>
+ <td colspan="5">
+ <a class="formelement clearfloat add_foreign_key" href="">
+ <?php echo __('+ Add constraint'); ?>
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ <?php endif; ?>
+ <?php if ($cfgRelation['displaywork']): ?>
+ <?php $save_row = array_values($columns);?>
+ <?php $disp = PMA_getDisplayField($db, $table); ?>
+ <fieldset>
+ <label><?php echo __('Choose column to display:'); ?></label>
+ <select name="display_field">
+ <option value="">---</option>
+ <?php foreach ($save_row as $row): ?>
+ <option value="<?php echo htmlspecialchars($row['Field']); ?>"
+ <?php if (isset($disp) && $row['Field'] == $disp): ?>
+ selected="selected"
+ <?php endif; ?>>
+ <?php echo htmlspecialchars($row['Field']); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </fieldset>
+ <?php endif; ?>
+ <fieldset class="tblFooters">
+ <input type="button" class="preview_sql" value="<?php echo __('Preview SQL'); ?>" />
+ <input type="submit" value="<?php echo __('Save'); ?>" />
+ </fieldset>
+</form>
diff --git a/templates/table/relation/dropdown_generate.phtml b/templates/table/relation/dropdown_generate.phtml
new file mode 100644
index 0000000000..cd6b767b4f
--- /dev/null
+++ b/templates/table/relation/dropdown_generate.phtml
@@ -0,0 +1,12 @@
+<?php echo (! empty($dropdown_question)
+ ? htmlspecialchars($dropdown_question) . '&nbsp;&nbsp;'
+ : ''); ?><select name="<?php echo htmlspecialchars($select_name); ?>">
+<?php foreach ($choices as $one_value => $one_label): ?>
+ <option value="<?php echo htmlspecialchars($one_value); ?>"
+ <?php if ($selected_value == $one_value): ?>
+ selected="selected"
+ <?php endif; ?>>
+ <?php echo htmlspecialchars($one_label); ?>
+ </option>
+<?php endforeach; ?>
+</select>
diff --git a/templates/table/relation/foreign_key_row.phtml b/templates/table/relation/foreign_key_row.phtml
new file mode 100644
index 0000000000..9d2a74efdd
--- /dev/null
+++ b/templates/table/relation/foreign_key_row.phtml
@@ -0,0 +1,214 @@
+<?php
+$js_msg = '';
+$this_params = null;
+if (isset($one_key['constraint'])) {
+ $drop_fk_query = 'ALTER TABLE ' . PMA_Util::backquote($GLOBALS['table'])
+ . ' DROP FOREIGN KEY '
+ . PMA_Util::backquote($one_key['constraint']) . ';';
+ $this_params = $GLOBALS['url_params'];
+ $this_params['goto'] = 'tbl_relation.php';
+ $this_params['back'] = 'tbl_relation.php';
+ $this_params['sql_query'] = $drop_fk_query;
+ $this_params['message_to_show'] = sprintf(
+ __('Foreign key constraint %s has been dropped'),
+ $one_key['constraint']
+ );
+ $js_msg = PMA_jsFormat(
+ 'ALTER TABLE ' . $GLOBALS['table']
+ . ' DROP FOREIGN KEY '
+ . $one_key['constraint'] . ';'
+ );
+}
+
+// For ON DELETE and ON UPDATE, the default action
+// is RESTRICT as per MySQL doc; however, a SHOW CREATE TABLE
+// won't display the clause if it's set as RESTRICT.
+$on_delete = isset($one_key['on_delete'])
+ ? $one_key['on_delete'] : 'RESTRICT';
+$on_update = isset($one_key['on_update'])
+ ? $one_key['on_update'] : 'RESTRICT';
+
+$column_array = array();
+$column_array[''] = '';
+foreach ($columns as $column) {
+ if (! empty($column['Key'])) {
+ $column_array[$column['Field']] = $column['Field'];
+ }
+}
+
+$foreign_table = false;
+// foreign database dropdown
+$foreign_db = (isset($one_key['ref_db_name'])) ? $one_key['ref_db_name'] : $db;
+
+$tables = array();
+if ($foreign_db) {
+ $foreign_table = isset($one_key['ref_table_name'])
+ ? $one_key['ref_table_name'] : '';
+
+ // In Drizzle, 'SHOW TABLE STATUS' will show status only for the tables
+ // which are currently in the table cache. Hence we have to use
+ // 'SHOW TABLES' and manualy retrieve table engine values.
+ if (PMA_DRIZZLE) {
+ $tables_rs = $GLOBALS['dbi']->query(
+ 'SHOW TABLES FROM ' . PMA_Util::backquote($foreign_db),
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+ while ($row = $GLOBALS['dbi']->fetchArray($tables_rs)) {
+ $engine = $GLOBALS['dbi']->getTable(
+ $foreign_db,
+ $row[0]
+ )->getStatusInfo('Engine');
+ if (isset($engine)
+ && /*overload*/mb_strtoupper($engine) == $tbl_storage_engine
+ ) {
+ $tables[] = $row[0];
+ }
+ }
+ } else {
+ $tables_rs = $GLOBALS['dbi']->query(
+ 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($foreign_db),
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+ while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
+ if (isset($row[1])
+ && /*overload*/mb_strtoupper($row[1]) == $tbl_storage_engine
+ ) {
+ $tables[] = $row[0];
+ }
+ }
+ }
+}
+?>
+<tr class="<?php echo ($odd_row ? 'odd' : 'even'); ?>">
+ <!-- Drop key anchor -->
+ <td>
+ <?php if (isset($one_key['constraint'])): ?>
+ <input type="hidden"
+ class="drop_foreign_key_msg"
+ value="<?php echo $js_msg; ?>" />
+ <a class="drop_foreign_key_anchor ajax"
+ href="sql.php<?php echo PMA_URL_getCommon($this_params); ?>" >
+ <?php echo PMA_Util::getIcon('b_drop.png', __('Drop')); ?>
+ </a>
+ <?php endif; ?>
+ </td>
+ <td>
+ <span class="formelement clearfloat">
+ <input type="text" name="constraint_name[<?php echo $i; ?>]"
+ value="<?php if (isset($one_key['constraint']))
+ echo htmlspecialchars($one_key['constraint']); ?>"
+ placeholder="<?php echo __('Constraint name'); ?>"
+ maxlength="64" />
+ </span>
+ <div class="floatleft">
+ <span class="formelement">
+ <?php echo PMA\Template::get('table/relation/dropdown_generate')->render(
+ array(
+ 'dropdown_question' => 'ON DELETE',
+ 'select_name' => 'on_delete[' . $i . ']',
+ 'choices' => $options_array,
+ 'selected_value' => $on_delete
+ )
+ ); ?>
+ </span>
+ <span class="formelement">
+ <?php echo PMA\Template::get('table/relation/dropdown_generate')->render(
+ array(
+ 'dropdown_question' => 'ON UPDATE',
+ 'select_name' => 'on_update[' . $i . ']',
+ 'choices' => $options_array,
+ 'selected_value' => $on_update
+ )
+ ); ?>
+ </span>
+ </div>
+ </td>
+ <td>
+ <?php if (isset($one_key['index_list'])): ?>
+ <?php foreach ($one_key['index_list'] as $key => $column): ?>
+ <span class="formelement clearfloat">
+ <?php echo PMA\Template::get('table/relation/dropdown_generate')->render(
+ array(
+ 'dropdown_question' => '',
+ 'select_name' => 'foreign_key_fields_name[' . $i . '][]',
+ 'choices' => $column_array,
+ 'selected_value' => $column
+ )
+ ); ?>
+ </span>
+ <?php endforeach; ?>
+ <?php else: ?>
+ <span class="formelement clearfloat">
+ <?php echo PMA\Template::get('table/relation/dropdown_generate')->render(
+ array(
+ 'dropdown_question' => '',
+ 'select_name' => 'foreign_key_fields_name[' . $i . '][]',
+ 'choices' => $column_array,
+ 'selected_value' => ''
+ )
+ ); ?>
+ </span>
+ <?php endif; ?>
+ <a class="formelement clearfloat add_foreign_key_field"
+ href=""
+ data-index="<?php echo $i; ?>">
+ <?php echo __('+ Add column'); ?>
+ </a>
+ </td>
+ <td>
+ <span class="formelement clearfloat">
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_foreign_db[' . $i . ']',
+ 'title' => __('Database'),
+ 'values' => $GLOBALS['pma']->databases,
+ 'foreign' => $foreign_db
+ )
+ ); ?>
+ </td>
+ <td>
+ <span class="formelement clearfloat">
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_foreign_table[' . $i . ']',
+ 'title' => __('Table'),
+ 'values' => $tables,
+ 'foreign' => $foreign_table
+ )
+ ); ?>
+ </span>
+ </td>
+ <td>
+ <?php if ($foreign_db && $foreign_table): ?>
+ <?php foreach ($one_key['ref_index_list'] as $foreign_column): ?>
+ <?php
+ $table_obj = new PMA_Table($foreign_table, $foreign_db);
+ $columns = $table_obj->getUniqueColumns(false, false);
+ ?>
+ <span class="formelement clearfloat">
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_foreign_column[' . $i . '][]',
+ 'title' => __('Column'),
+ 'values' => $columns,
+ 'foreign' => $foreign_column
+ )
+ ); ?>
+ </span>
+ <?php endforeach; ?>
+ <?php else: ?>
+ <span class="formelement clearfloat">
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_foreign_column[' . $i . '][]',
+ 'title' => __('Column'),
+ 'values' => array(),
+ 'foreign' => ''
+ )
+ ); ?>
+ </span>
+ <?php endif; ?>
+ </td>
+</tr> \ No newline at end of file
diff --git a/templates/table/relation/internal_relational_row.phtml b/templates/table/relation/internal_relational_row.phtml
new file mode 100644
index 0000000000..f947723dbd
--- /dev/null
+++ b/templates/table/relation/internal_relational_row.phtml
@@ -0,0 +1,77 @@
+<?php
+$myfield = $save_row[$i]['Field'];
+// Use an md5 as array index to avoid having special characters
+// in the name attribute (see bug #1746964 )
+$myfield_md5 = md5($myfield);
+$myfield_html = htmlspecialchars($myfield);
+
+$foreign_table = false;
+$foreign_column = false;
+
+// database dropdown
+if (isset($existrel[$myfield])) {
+ $foreign_db = $existrel[$myfield]['foreign_db'];
+} else {
+ $foreign_db = $db;
+}
+
+// table dropdown
+$tables = array();
+if ($foreign_db) {
+ if (isset($existrel[$myfield])) {
+ $foreign_table = $existrel[$myfield]['foreign_table'];
+ }
+ $tables_rs = $GLOBALS['dbi']->query(
+ 'SHOW TABLES FROM ' . PMA_Util::backquote($foreign_db),
+ null,
+ PMA_DatabaseInterface::QUERY_STORE
+ );
+ while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
+ $tables[] = $row[0];
+ }
+}
+
+// column dropdown
+$columns = array();
+if ($foreign_db && $foreign_table) {
+ if (isset($existrel[$myfield])) {
+ $foreign_column = $existrel[$myfield]['foreign_field'];
+ }
+ $table_obj = new PMA_Table($foreign_table, $foreign_db);
+ $columns = $table_obj->getUniqueColumns(false, false);
+}
+?>
+<tr class="<?php echo ($odd_row ? 'odd' : 'even'); ?>">
+ <td class="vmiddle">
+ <strong><?php echo $myfield_html; ?></strong>
+ <input type="hidden" name="fields_name[<?php echo $myfield_md5; ?>]"
+ value="<?php echo $myfield_html; ?>"/>
+ </td>
+
+ <td>
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_db[' . $myfield_md5 . ']',
+ 'title' => __('Database'),
+ 'values' => $GLOBALS['pma']->databases,
+ 'foreign' => $foreign_db
+ )
+ ); ?>
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_table[' . $myfield_md5 . ']',
+ 'title' => __('Table'),
+ 'values' => $tables,
+ 'foreign' => $foreign_table
+ )
+ ); ?>
+ <?php echo PMA\Template::get('table/relation/relational_dropdown')->render(
+ array(
+ 'name' => 'destination_column[' . $myfield_md5 . ']',
+ 'title' => __('Column'),
+ 'values' => $columns,
+ 'foreign' => $foreign_column
+ )
+ ); ?>
+ </td>
+</tr>
diff --git a/templates/table/relation/relational_dropdown.phtml b/templates/table/relation/relational_dropdown.phtml
new file mode 100644
index 0000000000..ad052f8ac3
--- /dev/null
+++ b/templates/table/relation/relational_dropdown.phtml
@@ -0,0 +1,18 @@
+<select name="<?php echo $name; ?>" title="<?php echo $title; ?>">
+ <option value=""></option>
+ <?php $seen_key = false; ?>
+ <?php foreach ($values as $value): ?>
+ <option value="<?php echo htmlspecialchars($value); ?>"
+ <?php if ($foreign && $value == $foreign): ?>
+ selected="selected"
+ <?php $seen_key = true; ?>
+ <?php endif; ?>>
+ <?php echo htmlspecialchars($value); ?>
+ </option>
+ <?php endforeach; ?>
+ <?php if (is_string($foreign) && ! $seen_key): ?>
+ <option value="<?php echo htmlspecialchars($foreign); ?>" selected="selected">
+ <?php echo htmlspecialchars($foreign); ?>
+ </option>
+ <?php endif; ?>
+</select> \ No newline at end of file
diff --git a/templates/table/search/column_comparison_operators.phtml b/templates/table/search/column_comparison_operators.phtml
new file mode 100644
index 0000000000..fceff0cd55
--- /dev/null
+++ b/templates/table/search/column_comparison_operators.phtml
@@ -0,0 +1,7 @@
+<select name="criteriaColumnOperators[<?php echo $search_index; ?>]"
+ onchange="changeValueFieldType(this, <?php echo $search_index; ?>)">
+ <?php echo $GLOBALS['PMA_Types']->getTypeOperatorsHtml(
+ preg_replace('@\(.*@s', '', $columnTypes[$column_index]),
+ $columnNullFlags[$column_index], $selected_operator
+ ); ?>
+</select> \ No newline at end of file
diff --git a/templates/table/search/fields_table.phtml b/templates/table/search/fields_table.phtml
new file mode 100644
index 0000000000..4d939419ca
--- /dev/null
+++ b/templates/table/search/fields_table.phtml
@@ -0,0 +1,24 @@
+<table class="data" <?php if ($searchType == 'zoom') echo 'id="tableFieldsId"'; ?>>
+ <?php echo PMA\Template::get('table/search/table_header')
+ ->render(array(
+ 'geomColumnFlag' => $geomColumnFlag
+ )); ?>
+ <tbody>
+ <?php if ($searchType == 'zoom'): ?>
+ <?php echo PMA\Template::get('table/search/rows_zoom')
+ ->render(array(
+ 'self' => $self,
+ 'columnNames' => $columnNames
+ )); ?>
+ <?php else: ?>
+ <?php echo PMA\Template::get('table/search/rows_normal')
+ ->render(array(
+ 'self' => $self,
+ 'geomColumnFlag' => $geomColumnFlag,
+ 'columnNames' => $columnNames,
+ 'columnTypes' => $columnTypes,
+ 'columnCollations' => $columnCollations
+ )); ?>
+ <?php endif; ?>
+ </tbody>
+</table>
diff --git a/templates/table/search/form_tag.phtml b/templates/table/search/form_tag.phtml
new file mode 100644
index 0000000000..aec6af50f2
--- /dev/null
+++ b/templates/table/search/form_tag.phtml
@@ -0,0 +1,22 @@
+<?php
+$scriptName = '';
+$formId = '';
+switch ($searchType) {
+ case 'normal' :
+ $scriptName = 'tbl_select.php';
+ $formId = 'tbl_search_form';
+ break;
+ case 'zoom' :
+ $scriptName = 'tbl_zoom_select.php';
+ $formId = 'zoom_search_form';
+ break;
+ case 'replace' :
+ $scriptName = 'tbl_find_replace.php';
+ $formId = 'find_replace_form';
+ break;
+}
+?>
+<form method="post" action="<?php echo $scriptName; ?>" name="insertForm" id="<?php echo $formId; ?>" class="ajax lock-page">
+ <?php echo PMA_URL_getHiddenInputs($db, $table); ?>
+ <input type="hidden" name="goto" value="<?php echo $goto; ?>" />
+ <input type="hidden" name="back" value="<?php echo $scriptName; ?>" />
diff --git a/templates/table/search/geom_func.phtml b/templates/table/search/geom_func.phtml
new file mode 100644
index 0000000000..216d0ee4e7
--- /dev/null
+++ b/templates/table/search/geom_func.phtml
@@ -0,0 +1,39 @@
+<!-- Displays 'Function' column if it is present -->
+<td>
+ <?php
+ $geom_types = PMA_Util::getGISDatatypes();
+ ?>
+
+ <?php
+ /**
+ * if a geometry column is present
+ */
+ if (in_array($columnTypes[$column_index], $geom_types)): ?>
+ <select class="geom_func"
+ name="geom_func[<?php echo $column_index; ?>]">
+
+ <?php
+ // get the relevant list of GIS functions
+ $funcs = PMA_Util::getGISFunctions(
+ $columnTypes[$column_index], true, true
+ );
+ ?>
+
+ <?php
+ /**
+ * For each function in the list of functions,
+ * add an option to select list
+ */
+ foreach ($funcs as $func_name => $func): ?>
+ <?php $name = htmlspecialchars(
+ isset($func['display']) ? $func['display'] : $func_name
+ ); ?>
+ <option value="<?php echo $name; ?>">
+ <?php echo $name; ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ <?php else: ?>
+ &nbsp;
+ <?php endif; ?>
+</td> \ No newline at end of file
diff --git a/templates/table/search/input_box.phtml b/templates/table/search/input_box.phtml
new file mode 100644
index 0000000000..e9e09b9914
--- /dev/null
+++ b/templates/table/search/input_box.phtml
@@ -0,0 +1,135 @@
+<?php
+// Get inputbox based on different column types
+// (Foreign key, geometrical, enum)
+if ($_foreigners
+ && PMA_searchColumnInForeigners($_foreigners, $column_name)): ?>
+ <?php if (is_array($foreignData['disp_row'])): ?>
+ <select name="criteriaValues[<?php echo $column_index; ?>]"
+ id="<?php echo $column_id . $column_index; ?>">
+ <?php echo PMA_foreignDropdown(
+ $foreignData['disp_row'], $foreignData['foreign_field'],
+ $foreignData['foreign_display'], '', $foreignMaxLimit
+ ); ?>
+ </select>
+ <?php elseif ($foreignData['foreign_link'] == true): ?>
+ <input type="text"
+ id="<?php echo $column_id . $column_index; ?>"
+ name="criteriaValues[<?php echo $column_index; ?>]"
+ id="field_<?php echo md5($column_name); ?>[<?php echo $column_index; ?>]"
+ class="textfield"
+ <?php if (isset($criteriaValues[$column_index])
+ && is_string($criteriaValues[$column_index])
+ ): ?>
+ value="<?php echo $criteriaValues[$column_index]; ?>"
+ <?php endif; ?> />
+ <a class="ajax browse_foreign"
+ href="browse_foreigners.php<?php
+ echo PMA_URL_getCommon(
+ array('db' => $db, 'table' => $table)
+ );
+ ?>&amp;field=<?php
+ echo urlencode($column_name);
+ ?>&amp;fieldkey=<?php
+ echo $column_index;
+ ?>&amp;fromsearch=1">
+ <?php echo str_replace("'", "\\'", $titles['Browse']); ?>
+ </a>
+ <?php endif; ?>
+
+<?php elseif (in_array($column_type, PMA_Util::getGISDatatypes())): ?>
+ <input type="text"
+ name="criteriaValues[<?php echo $column_index; ?>]"
+ size="40"
+ class="textfield"
+ id="field_<?php echo $column_index; ?>" />
+ <?php if ($in_fbs): ?>
+
+ <?php
+ $edit_url = 'gis_data_editor.php' . PMA_URL_getCommon();
+ $edit_str = PMA_Util::getIcon('b_edit.png', __('Edit/Insert'));
+ ?>
+
+ <span class="open_search_gis_editor">
+ <?php echo PMA_Util::linkOrButton(
+ $edit_url, $edit_str, array(), false, false, '_blank'
+ ); ?>
+ </span>
+ <?php endif; ?>
+
+<?php elseif (strncasecmp($column_type, 'enum', 4) == 0
+ || (strncasecmp($column_type, 'set', 3) == 0
+ && $in_zoom_search_edit)
+): ?>
+
+ <?php
+ $in_zoom_search_edit = false;
+ $column_type = htmlspecialchars($column_type);
+ $value = explode(', ', str_replace("'", '', /*overload*/mb_substr($column_type, 5, -1)));
+ $cnt_value = count($value);
+ /*
+ * Enum in edit mode --> dropdown
+ * Enum in search mode --> multiselect
+ * Set in edit mode --> multiselect
+ * Set in search mode --> input (skipped here, so the 'else'
+ * section would handle it)
+ */
+ ?>
+
+ <?php if ((strncasecmp($column_type, 'enum', 4) && ! $in_zoom_search_edit)
+ || (strncasecmp($column_type, 'set', 3) && $in_zoom_search_edit)
+ ): ?>
+ <select name="criteriaValues[<?php echo $column_index; ?>]"
+ id="<?php echo $column_id . $column_index; ?>">
+ <?php else: ?>
+ <select name="criteriaValues[<?php echo $column_index; ?>]"
+ id="<?php echo $column_id . $column_index; ?>"
+ multiple="multiple"
+ size="<?php echo min(3, $cnt_value); ?>">
+ <?php endif; ?>
+
+ <!-- Add select options-->
+ <?php for ($j = 0; $j < $cnt_value; $j++): ?>
+ <?php if (isset($criteriaValues[$column_index])
+ && is_array($criteriaValues[$column_index])
+ && in_array($value[$j], $criteriaValues[$column_index])
+ ): ?>
+ <option value="<?php echo $value[$j]; ?>"
+ selected>
+ <?php echo $value[$j]; ?>
+ </option>
+ <?php else: ?>
+ <option value="<?php echo $value[$j]; ?>">
+ <?php echo $value[$j]; ?>
+ </option>
+ <?php endif; ?>
+ <?php endfor; ?>
+ </select>
+
+<?php else: ?>
+<!-- other cases-->
+
+ <?php
+ $the_class = 'textfield';
+
+ if ($column_type == 'date') {
+ $the_class .= ' datefield';
+ } elseif ($column_type == 'datetime'
+ || substr($column_type, 0, 9) == 'timestamp'
+ ) {
+ $the_class .= ' datetimefield';
+ } elseif (substr($column_type, 0, 3) == 'bit') {
+ $the_class .= ' bit';
+ }
+ ?>
+ <input type="text"
+ name="criteriaValues[<?php echo $column_index; ?>]"
+ size="40"
+ class="<?php echo $the_class; ?>"
+ id="<?php echo $column_id . $column_index; ?>"
+ <?php if (isset($criteriaValues[$column_index])
+ && is_string($criteriaValues[$column_index])
+ ): ?>
+ value="<?php echo $criteriaValues[$column_index]; ?>"
+ <?php endif; ?>/>
+
+<?php endif; ?> \ No newline at end of file
diff --git a/templates/table/search/options.phtml b/templates/table/search/options.phtml
new file mode 100644
index 0000000000..caf48d08e8
--- /dev/null
+++ b/templates/table/search/options.phtml
@@ -0,0 +1,78 @@
+<?php echo PMA_Util::getDivForSliderEffect(
+ 'searchoptions', __('Options')
+); ?>
+
+<!-- Displays columns select list for selecting distinct columns in the search -->
+<fieldset id="fieldset_select_fields">
+ <legend>
+ <?php echo __('Select columns (at least one):'); ?>
+ </legend>
+ <select name="columnsToDisplay[]"
+ size="<?php echo min(count($columnNames), 10); ?>"
+ multiple="multiple">
+ <?php
+ /**
+ * Displays the list of the fields
+ */
+ foreach ($columnNames as $each_field): ?>
+ <option value="<?php echo htmlspecialchars($each_field); ?>"
+ selected="selected">
+ <?php echo htmlspecialchars($each_field); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ <input type="checkbox"
+ name="distinct"
+ value="DISTINCT"
+ id="oDistinct" />
+ <label for="oDistinct">
+ DISTINCT
+ </label>
+</fieldset>
+
+<!-- Displays input box for custom 'Where' clause to be used in the search -->
+<fieldset id="fieldset_search_conditions">
+ <legend>
+ <em><?php echo __('Or'); ?></em>
+ <?php echo __('Add search conditions (body of the "where" clause):'); ?>
+ </legend>
+ <?php echo PMA_Util::showMySQLDocu('Functions'); ?>
+ <input type="text" name="customWhereClause" class="textfield" size="64" />
+</fieldset>
+
+<!-- Displays option of changing default number of rows displayed per page -->
+<fieldset id="fieldset_limit_rows">
+ <legend><?php echo __('Number of rows per page'); ?></legend>
+ <input type="number"
+ name="session_max_rows"
+ required="required"
+ min="1"
+ value="<?php echo $GLOBALS['cfg']['MaxRows']; ?>"
+ class="textfield" />
+</fieldset>
+
+<!-- Displays option for ordering search results by a column value (Asc or Desc) -->
+<fieldset id="fieldset_display_order">
+ <legend><?php echo __('Display order:'); ?></legend>
+ <select name="orderByColumn"><option value="--nil--"></option>
+ <?php foreach ($columnNames as $each_field): ?>
+ <option value="<?php echo htmlspecialchars($each_field); ?>">
+ <?php echo htmlspecialchars($each_field); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+
+ <?php echo PMA_Util::getRadioFields(
+ 'order',
+ array(
+ 'ASC' => __('Ascending'),
+ 'DESC' => __('Descending')
+ ),
+ 'ASC',
+ false,
+ true,
+ "formelement"
+ ); ?>
+
+</fieldset>
+<br style="clear: both;" /> \ No newline at end of file
diff --git a/templates/table/search/options_zoom.phtml b/templates/table/search/options_zoom.phtml
new file mode 100644
index 0000000000..bee78bdbf8
--- /dev/null
+++ b/templates/table/search/options_zoom.phtml
@@ -0,0 +1,48 @@
+<table class="data">
+ <!-- Select options for data label -->
+ <tr>
+ <td>
+ <label for="dataLabel">
+ <?php echo __("Use this column to label each point"); ?>
+ </label>
+ </td>
+ <td>
+ <select name="dataLabel" id="dataLabel" >
+ <option value = "">
+ <?php echo __('None'); ?>
+ </option>
+ <?php for ($j = 0, $nb = count($columnNames); $j < $nb; $j++): ?>
+ <?php if (isset($dataLabel)
+ && $dataLabel == htmlspecialchars($columnNames[$j])
+ ): ?>
+ <option value="<?php echo htmlspecialchars($columnNames[$j]); ?>"
+ selected="selected">
+ <?php echo htmlspecialchars($columnNames[$j]); ?>
+ </option>
+ <?php else: ?>
+ <option value="<?php echo htmlspecialchars($columnNames[$j]); ?>" >
+ <?php echo htmlspecialchars($columnNames[$j]); ?>
+ </option>
+ <?php endif; ?>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ <!-- Inputbox for changing default maximum rows to plot -->
+ <tr>
+ <td>
+ <label for="maxRowPlotLimit">
+ <?php echo __("Maximum rows to plot"); ?>
+ </label>
+ </td>
+ <td>
+ <input type="number"
+ name="maxPlotLimit"
+ id="maxRowPlotLimit"
+ required="required"
+ value="<?php echo ((! empty($_POST['maxPlotLimit']))
+ ? htmlspecialchars($_POST['maxPlotLimit'])
+ : $GLOBALS['cfg']['maxRowPlotLimit']); ?>" />
+ </td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/templates/table/search/replace_preview.phtml b/templates/table/search/replace_preview.phtml
new file mode 100644
index 0000000000..551340e4c8
--- /dev/null
+++ b/templates/table/search/replace_preview.phtml
@@ -0,0 +1,42 @@
+<form method="post"
+ action="tbl_find_replace.php"
+ name="previewForm"
+ id="previewForm">
+ <?php echo PMA_URL_getHiddenInputs($db, $table); ?>
+ <input type="hidden" name="replace" value="true" />
+ <input type="hidden" name="columnIndex" value="<?php echo $columnIndex; ?>" />
+ <input type="hidden" name="findString" value="<?php echo htmlspecialchars($find); ?>" />
+ <input type="hidden" name="replaceWith" value="<?php echo htmlspecialchars($replaceWith); ?>" />
+ <input type="hidden" name="useRegex" value="<?php echo $useRegex; ?>" />
+
+ <fieldset id="fieldset_find_replace_preview">
+ <legend><?php echo __('Find and replace - preview'); ?></legend>
+ <table id="previewTable">
+ <thead>
+ <tr>
+ <th><?php echo __('Count'); ?></th>
+ <th><?php echo __('Original string'); ?></th>
+ <th><?php echo __('Replaced string'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php $odd = true; ?>
+ <?php if (is_array($result)): ?>
+ <?php foreach ($result as $row): ?>
+ <?php $val = $row[0]; $replaced = $row[1]; $count = $row[2]; ?>
+ <tr class="<?php echo ($odd ? 'odd' : 'even'); ?>">
+ <td class="right"><?php echo htmlspecialchars($count); ?></td>
+ <td><?php echo htmlspecialchars($val); ?></td>
+ <td><?php echo htmlspecialchars($replaced); ?></td>
+ </tr>
+ <?php $odd = ! $odd; ?>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ </tbody>
+ </table>
+ </fieldset>
+
+ <fieldset class="tblFooters">
+ <input type="submit" name="replace" value="<?php echo __('Replace'); ?>" />
+ </fieldset>
+</form> \ No newline at end of file
diff --git a/templates/table/search/rows_normal.phtml b/templates/table/search/rows_normal.phtml
new file mode 100644
index 0000000000..d2fe1ab185
--- /dev/null
+++ b/templates/table/search/rows_normal.phtml
@@ -0,0 +1,52 @@
+<?php
+$odd_row = true;
+// for every column present in table
+for (
+ $column_index = 0, $nb = count($columnNames);
+ $column_index < $nb;
+ $column_index++
+): ?>
+ <tr class="noclick <?php echo $odd_row ? 'odd' : 'even'; ?>">
+ <?php $odd_row = !$odd_row; ?>
+ <!-- If 'Function' column is present -->
+ <?php if ($geomColumnFlag): ?>
+ <?php echo PMA\Template::get('table/search/geom_func')
+ ->render(array(
+ 'column_index' => $column_index,
+ 'columnTypes' => $columnTypes,
+ )); ?>
+ <?php endif; ?>
+ <!-- Displays column's name, type, collation and value -->
+ <th>
+ <?php echo htmlspecialchars($columnNames[$column_index]); ?>
+ </th>
+ <?php $properties = $self->getColumnProperties($column_index, $column_index); ?>
+ <td dir="ltr">
+ <?php echo htmlspecialchars($properties['type']); ?>
+ </td>
+ <td>
+ <?php echo $properties['collation']; ?>
+ </td>
+ <td>
+ <?php echo $properties['func']; ?>
+ </td>
+ <!-- here, the data-type attribute is needed for a date/time picker-->
+ <td data-type="<?php echo htmlspecialchars($properties['type']); ?>">
+ <?php echo $properties['value']; ?>
+ </td>
+ </tr>
+ <!-- Displays hidden fields -->
+ <tr>
+ <td>
+ <input type="hidden"
+ name="criteriaColumnNames[<?php echo $column_index; ?>]"
+ value="<?php echo htmlspecialchars($columnNames[$column_index]); ?>" />
+ <input type="hidden"
+ name="criteriaColumnTypes[<?php echo $column_index; ?>]"
+ value="<?php echo htmlspecialchars($columnTypes[$column_index]); ?>" />
+ <input type="hidden"
+ name="criteriaColumnCollations[<?php echo $column_index; ?>]"
+ value="<?php echo $columnCollations[$column_index]; ?>" />
+ </td>
+ </tr>
+<?php endfor; ?> \ No newline at end of file
diff --git a/templates/table/search/rows_zoom.phtml b/templates/table/search/rows_zoom.phtml
new file mode 100644
index 0000000000..06550cf4e8
--- /dev/null
+++ b/templates/table/search/rows_zoom.phtml
@@ -0,0 +1,88 @@
+<?php
+$odd_row = true;
+$type = $collation = $func = $value = array();
+/**
+ * Get already set search criteria (if any)
+ */
+
+// Displays column rows for search criteria input
+for ($i = 0; $i < 4; $i++): ?>
+ <?php
+ // After X-Axis and Y-Axis column rows, display additional criteria
+ // option
+ if ($i == 2): ?>
+ <tr>
+ <td>
+ <?php echo __("Additional search criteria"); ?>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <tr class="noclick <?php echo ($odd_row ? 'odd' : 'even'); ?>">
+ <?php $odd_row = ! $odd_row; ?>
+ <!-- Select options for column names -->
+ <th>
+ <select name="criteriaColumnNames[]" id="tableid_<?php echo $i; ?>" >
+ <option value="pma_null">
+ <?php echo __('None'); ?>
+ </option>
+ <?php for ($j = 0, $nb = count($columnNames); $j < $nb; $j++): ?>
+ <?php if (isset($_POST['criteriaColumnNames'][$i])
+ && $_POST['criteriaColumnNames'][$i] == htmlspecialchars($columnNames[$j])
+ ): ?>
+ <option value="<?php echo htmlspecialchars($columnNames[$j]); ?>" selected="selected">
+ <?php echo htmlspecialchars($columnNames[$j]); ?>
+ </option>
+ <?php else: ?>
+ <option value="<?php echo htmlspecialchars($columnNames[$j]); ?>">
+ <?php echo htmlspecialchars($columnNames[$j]); ?>
+ </option>
+ <?php endif; ?>
+ <?php endfor; ?>
+ </select>
+ </th>
+ <?php
+ if (isset($_POST['criteriaColumnNames'])
+ && $_POST['criteriaColumnNames'][$i] != 'pma_null'
+ ) {
+ $key = array_search(
+ $_POST['criteriaColumnNames'][$i],
+ $columnNames
+ );
+ $properties = $self->getColumnProperties($i, $key);
+ $type[$i] = $properties['type'];
+ $collation[$i] = $properties['collation'];
+ $func[$i] = $properties['func'];
+ $value[$i] = $properties['value'];
+ } ?>
+ <!-- Column type -->
+ <td dir="ltr">
+ <?php echo (isset($type[$i]) ? $type[$i] : ''); ?>
+ </td>
+ <!-- Column Collation -->
+ <td>
+ <?php echo (isset($collation[$i]) ? $collation[$i] : ''); ?>
+ </td>
+ <!-- Select options for column operators -->
+ <td>
+ <?php echo (isset($func[$i]) ? $func[$i] : ''); ?>
+ </td>
+ <!-- Inputbox for search criteria value -->
+ <td>
+ <?php echo (isset($value[$i]) ? $value[$i] : ''); ?>
+ </td>
+ </tr>
+ <!-- Displays hidden fields -->
+ <tr>
+ <td>
+ <input type="hidden"
+ name="criteriaColumnTypes[<?php echo $i; ?>]"
+ id="types_<?php echo $i; ?>"
+ <?php if (isset($_POST['criteriaColumnTypes'][$i])): ?>
+ value="<?php echo $_POST['criteriaColumnTypes'][$i]; ?>"
+ <?php endif; ?> />
+ <input type="hidden"
+ name="criteriaColumnCollations[<?php echo $i; ?>]"
+ id="collations_<?php echo $i; ?>" />
+ </td>
+ </tr>
+<?php endfor; ?> \ No newline at end of file
diff --git a/templates/table/search/search_and_replace.phtml b/templates/table/search/search_and_replace.phtml
new file mode 100644
index 0000000000..6d5f8b5a50
--- /dev/null
+++ b/templates/table/search/search_and_replace.phtml
@@ -0,0 +1,26 @@
+<?php echo __('Find:'); ?>
+<input type="text" value="" name="find" required />
+<?php echo __('Replace with:'); ?>
+<input type="text" value="" name="replaceWith" required />
+
+<?php echo __('Column:'); ?>
+<select name="columnIndex">
+ <?php for ($i = 0, $nb = count($columnNames); $i < $nb; $i++): ?>
+ <?php $type = preg_replace('@\(.*@s', '', $columnTypes[$i]); ?>
+ <?php if ($GLOBALS['PMA_Types']->getTypeClass($type) == 'CHAR'): ?>
+ <?php $column = $columnNames[$i]; ?>
+ <option value="<?php echo $i; ?>">
+ <?php echo htmlspecialchars($column); ?>
+ </option>
+ <?php endif; ?>
+ <?php endfor; ?>
+</select>
+
+<br>
+<?php echo PMA_Util::getCheckbox(
+ 'useRegex',
+ __('Use regular expression'),
+ false,
+ false,
+ 'useRegex'
+); ?>
diff --git a/templates/table/search/selection_form.phtml b/templates/table/search/selection_form.phtml
new file mode 100644
index 0000000000..676d26ad44
--- /dev/null
+++ b/templates/table/search/selection_form.phtml
@@ -0,0 +1,78 @@
+<?php echo PMA\Template::get('table/search/form_tag')
+ ->render(array(
+ 'searchType' => $searchType,
+ 'db' => $db,
+ 'table' => $table,
+ 'goto' => $goto
+ )) ?>
+<?php if ($searchType == 'zoom'): ?>
+ <fieldset id="fieldset_zoom_search">
+ <fieldset id="inputSection">
+ <legend>
+ <?php echo __('Do a "query by example" (wildcard: "%") for two different columns'); ?>
+ </legend>
+ <?php echo PMA\Template::get('table/search/fields_table')
+ ->render(array(
+ 'self' => $self,
+ 'searchType' => $searchType,
+ 'geomColumnFlag' => $geomColumnFlag,
+ 'columnNames' => $columnNames,
+ 'columnTypes' => $columnTypes,
+ 'columnCollations' => $columnCollations
+ ));
+ echo PMA\Template::get('table/search/options_zoom')
+ ->render(array(
+ 'dataLabel' => $dataLabel,
+ 'columnNames' => $columnNames
+ )); ?>
+ </fieldset>
+ </fieldset>
+<?php elseif ($searchType == 'normal'): ?>
+ <fieldset id="fieldset_table_search">
+ <fieldset id="fieldset_table_qbe">
+ <legend>
+ <?php echo __('Do a "query by example" (wildcard: "%")'); ?>
+ </legend>
+ <?php echo PMA\Template::get('table/search/fields_table')
+ ->render(array(
+ 'self' => $self,
+ 'searchType' => $searchType,
+ 'geomColumnFlag' => $geomColumnFlag,
+ 'columnNames' => $columnNames,
+ 'columnTypes' => $columnTypes,
+ 'columnCollations' => $columnCollations
+ )); ?>
+ <div id="gis_editor">
+ </div>
+ <div id="popup_background">
+ </div>
+ </fieldset>
+ <?php echo PMA\Template::get('table/search/options')
+ ->render(array(
+ 'columnNames' => $columnNames
+ )); ?>
+ </fieldset>
+<?php elseif ($searchType == 'replace'): ?>
+ <fieldset id="fieldset_find_replace">
+ <fieldset id="fieldset_find">
+ <legend>
+ <?php echo __('Find and replace'); ?>
+ </legend>
+ <?php echo PMA\Template::get('table/search/search_and_replace')
+ ->render(array(
+ 'columnNames' => $columnNames,
+ 'columnTypes' => $columnTypes
+ )); ?>
+ </fieldset>
+ </fieldset>
+<?php endif; ?>
+
+<!--Displays selection form's footer elements-->
+<fieldset class="tblFooters">
+ <input type="submit"
+ name="<?php echo ($searchType == 'zoom' ? 'zoom_submit' : 'submit'); ?>"
+ <?php if ($searchType == 'zoom') echo ' id="inputFormSubmitId"'; ?>
+ value="<?php echo __('Go'); ?>" />
+</fieldset>
+</form>
+<div id="sqlqueryresultsouter"></div> \ No newline at end of file
diff --git a/templates/table/search/table_header.phtml b/templates/table/search/table_header.phtml
new file mode 100644
index 0000000000..58cdf1775a
--- /dev/null
+++ b/templates/table/search/table_header.phtml
@@ -0,0 +1,12 @@
+<thead>
+ <tr>
+ <?php if ($geomColumnFlag): ?>
+ <th><?php echo __('Function'); ?></th>
+ <?php endif; ?>
+ <th><?php echo __('Column'); ?></th>
+ <th><?php echo __('Type'); ?></th>
+ <th><?php echo __('Collation'); ?></th>
+ <th><?php echo __('Operator'); ?></th>
+ <th><?php echo __('Value'); ?></th>
+ </tr>
+</thead> \ No newline at end of file
diff --git a/templates/table/search/zoom_result_form.phtml b/templates/table/search/zoom_result_form.phtml
new file mode 100644
index 0000000000..f4ca07dd83
--- /dev/null
+++ b/templates/table/search/zoom_result_form.phtml
@@ -0,0 +1,100 @@
+<form method="post" action="tbl_zoom_select.php" name="displayResultForm" id="zoom_display_form" class="ajax">
+ <?php echo PMA_URL_getHiddenInputs($_db, $_table); ?>
+ <input type="hidden" name="goto" value="<?php echo $goto; ?>" />
+ <input type="hidden" name="back" value="tbl_zoom_select.php" />
+
+ <fieldset id="displaySection">
+ <legend><?php echo __('Browse/Edit the points');?></legend>
+
+ <!-- JSON encode the data(query result) -->
+ <center>
+ <?php if (isset($_POST['zoom_submit']) && ! empty($data)): ?>
+ <div id="resizer">
+ <center>
+ <a href="#" onclick="displayHelp();">
+ <?php echo __('How to use'); ?>
+ </a>
+ </center>
+ <div id="querydata" style="display:none">
+ <?php echo json_encode($data); ?>
+ </div>
+ <div id="querychart"></div>
+ <button class="button-reset">
+ <?php echo __('Reset zoom'); ?></button>
+ </div>
+ <?php endif; ?>
+ </center>
+
+ <!-- Displays rows in point edit form -->
+ <div id="dataDisplay" style="display:none">
+ <table>
+ <thead>
+ <tr>
+ <th><?php echo __('Column'); ?> </th>
+ <th><?php echo __('Null'); ?> </th>
+ <th><?php echo __('Value'); ?> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php $odd_row = true; ?>
+ <?php for (
+ $column_index = 0, $nb = count($_columnNames);
+ $column_index < $nb;
+ $column_index++
+ ): ?>
+ <?php
+ $foreignData = PMA_getForeignData(
+ $_foreigners,
+ $_columnNames[$column_index],
+ false,
+ '',
+ ''
+ ); ?>
+ <?php endfor; ?>
+ <?php for (
+ $column_index = 0, $nb = count($_columnNames);
+ $column_index < $nb;
+ $column_index++
+ ): ?>
+ <?php
+ $fieldpopup = $_columnNames[$column_index];
+ $foreignData = PMA_getForeignData($_foreigners, $fieldpopup, false, '', '' );?>
+ <tr class="noclick <?php echo ($odd_row ? 'odd' : 'even'); ?>">
+ <?php $odd_row = ! $odd_row; ?>
+ <!-- Display column Names -->
+ <th><?php echo htmlspecialchars($_columnNames[$column_index]); ?></th>
+ <!-- Null checkbox if column can be null -->
+ <th>
+ <?php if ($_columnNullFlags[$column_index] == 'YES'): ?>
+ <input type="checkbox" class="checkbox_null"
+ name="criteriaColumnNullFlags[<?php echo $column_index; ?>]"
+ id="edit_fields_null_id_'<?php echo $column_index;?>" />
+ <?php endif; ?>
+ </th>
+<!-- Column's Input box-->
+ <th>
+ <?php
+ echo PMA\Template::get('table/search/input_box')->render(array(
+ 'str' => '',
+ 'column_type' => $_columnTypes[$column_index],
+ 'column_id' => ($_columnTypes[$column_index]) ? 'edit_fieldID_' : 'fieldID_',
+ 'in_zoom_search_edit' => true,
+ '_foreigners' => $_foreigners,
+ 'column_name' => $fieldpopup,
+ 'foreignData' => $foreignData,
+ 'table' => $_table,
+ 'column_index' => $column_index,
+ 'foreignMaxLimit' => $GLOBALS['cfg']['ForeignKeyMaxLimit'],
+ 'criteriaValues' => '',
+ 'db' => $_db,
+ 'titles' => $titles,
+ 'in_fbs' => false
+ ));?>
+ </th>
+ </tr>
+ <?php endfor; ?>
+ </tbody>
+ </table>
+ </div>
+ <input type="hidden" id="queryID" name="sql_query" />
+</form> \ No newline at end of file
diff --git a/templates/table/secondary_tabs.phtml b/templates/table/secondary_tabs.phtml
new file mode 100644
index 0000000000..9ace3a0eb9
--- /dev/null
+++ b/templates/table/secondary_tabs.phtml
@@ -0,0 +1,19 @@
+<?php $cfgRelation = PMA_getRelationsParam(); ?>
+<?php if ($cfgRelation['relwork'] ||
+ PMA_Util::isForeignKeySupported($engine)): ?>
+ <ul id="topmenu2">
+ <?php echo PMA_Util::getHtmlTab(array(
+ 'icon' => 'b_props',
+ 'link' => 'tbl_structure.php',
+ 'text' => __('Table structure'),
+ 'id' => 'table_strucuture_id'
+ ), $url_params); ?>
+ <?php echo PMA_Util::getHtmlTab(array(
+ 'icon' => 'b_relations',
+ 'link' => 'tbl_relation.php',
+ 'text' => __('Relation view'),
+ 'id' => 'table_relation_id'
+ ), $url_params); ?>
+ </ul>
+ <div class="clearfloat"></div>
+<?php endif; ?>
diff --git a/templates/table/structure/action_row_in_structure_table.phtml b/templates/table/structure/action_row_in_structure_table.phtml
new file mode 100644
index 0000000000..61c0ff8876
--- /dev/null
+++ b/templates/table/structure/action_row_in_structure_table.phtml
@@ -0,0 +1,28 @@
+<li class="<?php echo $class; ?>">
+<?php if ($type == 'text'
+ || $type == 'blob'
+ || 'ARCHIVE' == $tbl_storage_engine
+ || $hasField
+ ): ?>
+ <?php echo $titles['No' . $action]; ?>
+<?php else: ?>
+ <a rel="samepage" class="ajax add_key print_ignore
+ <?php if ($hasLinkClass): ?>
+ add_primary_key_anchor"
+ <?php elseif ($action=='Index'): ?>
+ add_index_anchor"
+ <?php elseif ($action=='Unique'): ?>
+ add_unique_anchor"
+ <?php elseif ($action=='Spatial'): ?>
+ add_spatial_anchor"
+ <?php else: ?>
+ "
+ <?php endif; ?> href="tbl_structure.php<?php echo $url_query; ?>&amp;add_key=1&amp;sql_query=<?php echo urlencode(
+ 'ALTER TABLE ' . PMA_Util::backquote($GLOBALS['table'])
+ . ($isPrimary ? ($primary ? ' DROP PRIMARY KEY,' : '') : '')
+ . ' ' . $syntax . '('
+ . PMA_Util::backquote($row['Field']) . ');'); ?>&amp;message_to_show=<?php echo urlencode(sprintf($message, htmlspecialchars($row['Field']))); ?>" >
+ <?php echo $titles[$action]; ?>
+ </a>
+<?php endif; ?>
+</li>
diff --git a/templates/table/structure/actions_in_table_structure.phtml b/templates/table/structure/actions_in_table_structure.phtml
new file mode 100644
index 0000000000..1d343b6f3e
--- /dev/null
+++ b/templates/table/structure/actions_in_table_structure.phtml
@@ -0,0 +1,143 @@
+<td class="print_ignore"><ul class="table-structure-actions resizable-menu">
+ <!-- Add primary -->
+ <?php
+ echo PMA\Template::get('table/structure/action_row_in_structure_table')->render(
+ array(
+ 'type' => $type,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'class' => 'primary nowrap',
+ 'hasField' => ($primary && $primary->hasColumn($field_name)),
+ 'hasLinkClass' => true,
+ 'url_query' => $url_query,
+ 'primary' => $primary,
+ 'syntax' => 'ADD PRIMARY KEY',
+ 'message' => __('A primary key has been added on %s.'),
+ 'action' => 'Primary',
+ 'titles' => $titles,
+ 'row' => $row,
+ 'isPrimary' => true
+ )
+ );
+ ?>
+ <!-- Add unique -->
+ <?php
+ echo PMA\Template::get('table/structure/action_row_in_structure_table')->render(
+ array(
+ 'type' => $type,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'class' => 'add_unique unique nowrap',
+ 'hasField' => in_array($field_name, $columns_with_unique_index),
+ 'hasLinkClass' => false,
+ 'url_query' => $url_query,
+ 'primary' => $primary,
+ 'syntax' => 'ADD UNIQUE',
+ 'message' => __('An index has been added on %s.'),
+ 'action' => 'Unique',
+ 'titles' => $titles,
+ 'row' => $row,
+ 'isPrimary' => false
+ )
+ );
+ ?>
+ <!-- Add index -->
+ <?php
+ echo PMA\Template::get('table/structure/action_row_in_structure_table')->render(
+ array(
+ 'type' => $type,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'class' => 'add_index nowrap',
+ 'hasField' => false,
+ 'hasLinkClass' => false,
+ 'url_query' => $url_query,
+ 'primary' => $primary,
+ 'syntax' => 'ADD INDEX',
+ 'message' => __('An index has been added on %s.'),
+ 'action' => 'Index',
+ 'titles' => $titles,
+ 'row' => $row,
+ 'isPrimary' => false
+ )
+ );
+ ?>
+ <?php if (!PMA_DRIZZLE): ?>
+ <!-- Add spatial -->
+ <?php
+ $spatial_types = array(
+ 'geometry', 'point', 'linestring', 'polygon', 'multipoint',
+ 'multilinestring', 'multipolygon', 'geomtrycollection'
+ );
+ echo PMA\Template::get('table/structure/action_row_in_structure_table')->render(
+ array(
+ 'type' => $type,
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'class' => 'spatial nowrap',
+ 'hasField' => ! (in_array($type, $spatial_types) && ('MYISAM' == $tbl_storage_engine || PMA_MYSQL_INT_VERSION >= 50705)),
+ 'hasLinkClass' => false,
+ 'url_query' => $url_query,
+ 'primary' => $primary,
+ 'syntax' => 'ADD SPATIAL',
+ 'message' => __('An index has been added on %s.'),
+ 'action' => 'Spatial',
+ 'titles' => $titles,
+ 'row' => $row,
+ 'isPrimary' => false
+ )
+ );
+ ?>
+ <!-- FULLTEXT is possible on TEXT, CHAR and VARCHAR -->
+ <li class="fulltext nowrap">
+ <?php if (! empty($tbl_storage_engine)
+ && ($tbl_storage_engine == 'MYISAM'
+ || $tbl_storage_engine == 'ARIA'
+ || $tbl_storage_engine == 'MARIA'
+ || ($tbl_storage_engine == 'INNODB' && PMA_MYSQL_INT_VERSION >= 50604))
+ && (/*overload*/mb_strpos($type, 'text') !== false
+ || /*overload*/mb_strpos($type, 'char') !== false)
+ ): ?>
+ <a rel="samepage" class="ajax add_key add_fulltext_anchor" href="tbl_structure.php<?php echo $url_query; ?>&amp;add_key=1&amp;sql_query=<?php echo urlencode(
+ 'ALTER TABLE ' . PMA_Util::backquote($GLOBALS['table'])
+ . ' ADD FULLTEXT(' . PMA_Util::backquote($row['Field'])
+ . ');'); ?>&amp;message_to_show=<?php echo urlencode(sprintf(
+ __('An index has been added on %s.'),
+ htmlspecialchars($row['Field']))); ?>">
+ <?php echo $titles['IdxFulltext']; ?>
+ </a>
+ <?php else: ?>
+ <?php echo $titles['NoIdxFulltext']; ?>
+ <?php endif; ?>
+ </li>
+ <?php endif; ?>
+ <!-- Distinct value action -->
+ <li class="browse nowrap">
+ <a href="sql.php<?php echo $url_query; ?>&amp;sql_query=<?php echo urlencode(
+ 'SELECT COUNT(*) AS ' . PMA_Util::backquote(__('Rows'))
+ . ', ' . PMA_Util::backquote($row['Field'])
+ . ' FROM ' . PMA_Util::backquote($GLOBALS['table'])
+ . ' GROUP BY ' . PMA_Util::backquote($row['Field'])
+ . ' ORDER BY ' . PMA_Util::backquote($row['Field'])
+ ); ?>&amp;is_browse_distinct=1">
+ <?php echo $titles['DistinctValues']; ?>
+ </a>
+ </li>
+ <?php if ($GLOBALS['cfgRelation']['centralcolumnswork']): ?>
+ <li class="browse nowrap">
+ <?php if ($isInCentralColumns): ?>
+ <a href="#" onclick=$("input:checkbox").prop("checked",false);
+ $("#checkbox_row_' . $rownum . '").prop("checked",true);
+ $("button[value=remove_from_central_columns]").click();>
+ <?php echo PMA_Util::getIcon(
+ 'centralColumns_delete.png',
+ __('Remove from central columns')
+ ); ?></a>
+ <?php else: ?>
+ <a href="#" onclick=$("input:checkbox").prop("checked",false);
+ $("#checkbox_row_' . $rownum . '").prop("checked",true);
+ $("button[value=add_to_central_columns]").click();>
+ <?php echo PMA_Util::getIcon(
+ 'centralColumns_add.png',
+ __('Add to central columns')
+ ); ?></a>
+ <?php endif; ?>
+ </li>
+ <?php endif; ?>
+</ul></td>
diff --git a/templates/table/structure/add_column.phtml b/templates/table/structure/add_column.phtml
new file mode 100644
index 0000000000..3853cfcb4c
--- /dev/null
+++ b/templates/table/structure/add_column.phtml
@@ -0,0 +1,26 @@
+<form method="post" action="tbl_addfield.php" id="addColumns" name="addColumns" onsubmit="return checkFormElementInRange(this, 'num_fields', '<?php echo str_replace('\'', '\\\'', __('You have to add at least one column.')); ?>', 1)">
+ <?php echo PMA_URL_getHiddenInputs($GLOBALS['db'], $GLOBALS['table']); ?>
+ <?php if (PMA_Util::showIcons('ActionLinksMode')): ?>
+ <?php echo PMA_Util::getImage('b_insrow.png', __('Add column')); ?>&nbsp;
+ <?php endif; ?>
+ <?php $num_fields = '<input type="number" name="num_fields" value="1" onfocus="this.select()" min="1" required />'; ?>
+ <?php echo sprintf(__('Add %s column(s)'), $num_fields); ?>
+ <input type="hidden" name="field_where" value="after"/>&nbsp;
+ <!-- I tried displaying the drop-down inside the label but with Firefox the drop-down was blinking -->
+ <select name="after_field" onchange="checkFirst()">
+ <option value="first" data-pos = "first">
+ <?php echo __('at beginning of table'); ?>
+ </option>
+ <?php $cols_count = count($columns_list);
+ foreach ($columns_list as $one_column_name): ?>
+ <?php if (--$cols_count == 0): ?>
+ <option value="<?php echo htmlspecialchars($one_column_name); ?>" selected="selected">
+ <?php else: ?>
+ <option value="<?php echo htmlspecialchars($one_column_name); ?>">
+ <?php endif; ?>
+ <?php echo sprintf(__('after %s'), htmlspecialchars($one_column_name)); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ <input type="submit" value="<?php echo __('Go'); ?>" />
+</form>
diff --git a/templates/table/structure/check_all_table_column.phtml b/templates/table/structure/check_all_table_column.phtml
new file mode 100644
index 0000000000..1e7cfa727a
--- /dev/null
+++ b/templates/table/structure/check_all_table_column.phtml
@@ -0,0 +1,57 @@
+<div class="print_ignore" >
+ <?php echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "fieldsForm"); ?>
+ <?php echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_browse',
+ __('Browse'), 'b_browse.png', 'browse'
+ ); ?>
+
+ <?php if (! $tbl_is_view && ! $db_is_system_schema): ?>
+ <?php echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit change_columns_anchor ajax',
+ 'submit_mult_change', __('Change'), 'b_edit.png', 'change'
+ ); ?>
+ <?php echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_drop',
+ __('Drop'), 'b_drop.png', 'drop'
+ ); ?>
+
+ <?php if ('ARCHIVE' != $tbl_storage_engine): ?>
+ <?php
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_primary',
+ __('Primary'), 'b_primary.png', 'primary'
+ );
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_unique',
+ __('Unique'), 'b_unique.png', 'unique'
+ );
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_index',
+ __('Index'), 'b_index.png', 'index'
+ );
+ ?>
+
+ <?php if (! empty($tbl_storage_engine)
+ && ($tbl_storage_engine == 'MYISAM'
+ || $tbl_storage_engine == 'ARIA'
+ || $tbl_storage_engine == 'MARIA')): ?>
+ <?php echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_fulltext',
+ __('Fulltext'), 'b_ftext.png', 'ftext'
+ ); ?>
+ <?php endif; ?>
+
+ <?php if ($GLOBALS['cfgRelation']['centralcolumnswork']): ?>
+ <?php
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_central_columns_add',
+ __('Add to central columns'), 'centralColumns_add.png',
+ 'add_to_central_columns');
+ echo PMA_Util::getButtonOrImage(
+ 'submit_mult', 'mult_submit', 'submit_mult_central_columns_remove',
+ __('Remove from central columns'), 'centralColumns_delete.png',
+ 'remove_from_central_columns'); ?>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endif; ?>
+</div>
diff --git a/templates/table/structure/display_partitions.phtml b/templates/table/structure/display_partitions.phtml
new file mode 100644
index 0000000000..fe3ced64d8
--- /dev/null
+++ b/templates/table/structure/display_partitions.phtml
@@ -0,0 +1,125 @@
+<div id="partitions">
+ <fieldset>
+ <legend><?php echo __('Partitions')
+ . PMA_Util::showMySQLDocu('partitioning'); ?>
+ </legend>
+ <p>
+ <?php echo __('Partitioned by:');?>
+ <code><?php echo $partitionMethod . '(' . $partitionExpression . ' )'; ?></code>
+ </p>
+ <?php if ($hasSubPartitions): ?>
+ <p>
+ <?php echo __('Sub partitioned by:'); ?>
+ <code><?php echo $subPartitionMethod . '(' . $subPartitionExpression . ' )'; ?></code>
+ <p>
+ <?php endif; ?>
+ <table>
+ <thead>
+ <tr>
+ <th colspan="2">#</th>
+ <th><?php echo __('Name'); ?></th>
+ <?php if ($hasDescription): ?>
+ <th><?php echo __('Expression'); ?></th>
+ <?php endif; ?>
+ <th><?php echo __('Rows'); ?></th>
+ <th><?php echo __('Data length'); ?></th>
+ <th><?php echo __('Index length'); ?></th>
+ <th><?php echo __('Comment'); ?></th>
+ <th colspan="<?php echo $rangeOrList ? '7' : '6'; ?>">
+ <?php echo __('Action'); ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php $odd = true; ?>
+ <?php foreach ($partitions as $partition): ?>
+ <tr class="noclick <?php echo $odd ? 'odd' : 'even'; echo $hasSubPartitions ? ' marked' : '';?>">
+ <?php if ($hasSubPartitions): ?>
+ <td><?php echo $partition->getOrdinal(); ?></td>
+ <td></td>
+ <?php else: ?>
+ <td colspan="2"><?php echo $partition->getOrdinal(); ?></td>
+ <?php endif; ?>
+ <th><?php echo htmlspecialchars($partition->getName()); ?></th>
+ <?php if ($hasDescription): ?>
+ <td>
+ <code>
+ <?php
+ echo htmlspecialchars($partition->getExpression())
+ . ($partition->getMethod() == 'LIST' ? ' IN (' : ' < ')
+ . htmlspecialchars($partition->getDescription())
+ . ($partition->getMethod() == 'LIST' ? ')' : '');
+ ?>
+ </code>
+ </td>
+ <?php endif; ?>
+ <td class="value"><?php echo $partition->getRows(); ?></td>
+ <td class="value"><?php
+ list($value, $unit) = PMA_Util::formatByteDown(
+ $partition->getDataLength(), 3, 1
+ );
+ ?>
+ <span><?php echo $value; ?></span>
+ <span class="unit"><?php echo $unit; ?></span>
+ </td>
+ <td class="value"><?php
+ list($value, $unit) = PMA_Util::formatByteDown(
+ $partition->getIndexLength(), 3, 1
+ );
+ ?>
+ <span><?php echo $value; ?></span>
+ <span class="unit"><?php echo $unit; ?></span>
+ </td>
+ <td><?php echo $partition->getComment(); ?></td>
+ <?php foreach ($actionIcons as $action => $icon): ?>
+ <td>
+ <a href="tbl_structure.php<?php echo $url_query; ?>&amp;partition_maintenance=1&amp;sql_query=<?php echo urlencode(
+ "ALTER TABLE " . PMA_Util::backquote($table) . $action . " PARTITION " . $partition->getName()
+ ) ?>"
+ id="partition_action_<?php echo $action; ?>"
+ name="partition_action_<?php echo $action; ?>"
+ class="ajax"
+ >
+ <?php echo $icon; ?>
+ </a>
+ </td>
+ <?php endforeach; ?>
+
+ <?php if ($hasSubPartitions): ?>
+ <?php foreach ($partition->getSubPartitions() as $subParition): ?>
+ <tr class="noclick <?php echo $odd ? 'odd' : 'even' ?>">
+ <td></td>
+ <td><?php echo $subParition->getOrdinal(); ?></td>
+ <td><?php echo htmlspecialchars($subParition->getName()); ?></td>
+ <?php if ($hasDescription): ?>
+ <td></td>
+ <?php endif; ?>
+ <td class="value"><?php echo $subParition->getRows(); ?></td>
+ <td class="value"><?php
+ list($value, $unit) = PMA_Util::formatByteDown(
+ $subParition->getDataLength(), 3, 1
+ );
+ ?>
+ <span><?php echo $value; ?></span>
+ <span class="unit"><?php echo $unit; ?></span>
+ </td>
+ <td class="value"><?php
+ list($value, $unit) = PMA_Util::formatByteDown(
+ $subParition->getIndexLength(), 3, 1
+ );
+ ?>
+ <span><?php echo $value; ?></span>
+ <span class="unit"><?php echo $unit; ?></span>
+ </td>
+ <td><?php echo $subParition->getComment(); ?></td>
+ <td colspan="<?php echo $rangeOrList ? '7' : '6'; ?>"></td>
+ </tr>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ </tr>
+ <?php $odd = ! $odd; ?>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ </fieldset>
+</div> \ No newline at end of file
diff --git a/templates/table/structure/display_structure.phtml b/templates/table/structure/display_structure.phtml
new file mode 100644
index 0000000000..25f962dcb5
--- /dev/null
+++ b/templates/table/structure/display_structure.phtml
@@ -0,0 +1,222 @@
+<?php $rownum = 0; $odd_row = true; ?>
+<form method="post" action="tbl_structure.php" name="fieldsForm" id="fieldsForm" class="ajax<?php echo $HideStructureActions; ?>">
+ <?php echo PMA_URL_getHiddenInputs($db, $table); ?>
+ <input type="hidden" name="table_type" value=
+ <?php if ($db_is_system_schema): ?>
+ "information_schema" />
+ <?php elseif ($tbl_is_view): ?>
+ "view" />
+ <?php else: ?>
+ "table" />
+ <?php endif; ?>
+ <table id="tablestructure" class="data topmargin">
+ <!-- table header -->
+ <?php echo PMA\Template::get('table/structure/table_structure_header')->render(
+ array(
+ 'db_is_system_schema' => $db_is_system_schema,
+ 'tbl_is_view' => $tbl_is_view
+ )
+ ); ?>
+ <tbody>
+ <!-- table body -->
+ <?php foreach($fields as $row): ?>
+ <?php
+ $rownum++;
+ $columns_list[] = $row['Field'];
+ $extracted_columnspec = PMA_Util::extractColumnSpec($row['Type']);
+ $attribute = $extracted_columnspec['attribute'];
+
+ // prepare a common variable to reuse below; however,
+ // in case of a VIEW, $create_table_fields is empty
+ if (isset($create_table_fields[$row['Field']])) {
+ $tempField = $create_table_fields[$row['Field']];
+ } else {
+ $tempField = array();
+ }
+
+ // MySQL 4.1.2+ TIMESTAMP options
+ // (if on_update_current_timestamp is set, then it's TRUE)
+ if (isset($tempField['on_update_current_timestamp'])) {
+ $attribute = 'on update CURRENT_TIMESTAMP';
+ }
+
+ // here, we have a TIMESTAMP that SHOW FULL COLUMNS reports as having the
+ // NULL attribute, but SHOW CREATE TABLE says the contrary. Believe
+ // the latter.
+ if (! empty($tempField['type'])
+ && $tempField['type'] == 'TIMESTAMP'
+ && $tempField['timestamp_not_null']
+ ) {
+ $row['Null'] = '';
+ }
+
+ if (! isset($row['Default'])) {
+ if ($row['Null'] == 'YES') {
+ $row['Default'] = '<i>NULL</i>';
+ }
+ } else {
+ $row['Default'] = htmlspecialchars($row['Default']);
+ }
+
+ $field_name = htmlspecialchars($row['Field']);
+ $displayed_field_name = $field_name;
+
+ // underline commented fields and display a hover-title (CSS only)
+
+ if (isset($comments_map[$row['Field']])) {
+ $displayed_field_name = '<span class="commented_column" title="'
+ . htmlspecialchars($comments_map[$row['Field']]) . '">'
+ . $field_name . '</span>';
+ }
+
+ if ($primary && $primary->hasColumn($field_name)) {
+ $displayed_field_name .= PMA_Util::getImage(
+ 'b_primary.png', __('Primary')
+ );
+ }
+ if (in_array($field_name, $columns_with_index)) {
+ $displayed_field_name .= PMA_Util::getImage(
+ 'bd_primary.png', __('Index')
+ );
+ }
+ ?>
+ <tr class="<?php echo ($odd_row ? 'odd': 'even'); ?>">
+ <?php $odd_row = !$odd_row; ?>
+ <?php echo PMA\Template::get('table/structure/table_structure_row')->render(
+ array(
+ 'row' => $row,
+ 'rownum' => $rownum,
+ 'displayed_field_name' => $displayed_field_name,
+ 'type_nowrap' => PMA_Util::getClassForType($extracted_columnspec['type']),
+ 'extracted_columnspec' => $extracted_columnspec,
+ 'attribute' => $attribute,
+ 'tbl_is_view' => $tbl_is_view,
+ 'db_is_system_schema' => $db_is_system_schema,
+ 'url_query' => $url_query,
+ 'field_encoded' => urlencode($row['Field']),
+ 'titles' => $titles,
+ 'table' => $table,
+ 'tbl_storage_engine' => $tbl_storage_engine
+ )
+ ); ?>
+ <?php if (! $tbl_is_view && ! $db_is_system_schema): ?>
+ <?php echo PMA\Template::get('table/structure/actions_in_table_structure')->render(
+ array(
+ 'extracted_columnspec' => $extracted_columnspec,
+ 'type' => (!empty($extracted_columnspec['print_type'])) ? $extracted_columnspec['print_type'] : ' ',
+ 'tbl_storage_engine' => $tbl_storage_engine,
+ 'primary' => $primary,
+ 'field_name' => $field_name,
+ 'url_query' => $url_query,
+ 'titles' => $titles,
+ 'row' => $row,
+ 'rownum' => $rownum,
+ 'columns_with_unique_index' => $columns_with_unique_index,
+ 'isInCentralColumns' => in_array($row['Field'], $central_list) ? true : false
+ )
+ ); ?>
+ <?php endif; ?>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ <?php echo PMA\Template::get('table/structure/check_all_table_column')->render(
+ array(
+ 'pmaThemeImage' => $GLOBALS['pmaThemeImage'],
+ 'text_dir' => $GLOBALS['text_dir'],
+ 'tbl_is_view' => $tbl_is_view,
+ 'db_is_system_schema' => $db_is_system_schema,
+ 'tbl_storage_engine' => $tbl_storage_engine
+ )
+ ); ?>
+</form>
+<hr class="print_ignore"/>
+<?php echo PMA\Template::get('table/structure/move_columns_dialog')->render(); ?>
+<!--Work on the table-->
+<div id="structure-action-links">
+ <?php if ($tbl_is_view): ?>
+ <?php echo PMA_Util::linkOrButton(
+ $edit_view_url,
+ PMA_Util::getIcon('b_edit.png', __('Edit view'), true)
+ ); ?>
+ <?php endif; ?>
+ <?php echo PMA\Template::get('table/structure/optional_action_links')->render(
+ array(
+ 'url_query' => $url_query,
+ 'tbl_is_view' => $tbl_is_view,
+ 'db_is_system_schema' => $db_is_system_schema
+ )
+ ); ?>
+</div>
+<?php if (! $tbl_is_view && ! $db_is_system_schema): ?>
+ <br />
+ <?php echo PMA\Template::get('table/structure/add_column')->render(
+ array('columns_list' => $columns_list)
+ ); ?>
+<?php endif; ?>
+
+<!--Displays indexes-->
+<?php if (! $tbl_is_view
+ && ! $db_is_system_schema && 'ARCHIVE' != $tbl_storage_engine): ?>
+ <?php echo PMA_getHtmlForDisplayIndexes(); ?>
+<?php endif; ?>
+
+<!--Display partition details-->
+<?php
+$partition_names = PMA_Partition::getPartitionNames($db, $table);
+// detect partitioning
+if (! is_null($partition_names[0])) {
+
+ $partitions = PMA_Partition::getPartitions($db, $table);
+ $firstPartition = $partitions[0];
+ $rangeOrList = $firstPartition->getMethod() == 'RANGE'
+ || $firstPartition->getMethod() == 'LIST';
+ $subParitions = $firstPartition->getSubPartitions();
+ $hasSubPartitions = $firstPartition->hasSubPartitions();
+ if ($hasSubPartitions) {
+ $firstSubPartition = $subParitions[0];
+ }
+
+ $actionIcons = array(
+ 'ANALYZE' => PMA_Util::getIcon('b_search.png', __('Analyze')),
+ 'CHECK' => PMA_Util::getIcon('eye.png', __('Check')),
+ 'OPTIMIZE' => PMA_Util::getIcon('normalize.png', __('Optimize')),
+ 'REBUILD' => PMA_Util::getIcon('s_tbl.png', __('Rebuild')),
+ 'REPAIR' => PMA_Util::getIcon('b_tblops.png', __('Repair')),
+ 'TRUNCATE' => PMA_Util::getIcon('b_empty.png', __('Truncate')),
+ );
+ if ($rangeOrList) {
+ $actionIcons['DROP'] = PMA_Util::getIcon('b_drop.png', __('Drop'));
+ }
+
+ echo PMA_Util::getDivForSliderEffect(
+ 'partitions', __('Partitions')
+ );
+
+ $tmp_partition_description = $firstPartition->getDescription();
+
+ echo PMA\Template::get('table/structure/display_partitions')->render(
+ array(
+ 'table' => $table,
+ 'url_query' => $url_query,
+ 'partitions' => $partitions,
+ 'partitionMethod' => $firstPartition->getMethod(),
+ 'partitionExpression' => $firstPartition->getExpression(),
+ 'hasDescription' => ! empty($tmp_partition_description),
+ 'hasSubPartitions' => $hasSubPartitions,
+ 'subPartitionMethod' => $hasSubPartitions ? $firstSubPartition->getMethod() : null,
+ 'subPartitionExpression' => $hasSubPartitions ? $firstSubPartition->getExpression() : null,
+ 'actionIcons' => $actionIcons,
+ 'rangeOrList' => $rangeOrList,
+ )
+ );
+?>
+<!-- For closing Slider effect div-->
+</div>
+<?php } ?>
+
+<!--Displays Space usage and row statistics-->
+<?php if ($GLOBALS['cfg']['ShowStats']): ?>
+ <?php echo $tablestats; ?>
+<?php endif; ?>
+<div class="clearfloat"></div>
diff --git a/templates/table/structure/display_table_stats.phtml b/templates/table/structure/display_table_stats.phtml
new file mode 100644
index 0000000000..281827a961
--- /dev/null
+++ b/templates/table/structure/display_table_stats.phtml
@@ -0,0 +1,77 @@
+<div id="tablestatistics">
+ <?php $odd_row = false; ?>
+ <fieldset>
+ <legend><?php echo __('Information'); ?></legend>
+ <a id="showusage"></a>
+
+ <?php if (! $tbl_is_view && ! $db_is_system_schema): ?>
+ <table id="tablespaceusage" class="data">
+ <caption class="tblHeaders"><?php echo __('Space usage'); ?></caption>
+ <tbody>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Data'); ?></th>
+ <td class="value"><?php echo $data_size; ?></td>
+ <td class="unit"><?php echo $data_unit; ?></td>
+ </tr>
+
+ <?php if (isset($index_size)): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Index'); ?></th>
+ <td class="value"><?php echo $index_size; ?></td>
+ <td class="unit"><?php echo $index_unit; ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (isset($free_size)): ?>
+ <tr class="<?php echo ((!$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Overhead'); ?></th>
+ <td class="value"><?php echo $free_size; ?></td>
+ <td class="unit"><?php echo $free_unit; ?></td>
+ </tr>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Effective'); ?></th>
+ <td class="value"><?php echo $effect_size; ?></td>
+ <td class="unit"><?php echo $effect_unit; ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (isset($tot_size) && $mergetable == false): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Total'); ?></th>
+ <td class="value"><?php echo $tot_size; ?></td>
+ <td class="unit"><?php echo $tot_unit; ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <!-- Optimize link if overhead -->
+ <?php if (isset($free_size) && !PMA_DRIZZLE
+ && ($tbl_storage_engine == 'MYISAM'
+ || $tbl_storage_engine == 'ARIA'
+ || $tbl_storage_engine == 'MARIA'
+ || $tbl_storage_engine == 'BDB')): ?>
+ <tr class="tblFooters">
+ <td colspan="3" class="center">
+ <a href="sql.php<?php echo $url_query; ?>&pos=0&amp;sql_query=<?php echo urlencode(
+ 'OPTIMIZE TABLE ' . PMA_Util::backquote($GLOBALS['table'])); ?>">
+ <?php echo PMA_Util::getIcon('b_tbloptimize.png', __('Optimize table')); ?>
+ </a>
+ </td>
+ </tr>
+ <?php endif; ?>
+ </tbody>
+ </table>
+ <?php endif; ?>
+ <?php
+ echo PMA\Template::get('table/structure/row_stats_table')->render(
+ array(
+ 'showtable' => $showtable,
+ 'tbl_collation' => $tbl_collation,
+ 'is_innodb' => $is_innodb,
+ 'mergetable' => $mergetable,
+ 'avg_size' => (isset ($avg_size) ? $avg_size : ''),
+ 'avg_unit' => (isset ($avg_unit) ? $avg_unit : '')
+ )
+ );
+ ?>
+ </fieldset>
+</div>
diff --git a/templates/table/structure/move_columns_dialog.phtml b/templates/table/structure/move_columns_dialog.phtml
new file mode 100644
index 0000000000..cc4a40eaef
--- /dev/null
+++ b/templates/table/structure/move_columns_dialog.phtml
@@ -0,0 +1,8 @@
+<div id="move_columns_dialog" title="<?php echo __('Move columns'); ?>" style="display: none">
+ <p><?php echo __('Move the columns by dragging them up and down.'); ?></p>
+ <form action="tbl_structure.php">
+ <div><?php echo PMA_URL_getHiddenInputs($GLOBALS['db'], $GLOBALS['table']); ?>
+ <ul></ul>
+ </div>
+ </form>
+</div>
diff --git a/templates/table/structure/optional_action_links.phtml b/templates/table/structure/optional_action_links.phtml
new file mode 100644
index 0000000000..865ebee4aa
--- /dev/null
+++ b/templates/table/structure/optional_action_links.phtml
@@ -0,0 +1,34 @@
+<a href="#" id="printView"><?php echo PMA_Util::getIcon('b_print.png', __('Print view'), true); ?></a>
+<?php if (! $tbl_is_view && ! $db_is_system_schema): ?>
+ <?php if (!PMA_DRIZZLE): ?>
+ <a href="sql.php<?php echo $url_query; ?>&amp;session_max_rows=all&amp;sql_query=' . <?php echo urlencode(
+ 'SELECT * FROM ' . PMA_Util::backquote($GLOBALS['table'])
+ . ' PROCEDURE ANALYSE()'
+ ); ?>" style="margin-right: 0;">
+ <?php echo PMA_Util::getIcon(
+ 'b_tblanalyse.png',
+ __('Propose table structure'),
+ true
+ ); ?>
+ </a>
+ <?php echo PMA_Util::showMySQLDocu('procedure_analyse'); ?>
+ <?php endif; ?>
+ <?php if (PMA_Tracker::isActive()): ?>
+ <a href="tbl_tracking.php<?php echo $url_query; ?>">
+ <?php echo PMA_Util::getIcon('eye.png', __('Track table'), true); ?>
+ </a>
+ <?php endif; ?>
+ <a href="#" id="move_columns_anchor">
+ <?php echo PMA_Util::getIcon('b_move.png', __('Move columns'), true); ?>
+ </a>
+ <a href="normalization.php<?php echo $url_query; ?>">
+ <?php echo PMA_Util::getIcon('normalize.png', __('Improve table structure'), true); ?>
+ </a>
+<?php endif; ?>
+<?php if ($tbl_is_view && ! $db_is_system_schema): ?>
+ <?php if (PMA_Tracker::isActive()): ?>
+ <a href="tbl_tracking.php<?php echo $url_query; ?>">
+ <?php echo PMA_Util::getIcon('eye.png', __('Track view'), true); ?>
+ </a>
+ <?php endif; ?>
+<?php endif; ?>
diff --git a/templates/table/structure/row_stats_table.phtml b/templates/table/structure/row_stats_table.phtml
new file mode 100644
index 0000000000..4f3b243466
--- /dev/null
+++ b/templates/table/structure/row_stats_table.phtml
@@ -0,0 +1,99 @@
+<?php $odd_row = false; ?>
+<table id="tablerowstats" class="data">
+<caption class="tblHeaders"><?php echo __('Row statistics'); ?></caption>
+<tbody>
+ <?php if (isset($showtable['Row_format'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Format'); ?></th>
+ <?php if ($showtable['Row_format'] == 'Fixed'): ?>
+ <td class="value"><?php echo __('static'); ?></td>
+ <?php elseif ($showtable['Row_format'] == 'Dynamic'): ?>
+ <td class="value"><?php echo __('dynamic'); ?></td>
+ <?php else: ?>
+ <td class="value"><?php echo $showtable['Row_format']; ?></td>
+ <?php endif; ?>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (! empty($showtable['Create_options'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Options'); ?></th>
+ <?php if ($showtable['Create_options'] == 'partitioned'): ?>
+ <td class="value"><?php echo __('partitioned'); ?></td>
+ <?php else: ?>
+ <td class="value"><?php echo $showtable['Create_options']; ?></td>
+ <?php endif; ?>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (!empty($tbl_collation)): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Collation'); ?></th>
+ <td class="value">
+ <dfn title="<?php echo PMA_getCollationDescr($tbl_collation); ?>">
+ <?php echo $tbl_collation; ?>
+ </dfn>
+ </td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (!$is_innodb && isset($showtable['Rows'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Rows'); ?></th>
+ <td class="value"><?php echo PMA_Util::formatNumber($showtable['Rows'], 0); ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (!$is_innodb
+ && isset($showtable['Avg_row_length'])
+ && $showtable['Avg_row_length'] > 0
+ ): ?>
+ <?php list($avg_row_length_value, $avg_row_length_unit)
+ = PMA_Util::formatByteDown($showtable['Avg_row_length'], 6, 1); ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Row length'); ?></th>
+ <td class="value"><?php echo ($avg_row_length_value . ' ' . $avg_row_length_unit); ?></td>
+ </tr>
+ <?php unset($avg_row_length_value, $avg_row_length_unit); ?>
+ <?php endif; ?>
+
+ <?php if (!$is_innodb
+ && isset($showtable['Data_length'])
+ && isset($showtable['Rows'])
+ && $showtable['Rows'] > 0
+ && $mergetable == false): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Row size'); ?></th>
+ <td class="value"><?php echo ($avg_size . ' ' . $avg_unit); ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (isset($showtable['Auto_increment'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Next autoindex'); ?></th>
+ <td class="value"><?php echo PMA_Util::formatNumber($showtable['Auto_increment'], 0); ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (isset($showtable['Create_time'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Creation'); ?></th>
+ <td class="value"><?php echo PMA_Util::localisedDate(strtotime($showtable['Create_time'])); ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (isset($showtable['Update_time'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Last update'); ?></th>
+ <td class="value"><?php echo PMA_Util::localisedDate(strtotime($showtable['Update_time'])); ?></td>
+ </tr>
+ <?php endif; ?>
+
+ <?php if (isset($showtable['Check_time'])): ?>
+ <tr class="<?php echo (($odd_row = !$odd_row) ? 'odd' : 'even'); ?>">
+ <th class="name"><?php echo __('Last check'); ?></th>
+ <td class="value"><?php echo PMA_Util::localisedDate(strtotime($showtable['Check_time'])); ?></td>
+ </tr>
+ <?php endif; ?>
+</tbody>
+</table>
diff --git a/templates/table/structure/table_structure_header.phtml b/templates/table/structure/table_structure_header.phtml
new file mode 100644
index 0000000000..a739e73e08
--- /dev/null
+++ b/templates/table/structure/table_structure_header.phtml
@@ -0,0 +1,26 @@
+<thead>
+<tr>
+ <th class="print_ignore"></th>
+ <th>#</th>
+ <th><?php echo __('Name'); ?></th>
+ <th><?php echo __('Type'); ?></th>
+ <th><?php echo __('Collation'); ?></th>
+ <th><?php echo __('Attributes'); ?></th>
+ <th><?php echo __('Null'); ?></th>
+ <th><?php echo __('Default'); ?></th>
+ <th><?php echo __('Extra'); ?></th>
+ <!-- see tbl_structure.js, function moreOptsMenuResize() -->
+ <?php if (! $db_is_system_schema && ! $tbl_is_view): ?>
+ <?php
+ $colspan = 9;
+ if (PMA_DRIZZLE) {
+ $colspan -= 2;
+ }
+ if (PMA_Util::showIcons('ActionLinksMode')) {
+ $colspan--;
+ }
+ ?>
+ <th colspan="<?php echo $colspan; ?>" class="action print_ignore"><?php echo __('Action'); ?></th>
+ <?php endif; ?>
+</tr>
+</thead>
diff --git a/templates/table/structure/table_structure_row.phtml b/templates/table/structure/table_structure_row.phtml
new file mode 100644
index 0000000000..0928c7a0fa
--- /dev/null
+++ b/templates/table/structure/table_structure_row.phtml
@@ -0,0 +1,50 @@
+<td class="center print_ignore">
+ <input type="checkbox" class="checkall" name="selected_fld[]" value="<?php echo htmlspecialchars($row['Field']); ?>" id="checkbox_row_<?php echo $rownum; ?>"/>
+</td>
+<td class="right"><?php echo $rownum; ?></td>
+<th class="nowrap">
+ <label for="checkbox_row_<?php echo $rownum; ?>">
+ <?php echo preg_replace('/[\x00-\x1F]/', '&#x2051;', $displayed_field_name); ?>
+ </label>
+</th>
+<td <?php echo $type_nowrap; ?>>
+ <bdo dir="ltr" lang="en"><?php echo $extracted_columnspec['displayed_type']; ?>
+ <?php if ($GLOBALS['cfgRelation']['commwork'] && $GLOBALS['cfgRelation']['mimework']
+ && $GLOBALS['cfg']['BrowseMIME'] && isset($mime_map[$row['Field']]['mimetype'])): ?>
+ <br />MIME: <?php echo strtolower(str_replace('_', '/', $mime_map[$row['Field']]['mimetype'])); ?>
+ <?php endif; ?>
+ </bdo>
+</td>
+<td>
+<?php if (! empty($field_charset)): ?>
+ <dfn title="<?php echo PMA_getCollationDescr($field_charset); ?>"><?php echo $field_charset; ?></dfn>
+<?php endif; ?>
+</td>
+<td class="column_attribute nowrap"><?php echo $attribute; ?></td>
+<td><?php echo (($row['Null'] == 'YES') ? __('Yes') : __('No')); ?></td>
+<td class="nowrap">
+ <?php if (isset($row['Default'])): ?>
+ <?php if ($extracted_columnspec['type'] == 'bit'): ?>
+ <?php echo PMA_Util::convertBitDefaultValue($row['Default']); ?>
+ <?php else: ?>
+ <?php echo $row['Default']; ?>
+ <?php endif;?>
+ <?php else: ?>
+ <i><?php echo _pgettext('None for default', 'None'); ?></i>
+ <?php endif; ?>
+</td>
+<td class="nowrap"><?php echo /*overload*/mb_strtoupper($row['Extra']); ?></td>
+<?php if (! $tbl_is_view && ! $db_is_system_schema): ?>
+ <td class="edit center print_ignore">
+ <a class="change_column_anchor ajax" href="tbl_structure.php<?php echo $url_query; ?>&amp;field=<?php echo $field_encoded; ?>&amp;change_column=1">
+ <?php echo $titles['Change']; ?>
+ </a>
+ </td>
+ <td class="drop center print_ignore">
+ <a class="drop_column_anchor ajax" href="sql.php<?php echo $url_query; ?>&amp;sql_query=<?php echo urlencode(
+ 'ALTER TABLE ' . PMA_Util::backquote($table)
+ . ' DROP ' . PMA_Util::backquote($row['Field']) . ';'); ?>&amp;dropped_column=<?php echo $field_encoded; ?>&amp;purge=1&amp;message_to_show=<?php echo urlencode(sprintf(__('Column %s has been dropped.'), htmlspecialchars($row['Field']))) ?>" >
+ <?php echo $titles['Drop']; ?>
+ </a>
+ </td>
+<?php endif; ?>
diff --git a/templates/test/echo.phtml b/templates/test/echo.phtml
new file mode 100644
index 0000000000..44da4ed410
--- /dev/null
+++ b/templates/test/echo.phtml
@@ -0,0 +1,2 @@
+<?php
+echo $variable; \ No newline at end of file
diff --git a/templates/test/static.phtml b/templates/test/static.phtml
new file mode 100644
index 0000000000..703390d105
--- /dev/null
+++ b/templates/test/static.phtml
@@ -0,0 +1 @@
+static content \ No newline at end of file
diff --git a/templates/test/trim.phtml b/templates/test/trim.phtml
new file mode 100644
index 0000000000..56b4ac493e
--- /dev/null
+++ b/templates/test/trim.phtml
@@ -0,0 +1 @@
+outer <element> value </element> value \ No newline at end of file
diff --git a/themes.php b/themes.php
index 4e56365d01..e938a824b5 100644
--- a/themes.php
+++ b/themes.php
@@ -28,5 +28,3 @@ $output .= '</p>';
$output .= $_SESSION['PMA_Theme_Manager']->getPrintPreviews();
$response->addHTML($output);
-
-?>
diff --git a/themes/original/css/common.css.php b/themes/original/css/common.css.php
index 58538181fa..42e7b48c1c 100644
--- a/themes/original/css/common.css.php
+++ b/themes/original/css/common.css.php
@@ -43,7 +43,7 @@ body#loginform {
margin: 0;
}
-#page_content, #session_debug {
+#page_content {
margin: 0 .5em;
}
@@ -120,11 +120,6 @@ form {
textarea {
overflow: visible;
- height: <?php echo ceil($GLOBALS['cfg']['TextareaRows'] * 1.2); ?>em;
-}
-
-textarea.char {
- height: <?php echo ceil($GLOBALS['cfg']['CharTextareaRows'] * 1.2); ?>em;
}
fieldset {
@@ -203,6 +198,7 @@ th.center, td.center {
th.right, td.right {
text-align: right;
+ padding-right: 1em;
}
tr.vtop, th.vtop, td.vtop {
@@ -812,20 +808,30 @@ div#tablestatistics table {
white-space: nowrap;
}
-#goto_pagetop, #lock_page_icon {
+#page_nav_icons {
position: fixed;
- padding: .1em .3em;
top: 0;
+ <?php echo $right; ?>: 0;
z-index: 99;
+ padding: .1em 0;
+}
+
+#goto_pagetop, #lock_page_icon, #page_settings_icon {
+ padding: .3em;
background: white;
}
-#goto_pagetop {
- <?php echo $right; ?>: 0;
+#page_settings_icon {
+ cursor: pointer;
+ display: none;
}
-#lock_page_icon {
- <?php echo $right; ?>: 2em;
+#page_settings_modal {
+ display: none;
+}
+
+#pma_navigation_settings {
+ display: none;
}
#span_table_comment {
@@ -1038,7 +1044,7 @@ table#chartGrid div.monitorChart {
div.tabLinks {
margin-left: 0.3em;
float: <?php echo $left; ?>;
- padding: 5px 0px;
+ padding: 5px 0;
}
div.tabLinks a, div.tabLinks label {
@@ -1046,7 +1052,7 @@ div.tabLinks a, div.tabLinks label {
}
div.tabLinks .icon {
- margin: -0.2em 0.3em 0px 0px;
+ margin: -0.2em 0.3em 0 0;
}
.popupContent {
@@ -1164,6 +1170,13 @@ div#profilingchart {
}
/* end profiling */
+/* table charting */
+.chartOption {
+ float: <?php echo $left; ?>;
+ margin-<?php echo $right;?>: 40px;
+}
+/* end table charting */
+
/* querybox */
div#sqlquerycontainer {
@@ -1216,7 +1229,7 @@ div#queryboxcontainer div#bookmarkoptions {
}
#maincontainer li {
- margin: 0.2em 0em;
+ margin: 0.2em 0;
}
#full_name_layer {
@@ -1342,6 +1355,7 @@ div.sqlvalidate {
margin-bottom: 0;
max-height: 10em;
overflow: auto;
+ direction: ltr;
}
.result_query div.sqlOuter,
@@ -1502,6 +1516,30 @@ select.invalid_value,
* Export and Import styles
*/
+.export_table_list_container {
+ display: inline-block;
+ max-height: 20em;
+ overflow-y: scroll;
+}
+
+.export_table_select th {
+ text-align: center;
+ vertical-align: middle;
+}
+
+.export_table_select .all {
+ font-weight: bold;
+ border-bottom: 1px solid black;
+}
+
+.export_structure, .export_data {
+ text-align: center;
+}
+
+.export_table_name {
+ vertical-align: middle;
+}
+
.exportoptions h3, .importoptions h3 {
border-bottom: 1px #999999 solid;
font-size: 110%;
@@ -1923,6 +1961,7 @@ fieldset .disabled-field td {
#prefs_autoload {
margin-bottom: .5em;
+ margin-left: .5em;
}
#placeholder .button {
@@ -1991,6 +2030,17 @@ fieldset .disabled-field td {
padding: 0.5em;
}
+#table_name_col_no_outer {
+ margin-top: 30px;
+}
+
+#table_name_col_no {
+ position: fixed;
+ top: 44px;
+ width: 100%;
+ background: <?php echo $GLOBALS['cfg']['MainBackground']; ?>;
+}
+
#table_columns input[type="text"],
#table_columns input[type="password"],
#table_columns input[type="number"],
@@ -2359,45 +2409,39 @@ according to css rules*/
.jqplot-xaxis-tick {
- top: 0px;
+ top: 0;
/* initial position untill tick is drawn in proper place */
left: 15px;
-/* padding-top: 10px;*/
vertical-align: top;
}
.jqplot-x2axis-tick {
- bottom: 0px;
+ bottom: 0;
/* initial position untill tick is drawn in proper place */
left: 15px;
-/* padding-bottom: 10px;*/
vertical-align: bottom;
}
.jqplot-yaxis-tick {
- right: 0px;
+ right: 0;
/* initial position untill tick is drawn in proper place */
top: 15px;
-/* padding-right: 10px;*/
text-align: right;
}
.jqplot-yaxis-tick.jqplot-breakTick {
right: -20px;
- margin-right: 0px;
+ margin-right: 0;
padding:1px 5px 1px 5px;
-/* background-color: white;*/
z-index: 2;
font-size: 1.5em;
}
.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick,
.jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick {
- left: 0px;
- /* initial position untill tick is drawn in proper place */
+ left: 0;
+ /* initial position until tick is drawn in proper place */
top: 15px;
-/* padding-left: 10px;*/
-/* padding-right: 15px;*/
text-align: left;
}
@@ -2497,8 +2541,8 @@ div.jqplot-table-legend-swatch-outline {
}
div.jqplot-table-legend-swatch {
- width:0px;
- height:0px;
+ width:0;
+ height:0;
border-top-width: 5px;
border-bottom-width: 5px;
border-left-width: 6px;
@@ -2510,8 +2554,8 @@ div.jqplot-table-legend-swatch {
}
.jqplot-title {
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
padding-bottom: 0.5em;
font-size: 1.2em;
}
@@ -2661,7 +2705,7 @@ table.show_create td {
margin-<?php echo $left; ?>: 240px;
z-index: 100;
}
-#pma_console>.templates {
+#pma_console .templates {
display: none;
}
#pma_console .mid_text,
@@ -2688,6 +2732,7 @@ table.show_create td {
#pma_console .message span.text,
#pma_console .message span.action,
#pma_console .toolbar .button,
+#pma_console .toolbar .text,
#pma_console .switch_button {
padding: 0 3px;
display: inline-block;
@@ -2699,13 +2744,19 @@ table.show_create td {
}
#pma_console .message span.action:hover,
#pma_console .toolbar .button:hover,
-#pma_console .switch_button:hover {
+#pma_console .switch_button:hover,
+#pma_console .toolbar .button.active {
background: #ddd;
}
-#pma_console .toolbar .button {
+#pma_console .toolbar .text {
+ font-weight: bold;
+}
+#pma_console .toolbar .button,
+#pma_console .toolbar .text {
margin-<?php echo $right; ?>: .4em;
}
-#pma_console .toolbar .button {
+#pma_console .toolbar .button,
+#pma_console .toolbar .text {
float: <?php echo $right; ?>;
}
#pma_console .content {
@@ -2716,6 +2767,26 @@ table.show_create td {
background: #fff;
padding-top: .4em;
}
+#pma_console .content.console_dark_theme {
+ background: #000;
+ color: #fff;
+}
+#pma_console .content.console_dark_theme .CodeMirror-wrap {
+ background: #000;
+ color: #fff;
+}
+#pma_console .content.console_dark_theme .action_content {
+ color: #000;
+}
+#pma_console .content.console_dark_theme .message {
+ border-color: #373B41;
+}
+#pma_console .content.console_dark_theme .CodeMirror-cursor {
+ border-color: #fff;
+}
+#pma_console .content.console_dark_theme .cm-keyword {
+ color: #de935f;
+}
#pma_console .message,
#pma_console .query_input {
position: relative;
@@ -2727,7 +2798,7 @@ table.show_create td {
border-bottom: solid 1px #ccc;
padding-bottom: .2em;
}
-#pma_console .message.expanded .action_content {
+#pma_console .message.expanded>.action_content {
position: relative;
}
#pma_console .message:before,
@@ -2819,9 +2890,12 @@ html.ie8 #pma_console .message .action_content {
#pma_console .message .text {
background: #fff;
}
-#pma_console .message.collapsed:not(:hover) .action_content {
+#pma_console .message.collapsed>.action_content {
display: none;
}
+#pma_console .message.collapsed:hover>.action_content {
+ display: block;
+}
#pma_console .message .bookmark_label {
padding: 0 4px;
top: 0;
@@ -2892,6 +2966,55 @@ html.ie7 #pma_console .query_input {
margin: 0;
padding: 2px 4px;
}
+#pma_console .button.hide,
+#pma_console .message span.text.hide {
+ display: none;
+}
+#debug_console.grouped .ungroup_queries,
+#debug_console.ungrouped .group_queries {
+ display: inline-block;
+}
+#debug_console.ungrouped .ungroup_queries,
+#debug_console.ungrouped .sort_count,
+#debug_console.grouped .group_queries {
+ display: none;
+}
+#debug_console .count {
+ margin-right: 8px;
+}
+#debug_console .show_trace .trace,
+#debug_console .show_args .args {
+ display: block;
+}
+#debug_console .hide_trace .trace,
+#debug_console .hide_args .args,
+#debug_console .show_trace .action.dbg_show_trace,
+#debug_console .hide_trace .action.dbg_hide_trace,
+#debug_console .traceStep.hide_args .action.dbg_hide_args,
+#debug_console .traceStep.show_args .action.dbg_show_args {
+ display: none;
+}
+
+#debug_console .traceStep:after,
+#debug_console .trace.welcome:after,
+#debug_console .debug>.welcome:after {
+ content: "";
+ display: table;
+ clear: both;
+}
+#debug_console .debug_summary {
+ float: left;
+}
+#debug_console .trace.welcome .time {
+ float: right;
+}
+#debug_console .traceStep .file,
+#debug_console .script_name {
+ float: right;
+}
+#debug_console .traceStep .args pre {
+ margin: 0;
+}
/* Code mirror console style*/
@@ -2915,7 +3038,6 @@ html.ie7 #pma_console .query_input {
font-size: 120%;
}
.cm-s-pma .CodeMirror-scroll {
- padding-bottom: 2em;
cursor: text;
}
@@ -2924,8 +3046,8 @@ html.ie7 #pma_console .query_input {
.pma_drop_handler {
display: none;
position: fixed;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
width: 100%;
background: rgba(0, 0, 0, 0.6);
height: 100%;
@@ -2939,7 +3061,7 @@ html.ie7 #pma_console .query_input {
.pma_sql_import_status {
display: none;
position: fixed;
- bottom: 0px;
+ bottom: 0;
right: 25px;
width: 400px;
border: 1px solid #999;
@@ -2988,13 +3110,13 @@ html.ie7 #pma_console .query_input {
.pma_sql_import_status h2 .minimize {
float: right;
margin-right: 5px;
- padding: 0px 10px;
+ padding: 0 10px;
}
.pma_sql_import_status h2 .close {
float: right;
margin-right: 5px;
- padding: 0px 10px;
+ padding: 0 10px;
display: none;
}
@@ -3022,7 +3144,7 @@ html.ie7 #pma_console .query_input {
background: white;
min-height: 300px;
z-index: 800;
- -webkit-box-shadow: 0px 0px 15px #999;
+ -webkit-box-shadow: 0 0 15px #999;
border-radius: 10px;
cursor: move;
}
@@ -3030,7 +3152,7 @@ html.ie7 #pma_console .query_input {
.pma_drop_result h2 .close {
float: right;
margin-right: 5px;
- padding: 0px 10px;
+ padding: 0 10px;
}
#composite_index_list {
@@ -3079,4 +3201,73 @@ th.headerSortUp .sorticon, th.headerSortDown:hover .sorticon {
th.headerSortDown .sorticon, th.headerSortUp:hover .sorticon {
background-image: url(<?php echo $_SESSION['PMA_Theme']->getImgPath('s_asc.png');?>);
}
-/* end of styles of sortable tables */ \ No newline at end of file
+/* end of styles of sortable tables */
+
+/* styles for jQuery-ui to support rtl languages */
+body .ui-dialog .ui-dialog-titlebar-close {
+ <?php echo $right; ?>: .3em;
+ <?php echo $left; ?>: initial;
+}
+
+body .ui-dialog .ui-dialog-title {
+ float: <?php echo $left; ?>;
+}
+
+body .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: <?php echo $right; ?>;
+}
+/* end of styles for jQuery-ui to support rtl languages */
+
+/* Override some jQuery-ui styling to have square corners */
+body .ui-corner-all,
+body .ui-corner-top,
+body .ui-corner-left,
+body .ui-corner-tl {
+ border-top-left-radius: 0;
+}
+body .ui-corner-all,
+body .ui-corner-top,
+body .ui-corner-right,
+body .ui-corner-tr {
+ border-top-right-radius: 0;
+}
+body .ui-corner-all,
+body .ui-corner-bottom,
+body .ui-corner-left,
+body .ui-corner-bl {
+ border-bottom-left-radius: 0;
+}
+body .ui-corner-all,
+body .ui-corner-bottom,
+body .ui-corner-right,
+body .ui-corner-br {
+ border-bottom-right-radius: 0;
+}
+/* Override jQuery-ui styling for ui-dialog */
+body .ui-dialog {
+ padding: 0;
+ border-color: #000000;
+}
+body .ui-dialog .ui-dialog-titlebar {
+ padding: .3em .5em;
+ border: none;
+ border-bottom: 1px solid #000000;
+}
+body .ui-dialog .ui-dialog-titlebar button {
+ border: 1px solid #999999;
+}
+body .ui-dialog .ui-dialog-content {
+ padding: .2em .4em;
+}
+body .ui-dialog .ui-dialog-buttonpane {
+ background: #D3DCE3;
+ border-top: 1px solid #000000;
+}
+body .ui-dialog .ui-dialog-buttonpane button {
+ margin: .1em 0 .1em .4em;
+ border: 1px solid #999999;
+ color: #000000;
+}
+body .ui-dialog .ui-button-text-only .ui-button-text {
+ padding: .2em .6em;
+}
diff --git a/themes/original/css/navigation.css.php b/themes/original/css/navigation.css.php
index d3cc4754eb..97705dca6f 100644
--- a/themes/original/css/navigation.css.php
+++ b/themes/original/css/navigation.css.php
@@ -123,7 +123,7 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
#pma_navigation_select_database {
text-align: left;
- padding: 0px 0px 0px;
+ padding: 0 0 0;
border: 0;
margin: 0;
}
@@ -140,7 +140,7 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
border-top: 1px solid #bbb;
color: #333;
padding: 4px 6px;
- margin: 0px 0px 0px;
+ margin: 0 0 0;
width: 92%;
font-size: 1.11em;
}
@@ -346,7 +346,7 @@ li.fast_filter.db_fast_filter {
text-align: center;
cursor: pointer;
z-index: 800;
- text-shadow: 0px 1px 0px #fff;
+ text-shadow: 0 1px 0 #fff;
filter: dropshadow(color=#fff, offx=0, offy=1);
border: 1px solid #888;
}
diff --git a/themes/original/css/printview.css b/themes/original/css/printview.css
new file mode 100644
index 0000000000..5ee47195e2
--- /dev/null
+++ b/themes/original/css/printview.css
@@ -0,0 +1,168 @@
+@media print {
+
+ /* For removing element from Print View */
+ .print_ignore {
+ display: none;
+ }
+
+ .nowrap {
+ white-space: nowrap;
+ }
+
+ .hide {
+ display: none;
+ }
+
+ /* Standard CSS */
+ body, table, th, td {
+ color: #000;
+ background-color: #fff;
+ font-size: 12px;
+ }
+
+ /* To remove link text decoration */
+ a:link {
+ color:#000;
+ text-decoration:none
+ }
+
+ /* To remove any image borders */
+ img {
+ border: 0;
+ }
+
+ /* Table specific */
+ table, th, td {
+ border: .1em solid #000;
+ background-color: #fff;
+ }
+
+ table {
+ border-collapse: collapse;
+ border-spacing: 0.2em;
+ }
+
+ thead {
+ border-collapse: collapse;
+ border-spacing: 0.2em;
+ border: .1em solid #000;
+ font-weight: 900;
+ }
+
+ th, td {
+ padding: 0.2em;
+ }
+
+ thead th {
+ font-weight: bold;
+ background-color: #e5e5e5;
+ border: .1em solid #000;
+ }
+
+ th.vtop, td.vtop {
+ vertical-align: top;
+ }
+
+ th.vbottom, td.vbottom {
+ vertical-align: bottom;
+ }
+
+ /* Common Elements not to be included */
+ /* Hide Navigation and Top Menu bar */
+ #pma_navigation, #floating_menubar {
+ display: none;
+ }
+ /* Hide console */
+ #pma_console_container {
+ display: none;
+ }
+
+ /* Hide Navigation items (like Goto Top) */
+ #page_nav_icons {
+ display: none;
+ }
+
+ /* Hide the Create Table form */
+ #create_table_form_minimal {
+ display: none;
+ }
+
+ /* Hide the Page Settings Modal box */
+ #page_settings_modal {
+ display: none;
+ }
+
+ /* Hide footer, Demo notice, errors div */
+ #pma_footer, #pma_demo, #pma_errors {
+ display: none;
+ }
+
+ /* Hide the #selflink div */
+ #selflink {
+ display: none;
+ }
+
+ /* Position the main content */
+ #page_content {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 95%;
+ float: none;
+ }
+
+ /* Specific Class for overriding while Print */
+ .print {
+ background-color: #000;
+ }
+
+ /* For the Success message div */
+ div.success {
+ width: 80%;
+ background-color: #fff;
+ }
+
+ .sqlOuter {
+ color: black;
+ background-color: #000;
+ }
+
+ /* For hiding 'Open a New phpMyAdmin Window' button */
+ .ic_window-new, .ic_s_cog {
+ display: none;
+ }
+
+ .sticky_columns tr {
+ display: none;
+ }
+
+ #structure-action-links, #addColumns {
+ display: none;
+ }
+
+ /* Hide extra menu on tbl_structure.php */
+ #topmenu2 {
+ display: none;
+ }
+
+ .cDrop, .cEdit, .cList, .cCpy, .cPointer {
+ display: none;
+ }
+
+ /* For Odd-Even contrast */
+ table tr.odd th,
+ table tr.odd td,
+ .odd {
+ background: #fff;
+ }
+
+ table tr.even th,
+ table tr.even td,
+ .even {
+ background: #dfdfdf;
+ }
+
+ .column_attribute {
+ font-size: 100%;
+ }
+}
diff --git a/themes/original/img/b_selboard.png b/themes/original/img/b_selboard.png
deleted file mode 100644
index c54a20fee9..0000000000
--- a/themes/original/img/b_selboard.png
+++ /dev/null
Binary files differ
diff --git a/themes/original/img/s_okay.png b/themes/original/img/s_okay.png
new file mode 100644
index 0000000000..5587dc636a
--- /dev/null
+++ b/themes/original/img/s_okay.png
Binary files differ
diff --git a/themes/original/info.inc.php b/themes/original/info.inc.php
index 28866d6bf3..ce2287a0f8 100644
--- a/themes/original/info.inc.php
+++ b/themes/original/info.inc.php
@@ -12,4 +12,3 @@
*/
$theme_name = 'Original';
$theme_full_version = '2.9';
-?>
diff --git a/themes/original/layout.inc.php b/themes/original/layout.inc.php
index b0f91ac037..cfa1dc0f48 100644
--- a/themes/original/layout.inc.php
+++ b/themes/original/layout.inc.php
@@ -74,29 +74,3 @@ $GLOBALS['cfg']['ThColor'] = '#000000';
$GLOBALS['cfg']['BgOne'] = '#E5E5E5';
// table data row background, alternate
$GLOBALS['cfg']['BgTwo'] = '#D5D5D5';
-
-/**
- * Chart colors
- */
-
- $GLOBALS['cfg']['chartColor'] = array(
- 'gradientIntensity' => 0,
- // The style of the chart title.
- 'titleColor' => '#000000',
- 'titleBgColor' => $GLOBALS['cfg']['ThBackground'],
- // Chart border (0 for no border)
- 'border' => '#CCCCCC',
- // Chart background color.
- 'bgColor' => $GLOBALS['cfg']['BgTwo'],
- // when graph area gradient is used, this is the color of the graph
- // area border
- 'graphAreaColor' => '#D5D9DD',
- // the background color of the inner graph area
- 'graphAreaGradientColor' => $GLOBALS['cfg']['BgOne'],
- // the color of the grid lines in the graph area
- 'gridColor' => '#E6E6E6',
- // the color of the scale and the labels
- 'scaleColor' => '#D5D9DD',
- );
-
-?>
diff --git a/themes/original/sprites.lib.php b/themes/original/sprites.lib.php
index d52bada30e..3a09002296 100644
--- a/themes/original/sprites.lib.php
+++ b/themes/original/sprites.lib.php
@@ -732,4 +732,3 @@ function PMA_sprites()
),
);
}
-?>
diff --git a/themes/pmahomme/css/codemirror.css.php b/themes/pmahomme/css/codemirror.css.php
index f2117a8ca5..8b3944334e 100644
--- a/themes/pmahomme/css/codemirror.css.php
+++ b/themes/pmahomme/css/codemirror.css.php
@@ -14,267 +14,22 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
}
?>
-/* PADDING */
-
-.CodeMirror-lines {
- padding: 4px 0; /* Vertical padding around content */
-}
-.CodeMirror pre {
- padding: 0 4px; /* Horizontal padding of content */
-}
-
-.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
- background-color: white; /* The little square between H and V scrollbars */
-}
-
-/* GUTTER */
-
-.CodeMirror-gutters {
- border-right: 1px solid #ddd;
- background-color: #f7f7f7;
- white-space: nowrap;
-}
-.CodeMirror-linenumbers {}
-.CodeMirror-linenumber {
- padding: 0 3px 0 5px;
- min-width: 20px;
- text-align: right;
- color: #999;
-}
-
-/* CURSOR */
-
-.CodeMirror div.CodeMirror-cursor {
- border-left: 1px solid black;
- z-index: 3;
-}
-/* Shown when moving in bi-directional text */
-.CodeMirror div.CodeMirror-secondarycursor {
- border-left: 1px solid silver;
-}
-.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
- width: auto;
- border: 0;
- background: #7e7;
- z-index: 1;
-}
-/* Can style cursor different in overwrite (non-insert) mode */
-.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
-
-.cm-tab { display: inline-block; }
-
-/* DEFAULT THEME */
-
-.cm-s-default .cm-keyword {color: #708;}
-.cm-s-default .cm-atom {color: #219;}
-.cm-s-default .cm-number {color: #164;}
-.cm-s-default .cm-def {color: #00f;}
-.cm-s-default .cm-variable {color: black;}
-.cm-s-default .cm-variable-2 {color: #05a;}
-.cm-s-default .cm-variable-3 {color: #085;}
-.cm-s-default .cm-property {color: black;}
-.cm-s-default .cm-operator {color: black;}
-.cm-s-default .cm-comment {color: #a50;}
-.cm-s-default .cm-string {color: #a11;}
-.cm-s-default .cm-string-2 {color: #f50;}
-.cm-s-default .cm-meta {color: #555;}
-.cm-s-default .cm-error {color: #f00;}
-.cm-s-default .cm-qualifier {color: #555;}
-.cm-s-default .cm-builtin {color: #30a;}
-.cm-s-default .cm-bracket {color: #997;}
-.cm-s-default .cm-tag {color: #170;}
-.cm-s-default .cm-attribute {color: #00c;}
-.cm-s-default .cm-header {color: blue;}
-.cm-s-default .cm-quote {color: #090;}
-.cm-s-default .cm-hr {color: #999;}
-.cm-s-default .cm-link {color: #00c;}
-
-.cm-negative {color: #d44;}
-.cm-positive {color: #292;}
-.cm-header, .cm-strong {font-weight: bold;}
-.cm-em {font-style: italic;}
-.cm-link {text-decoration: underline;}
-
-.cm-invalidchar {color: #f00;}
-
-div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
-div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
-
-/* STOP */
-
-/* The rest of this file contains styles related to the mechanics of
- the editor. You probably shouldn't touch them. */
-
.CodeMirror {
- line-height: 1;
- position: relative;
- overflow: hidden;
- background: white;
- color: black;
- font-family: monospace;
- height: <?php echo ceil($GLOBALS['cfg']['TextareaRows'] * 1.2); ?>em;
- resize: vertical;
- max-height: 600px;
- min-height: 75px;
+ height: <?php echo ceil($GLOBALS['cfg']['TextareaRows'] * 1.2); ?>em;
+ direction: ltr;
}
-
#inline_editor_outer .CodeMirror {
height: <?php echo ceil($GLOBALS['cfg']['TextareaRows'] * 0.4); ?>em;
}
-
-.CodeMirror-scroll {
- /* 30px is the magic margin used to hide the element's real scrollbars */
- /* See overflow: hidden in .CodeMirror */
- height: 85% !important;
- outline: none; /* Prevent dragging from highlighting the element */
- resize: none;
- overflow-y: auto;
-}
-.CodeMirror-sizer {
- position: relative;
-}
-
-/* The fake, visible scrollbars. Used to force redraw during scrolling
- before actuall scrolling happens, thus preventing shaking and
- flickering artifacts. */
-.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
- position: absolute;
- z-index: 6;
- display: none;
-}
-.CodeMirror-vscrollbar {
- right: 0; top: 0;
- overflow-x: hidden;
- overflow-y: scroll;
- display:none !important;
-}
-.CodeMirror-hscrollbar {
- bottom: 0; left: 0;
- overflow-y: hidden;
- overflow-x: scroll;
-}
-.CodeMirror-scrollbar-filler {
- right: 0; bottom: 0;
-}
-.CodeMirror-gutter-filler {
- left: 0; bottom: 0;
-}
-
-.CodeMirror-gutters {
- position: absolute; left: 0; top: 0;
- padding-bottom: 30px;
- z-index: 3;
- height: 100% !important;
-}
-.CodeMirror-gutter {
- white-space: normal;
- height: 100%;
- padding-bottom: 30px;
- margin-bottom: -32px;
- display: inline-block;
- /* Hack to make IE7 behave */
- *zoom:1;
- *display:inline;
-}
-.CodeMirror-gutter-wrapper {
- position: relative;
+.insertRowTable .CodeMirror {
+ height: <?php echo ceil($GLOBALS['cfg']['TextareaRows'] * 0.6); ?>em;
+ width: <?php echo ceil($GLOBALS['cfg']['TextareaCols'] * 0.6); ?>em;
+ border: 1px solid #a9a9a9;
}
-.CodeMirror-gutter-elt {
- position: absolute;
- cursor: default;
- z-index: 4;
+#pma_console .CodeMirror-gutters {
+ background-color: initial;
+ border: none;
}
-
-.CodeMirror-lines {
- cursor: text;
-}
-.CodeMirror pre {
- /* Reset some styles that the rest of the page might have set */
- -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
- border-width: 0;
- background: transparent;
- font-family: inherit;
- font-size: inherit;
- margin: 0;
- white-space: pre;
- word-wrap: normal;
- line-height: inherit;
- color: inherit;
- z-index: 2;
- position: relative;
- overflow: visible;
-}
-.CodeMirror-wrap pre {
- word-wrap: break-word;
- white-space: pre-wrap;
- word-break: normal;
-}
-.CodeMirror-code pre {
- border-right: 30px solid transparent;
- width: -webkit-fit-content;
- width: -moz-fit-content;
- width: fit-content;
-}
-.CodeMirror-wrap .CodeMirror-code pre {
- border-right: none;
- width: auto;
-}
-.CodeMirror-linebackground {
- position: absolute;
- left: 0; right: 0; top: 0; bottom: 0;
- z-index: 0;
-}
-
-.CodeMirror-linewidget {
- position: relative;
- z-index: 2;
- overflow: auto;
-}
-
-.CodeMirror-widget {
- display: inline-block;
-}
-
-.CodeMirror-wrap .CodeMirror-scroll {
- overflow-x: hidden;
-}
-
-.CodeMirror-measure {
- position: absolute;
- width: 100%; height: 0px;
- overflow: hidden;
- visibility: hidden;
-}
-.CodeMirror-measure pre { position: static; }
-
-.CodeMirror div.CodeMirror-cursor {
- position: absolute;
- visibility: hidden;
- border-right: none;
- width: 0;
-}
-.CodeMirror-focused div.CodeMirror-cursor {
- visibility: visible;
-}
-
-.CodeMirror-selected { background: #d9d9d9; }
-.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
-
-.cm-searching {
- background: #ffa;
- background: rgba(255, 255, 0, .4);
-}
-
-/* IE7 hack to prevent it from returning funny offsetTops on the spans */
-.CodeMirror span { *vertical-align: text-bottom; }
-
-@media print {
- /* Hide the cursor when printing */
- .CodeMirror div.CodeMirror-cursor {
- visibility: hidden;
- }
-}
-
span.cm-keyword, span.cm-statement-verb {
color: #909;
}
@@ -308,43 +63,15 @@ span.cm-separator {
span.cm-number {
color: teal;
}
-
-/* CodeMirror Hints styling */
-.CodeMirror-hints {
- position: absolute;
- z-index: 2000;
- overflow: hidden;
- list-style: none;
-
- margin: 0;
- padding: 2px;
-
- -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
- -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
- box-shadow: 2px 3px 5px rgba(0,0,0,.2);
- border-radius: 3px;
- border: 1px solid silver;
-
- background: white;
- font-size: 90%;
- font-family: monospace;
-
- max-height: 20em;
- overflow-y: auto;
+.autocomplete-column-name {
+ display: inline-block;
}
-
-.CodeMirror-hint {
- margin: 0;
- padding: 0 4px;
- border-radius: 2px;
- max-width: 19em;
- overflow: hidden;
- white-space: pre;
- color: black;
- cursor: pointer;
-}
-
-li.CodeMirror-hint-active {
- background: #08f;
- color: white;
+.autocomplete-column-hint {
+ display: inline-block;
+ float: right;
+ color: #666;
+ margin-left: 1em;
}
+.CodeMirror-hints {
+ z-index: 200;
+} \ No newline at end of file
diff --git a/themes/pmahomme/css/common.css.php b/themes/pmahomme/css/common.css.php
index 46d4ac1eca..07d2540e68 100644
--- a/themes/pmahomme/css/common.css.php
+++ b/themes/pmahomme/css/common.css.php
@@ -42,7 +42,7 @@ body#loginform {
margin: 0;
}
-#page_content, #session_debug {
+#page_content {
margin: 0 .5em;
}
@@ -325,12 +325,10 @@ input.button:disabled {
textarea {
overflow: visible;
margin: 6px;
- height: <?php echo ceil($GLOBALS['cfg']['TextareaRows'] * 1.2); ?>em;
}
textarea.char {
margin: 6px;
- height: <?php echo ceil($GLOBALS['cfg']['CharTextareaRows'] * 1.2); ?>em;
}
fieldset, .preview_sql {
@@ -471,6 +469,7 @@ th.center, td.center {
th.right, td.right {
text-align: right;
+ padding-right: 1em;
}
tr.vtop th, tr.vtop td, th.vtop, td.vtop {
@@ -895,6 +894,7 @@ form.login label {
form.login input[type=text],
form.login input[type=password],
form.login select {
+ box-sizing: border-box;
width: 14em;
}
@@ -1140,20 +1140,30 @@ div#tablestatistics table {
color: #fff;
}
-#goto_pagetop, #lock_page_icon {
+#page_nav_icons {
position: fixed;
- padding: .25em .25em .2em;
top: 0;
+ <?php echo $right; ?>: 0;
z-index: 99;
+ padding: .25em 0;
+}
+
+#goto_pagetop, #lock_page_icon, #page_settings_icon {
+ padding: .25em;
background: #888;
}
-#goto_pagetop {
- <?php echo $right; ?>: 0;
+#page_settings_icon {
+ cursor: pointer;
+ display: none;
+}
+
+#page_settings_modal {
+ display: none;
}
-#lock_page_icon {
- <?php echo $right; ?>: 2em;
+#pma_navigation_settings {
+ display: none;
}
#span_table_comment {
@@ -1364,7 +1374,7 @@ table#chartGrid div.monitorChart {
div.tabLinks {
margin-left: 0.3em;
float: <?php echo $left; ?>;
- padding: 5px 0px;
+ padding: 5px 0;
}
div.tabLinks a, div.tabLinks label {
@@ -1372,7 +1382,7 @@ div.tabLinks a, div.tabLinks label {
}
div.tabLinks .icon {
- margin: -0.2em 0.3em 0px 0px;
+ margin: -0.2em 0.3em 0 0;
}
.popupContent {
@@ -1547,14 +1557,16 @@ div#profilingchart {
/* end profiling */
/* table charting */
-
#resizer {
border: 1px solid silver;
}
#inner-resizer { /* make room for the resize handle */
padding: 10px;
}
-
+.chartOption {
+ float: <?php echo $left; ?>;
+ margin-<?php echo $right;?>: 40px;
+}
/* end table charting */
/* querybox */
@@ -1621,6 +1633,7 @@ div#sqlquerycontainer {
div#tablefieldscontainer {
float: <?php echo $right; ?>;
width: 29%;
+ margin-top: -20px;
/* height: 15em; */
}
@@ -1797,6 +1810,7 @@ div.sqlvalidate {
margin-bottom: 0;
max-height: 10em;
overflow: auto;
+ direction: ltr;
}
.result_query div.sqlOuter {
@@ -1984,6 +1998,30 @@ select.invalid_value,
* Export and Import styles
*/
+.export_table_list_container {
+ display: inline-block;
+ max-height: 20em;
+ overflow-y: scroll;
+}
+
+.export_table_select th {
+ text-align: center;
+ vertical-align: middle;
+}
+
+.export_table_select .all {
+ font-weight: bold;
+ border-bottom: 1px solid black;
+}
+
+.export_structure, .export_data {
+ text-align: center;
+}
+
+.export_table_name {
+ vertical-align: middle;
+}
+
.exportoptions h3,
.importoptions h3 {
border-bottom: 1px #999 solid;
@@ -2461,6 +2499,7 @@ fieldset .disabled-field td {
#prefs_autoload {
margin-bottom: .5em;
+ margin-left: .5em;
}
#placeholder .button {
@@ -2533,6 +2572,17 @@ fieldset .disabled-field td {
padding: 1.5em;
}
+#table_name_col_no_outer {
+ margin-top: 45px;
+}
+
+#table_name_col_no {
+ position: fixed;
+ top: 55px;
+ width: 100%;
+ background: #ffffff;
+}
+
#table_columns input[type="text"],
#table_columns input[type="password"],
#table_columns input[type="number"],
@@ -2893,7 +2943,7 @@ body .ui-widget {
/* over-riding jqplot-yaxis class */
.jqplot-yaxis {
- left:0px !important;
+ left:0 !important;
min-width:25px;
width:auto;
}
@@ -2975,7 +3025,7 @@ table.show_create td {
position: relative;
margin-<?php echo $left; ?>: 240px;
}
-#pma_console>.templates {
+#pma_console .templates {
display: none;
}
#pma_console .mid_text,
@@ -3002,6 +3052,7 @@ table.show_create td {
#pma_console .message span.text,
#pma_console .message span.action,
#pma_console .toolbar .button,
+#pma_console .toolbar .text,
#pma_console .switch_button {
padding: 0 3px;
display: inline-block;
@@ -3013,13 +3064,19 @@ table.show_create td {
}
#pma_console .message span.action:hover,
#pma_console .toolbar .button:hover,
-#pma_console .switch_button:hover {
+#pma_console .switch_button:hover,
+#pma_console .toolbar .button.active {
background: #ddd;
}
-#pma_console .toolbar .button {
+#pma_console .toolbar .text {
+ font-weight: bold;
+}
+#pma_console .toolbar .button,
+#pma_console .toolbar .text {
margin-<?php echo $right; ?>: .4em;
}
-#pma_console .toolbar .button {
+#pma_console .toolbar .button,
+#pma_console .toolbar .text {
float: <?php echo $right; ?>;
}
#pma_console .content {
@@ -3030,6 +3087,26 @@ table.show_create td {
background: #fff;
padding-top: .4em;
}
+#pma_console .content.console_dark_theme {
+ background: #000;
+ color: #fff;
+}
+#pma_console .content.console_dark_theme .CodeMirror-wrap {
+ background: #000;
+ color: #fff;
+}
+#pma_console .content.console_dark_theme .action_content {
+ color: #000;
+}
+#pma_console .content.console_dark_theme .message {
+ border-color: #373B41;
+}
+#pma_console .content.console_dark_theme .CodeMirror-cursor {
+ border-color: #fff;
+}
+#pma_console .content.console_dark_theme .cm-keyword {
+ color: #de935f;
+}
#pma_console .message,
#pma_console .query_input {
position: relative;
@@ -3041,7 +3118,7 @@ table.show_create td {
border-bottom: solid 1px #ccc;
padding-bottom: .2em;
}
-#pma_console .message.expanded .action_content {
+#pma_console .message.expanded>.action_content {
position: relative;
}
#pma_console .message:before,
@@ -3133,9 +3210,12 @@ html.ie8 #pma_console .message .action_content {
#pma_console .message .text {
background: #fff;
}
-#pma_console .message.collapsed:not(:hover) .action_content {
+#pma_console .message.collapsed>.action_content {
display: none;
}
+#pma_console .message.collapsed:hover>.action_content {
+ display: block;
+}
#pma_console .message .bookmark_label {
padding: 0 4px;
top: 0;
@@ -3206,6 +3286,55 @@ html.ie7 #pma_console .query_input {
margin: 0;
padding: 2px 4px;
}
+#pma_console .button.hide,
+#pma_console .message span.text.hide {
+ display: none;
+}
+#debug_console.grouped .ungroup_queries,
+#debug_console.ungrouped .group_queries {
+ display: inline-block;
+}
+#debug_console.ungrouped .ungroup_queries,
+#debug_console.ungrouped .sort_count,
+#debug_console.grouped .group_queries {
+ display: none;
+}
+#debug_console .count {
+ margin-right: 8px;
+}
+#debug_console .show_trace .trace,
+#debug_console .show_args .args {
+ display: block;
+}
+#debug_console .hide_trace .trace,
+#debug_console .hide_args .args,
+#debug_console .show_trace .action.dbg_show_trace,
+#debug_console .hide_trace .action.dbg_hide_trace,
+#debug_console .traceStep.hide_args .action.dbg_hide_args,
+#debug_console .traceStep.show_args .action.dbg_show_args {
+ display: none;
+}
+
+#debug_console .traceStep:after,
+#debug_console .trace.welcome:after,
+#debug_console .debug>.welcome:after {
+ content: "";
+ display: table;
+ clear: both;
+}
+#debug_console .debug_summary {
+ float: left;
+}
+#debug_console .trace.welcome .time {
+ float: right;
+}
+#debug_console .traceStep .file,
+#debug_console .script_name {
+ float: right;
+}
+#debug_console .traceStep .args pre {
+ margin: 0;
+}
/* Code mirror console style*/
@@ -3229,7 +3358,6 @@ html.ie7 #pma_console .query_input {
font-size: 120%;
}
.cm-s-pma .CodeMirror-scroll {
- padding-bottom: 2em;
cursor: text;
}
@@ -3238,8 +3366,8 @@ html.ie7 #pma_console .query_input {
.pma_drop_handler {
display: none;
position: fixed;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
width: 100%;
background: rgba(0, 0, 0, 0.6);
height: 100%;
@@ -3253,7 +3381,7 @@ html.ie7 #pma_console .query_input {
.pma_sql_import_status {
display: none;
position: fixed;
- bottom: 0px;
+ bottom: 0;
right: 25px;
width: 400px;
border: 1px solid #999;
@@ -3302,13 +3430,13 @@ html.ie7 #pma_console .query_input {
.pma_sql_import_status h2 .minimize {
float: right;
margin-right: 5px;
- padding: 0px 10px;
+ padding: 0 10px;
}
.pma_sql_import_status h2 .close {
float: right;
margin-right: 5px;
- padding: 0px 10px;
+ padding: 0 10px;
display: none;
}
@@ -3336,7 +3464,7 @@ html.ie7 #pma_console .query_input {
background: white;
min-height: 300px;
z-index: 800;
- -webkit-box-shadow: 0px 0px 15px #999;
+ -webkit-box-shadow: 0 0 15px #999;
border-radius: 10px;
cursor: move;
}
@@ -3344,7 +3472,7 @@ html.ie7 #pma_console .query_input {
.pma_drop_result h2 .close {
float: right;
margin-right: 5px;
- padding: 0px 10px;
+ padding: 0 10px;
}
.dependencies_box {
@@ -3399,3 +3527,18 @@ th.headerSortDown .sorticon, th.headerSortUp:hover .sorticon {
background-image: url(<?php echo $_SESSION['PMA_Theme']->getImgPath('s_asc.png');?>);
}
/* end of styles of sortable tables */
+
+/* styles for jQuery-ui to support rtl languages */
+body .ui-dialog .ui-dialog-titlebar-close {
+ <?php echo $right; ?>: .3em;
+ <?php echo $left; ?>: initial;
+}
+
+body .ui-dialog .ui-dialog-title {
+ float: <?php echo $left; ?>;
+}
+
+body .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: <?php echo $right; ?>;
+}
+/* end of styles for jQuery-ui to support rtl languages */ \ No newline at end of file
diff --git a/themes/pmahomme/css/jqplot.css.php b/themes/pmahomme/css/jqplot.css.php
index b445927625..1fc4329bb7 100644
--- a/themes/pmahomme/css/jqplot.css.php
+++ b/themes/pmahomme/css/jqplot.css.php
@@ -56,18 +56,16 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
.jqplot-xaxis-tick {
- top: 0px;
+ top: 0;
/* initial position untill tick is drawn in proper place */
<?php echo $left; ?>: 15px;
-/* padding-top: 10px;*/
vertical-align: top;
}
.jqplot-x2axis-tick {
- bottom: 0px;
+ bottom: 0;
/* initial position untill tick is drawn in proper place */
<?php echo $left; ?>: 15px;
-/* padding-bottom: 10px;*/
vertical-align: bottom;
}
@@ -75,15 +73,13 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
<?php echo $right; ?>: 0px;
/* initial position untill tick is drawn in proper place */
top: 15px;
-/* padding-right: 10px;*/
text-align: <?php echo $right; ?>;
}
.jqplot-yaxis-tick.jqplot-breakTick {
<?php echo $right; ?>: -20px;
- margin-<?php echo $right; ?>: 0px;
+ margin-<?php echo $right; ?>: 0;
padding:1px 5px 1px;
-/* background-color: white;*/
z-index: 2;
font-size: 1.5em;
}
@@ -204,7 +200,7 @@ div.jqplot-table-legend-swatch {
}
.jqplot-title {
- top: 0px;
+ top: 0;
<?php echo $left; ?>: 0px;
padding-bottom: 0.5em;
font-size: 1.2em;
diff --git a/themes/pmahomme/css/navigation.css.php b/themes/pmahomme/css/navigation.css.php
index 2d4a6f8271..de0078d5c4 100644
--- a/themes/pmahomme/css/navigation.css.php
+++ b/themes/pmahomme/css/navigation.css.php
@@ -22,7 +22,7 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
top: 0;
<?php echo $left; ?>: 0;
height: 100%;
- background: url(./themes/pmahomme/img/left_nav_bg.png) repeat-y right 0% <?php echo $GLOBALS['cfg']['NaviBackground']; ?>;
+ background: url(./themes/pmahomme/img/left_nav_bg.png) repeat-y right 0 <?php echo $GLOBALS['cfg']['NaviBackground']; ?>;
color: <?php echo $GLOBALS['cfg']['NaviColor']; ?>;
z-index: 800;
}
@@ -77,7 +77,7 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
#pma_navigation #databaseList,
#pma_navigation div.pageselector.dbselector {
text-align: center;
- padding: 5px 10px 0px;
+ padding: 5px 10px 0;
border: 0;
}
@@ -108,7 +108,7 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
}
#pma_navigation_select_database {
text-align: left;
- padding: 0px 0px 0px;
+ padding: 0 0 0;
border: 0;
margin: 0;
}
@@ -125,7 +125,7 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
border-top: 1px solid #bbb;
color: #333;
padding: 4px 6px;
- margin: 0px 0px 0px;
+ margin: 0 0 0;
width: 92%;
font-size: 1.11em;
}
@@ -318,7 +318,7 @@ html.ie.ie8 li.fast_filter input {
}
li.fast_filter.db_fast_filter {
border: 0;
- margin-left: 0px;
+ margin-left: 0;
margin-right: 10px;
}
@@ -359,7 +359,7 @@ li.fast_filter.db_fast_filter {
text-align: center;
cursor: pointer;
z-index: 800;
- text-shadow: 0px 1px 0px #fff;
+ text-shadow: 0 1px 0 #fff;
filter: dropshadow(color=#fff, offx=0, offy=1);
border: 1px solid #888;
}
diff --git a/themes/pmahomme/css/pmd.css.php b/themes/pmahomme/css/pmd.css.php
index 1a9b70ccc7..0e1e9101d4 100644
--- a/themes/pmahomme/css/pmd.css.php
+++ b/themes/pmahomme/css/pmd.css.php
@@ -351,7 +351,7 @@ a.M_butt:hover {
}
#layer_menu {
- z-index: 50;
+ z-index: 98;
position: relative;
float: right;
background-color: #EAEEF0;
@@ -387,7 +387,7 @@ a.M_butt:hover {
#layer_menu_sizer {
background-image: url(<?php echo $resizeImg; ?>);
- cursor: e-resize;
+ cursor: ew-resize;
}
#layer_menu_sizer .icon {
@@ -398,15 +398,11 @@ a.M_butt:hover {
position: fixed;
top: 60px;
<?php echo $right; ?>: 0;
- display: none;
- background: #FFF;
- border: 1px solid gray;
- width: 350 px;
+ width: 350px;
max-height: 500px;
- overflow:scroll;
- padding: 30px;
- padding-<?php echo $left; ?>: 30px;
- color: #FFF;
+ display: none;
+ overflow: auto;
+ padding-top: 34px;
z-index: 102;
}
@@ -438,58 +434,15 @@ a.active.trigger:hover {
background: #fff696 url(<?php echo $minusImg; ?>) 85% 55% no-repeat;
}
-h2.tiger {
- background-repeat: repeat-x;
- padding: 1px;
- font-weight: bold;
- padding: 50px 20px 50px;
- margin: 0 0 5px 0;
- width: 250px;
- float: <?php echo $left; ?>;
- color : #333;
- text-align: center;
-}
-
-h2.tiger a {
- background-image: url(<?php echo $headerImg; ?>);
- text-align: center;
- text-decoration: none;
- color : #333;
- display: block;
-}
-
-h2.tiger a:hover {
- color: #000;
- background-image: url(<?php echo $headerLinkedImg; ?>);
-}
-
-h2.active {
- background-image: url(<?php echo $headerImg ?>);
- background-repeat: repeat-x;
- padding: 1px;
- background-position: left bottom;
-}
-
-.toggle_container {
- margin: 0 0 5px;
- padding: 0;
- border-top: 1px solid #d6d6d6;
- background: #FFF;
- overflow: hidden;
- font-size: 1.2em;
- clear: both;
-}
-
.toggle_container .block {
background-color: #DBE4E8;
- padding: 40px 15px 40px 15px; /*--Padding of Container--*/
- border:1px solid #999;
- color: #000;
+ border-top: 1px solid #999;
}
.history_table {
text-align: center;
background-color: #9999CC;
+ cursor: pointer;
}
.history_table2 {
@@ -497,58 +450,16 @@ h2.active {
background-color: #DBE4E8;
}
-#filter {
- display: none;
- position: absolute;
- top: 0%;
- left: 0%;
- width: 100%;
- height: 100%;
- background-color: #CCA;
- z-index: 10;
- opacity: .5;
- filter: alpha(opacity=50);
-}
-
-#box {
- display: none;
- position: absolute;
- top: 20%;
- <?php echo $left; ?>: 30%;
- width: 500px;
- height: 220px;
- padding: 48px;
- margin: 0;
- border: 1px solid #000;
- background-color: #fff;
- z-index: 101;
- overflow: visible;
+#ab {
+ min-width: 300px;
}
-#boxtitle {
- position: absolute;
- float: center;
- top: 0;
- <?php echo $left; ?>: 0;
- width: 593px;
- height: 20px;
+#ab .ui-accordion-content {
padding: 0;
- padding-top: 4px;
- margin: 0;
- border-bottom: 4px solid #3CF;
- background-color: #D0DCE0;
- color: black;
- font-weight: bold;
- padding-<?php echo $left; ?>: 2px;
- text-align: <?php echo $left; ?>;
}
-#tblfooter {
- background-color: #D3DCE3;
- float: <?php echo $right; ?>;
- padding-top: 10px;
- color: black;
- font-weight: normal;
+#box {
+ display: none;
}
#foreignkeychk {
@@ -559,7 +470,7 @@ h2.active {
.side-menu {
float: left;
- position: relative;
+ position: fixed;
width: auto;
height: auto;
background: #efefef;
@@ -571,6 +482,7 @@ h2.active {
.side-menu.right {
float: right;
+ right: 0;
}
.side-menu .hide {
diff --git a/themes/pmahomme/css/printview.css b/themes/pmahomme/css/printview.css
new file mode 100644
index 0000000000..5ee47195e2
--- /dev/null
+++ b/themes/pmahomme/css/printview.css
@@ -0,0 +1,168 @@
+@media print {
+
+ /* For removing element from Print View */
+ .print_ignore {
+ display: none;
+ }
+
+ .nowrap {
+ white-space: nowrap;
+ }
+
+ .hide {
+ display: none;
+ }
+
+ /* Standard CSS */
+ body, table, th, td {
+ color: #000;
+ background-color: #fff;
+ font-size: 12px;
+ }
+
+ /* To remove link text decoration */
+ a:link {
+ color:#000;
+ text-decoration:none
+ }
+
+ /* To remove any image borders */
+ img {
+ border: 0;
+ }
+
+ /* Table specific */
+ table, th, td {
+ border: .1em solid #000;
+ background-color: #fff;
+ }
+
+ table {
+ border-collapse: collapse;
+ border-spacing: 0.2em;
+ }
+
+ thead {
+ border-collapse: collapse;
+ border-spacing: 0.2em;
+ border: .1em solid #000;
+ font-weight: 900;
+ }
+
+ th, td {
+ padding: 0.2em;
+ }
+
+ thead th {
+ font-weight: bold;
+ background-color: #e5e5e5;
+ border: .1em solid #000;
+ }
+
+ th.vtop, td.vtop {
+ vertical-align: top;
+ }
+
+ th.vbottom, td.vbottom {
+ vertical-align: bottom;
+ }
+
+ /* Common Elements not to be included */
+ /* Hide Navigation and Top Menu bar */
+ #pma_navigation, #floating_menubar {
+ display: none;
+ }
+ /* Hide console */
+ #pma_console_container {
+ display: none;
+ }
+
+ /* Hide Navigation items (like Goto Top) */
+ #page_nav_icons {
+ display: none;
+ }
+
+ /* Hide the Create Table form */
+ #create_table_form_minimal {
+ display: none;
+ }
+
+ /* Hide the Page Settings Modal box */
+ #page_settings_modal {
+ display: none;
+ }
+
+ /* Hide footer, Demo notice, errors div */
+ #pma_footer, #pma_demo, #pma_errors {
+ display: none;
+ }
+
+ /* Hide the #selflink div */
+ #selflink {
+ display: none;
+ }
+
+ /* Position the main content */
+ #page_content {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 95%;
+ float: none;
+ }
+
+ /* Specific Class for overriding while Print */
+ .print {
+ background-color: #000;
+ }
+
+ /* For the Success message div */
+ div.success {
+ width: 80%;
+ background-color: #fff;
+ }
+
+ .sqlOuter {
+ color: black;
+ background-color: #000;
+ }
+
+ /* For hiding 'Open a New phpMyAdmin Window' button */
+ .ic_window-new, .ic_s_cog {
+ display: none;
+ }
+
+ .sticky_columns tr {
+ display: none;
+ }
+
+ #structure-action-links, #addColumns {
+ display: none;
+ }
+
+ /* Hide extra menu on tbl_structure.php */
+ #topmenu2 {
+ display: none;
+ }
+
+ .cDrop, .cEdit, .cList, .cCpy, .cPointer {
+ display: none;
+ }
+
+ /* For Odd-Even contrast */
+ table tr.odd th,
+ table tr.odd td,
+ .odd {
+ background: #fff;
+ }
+
+ table tr.even th,
+ table tr.even td,
+ .even {
+ background: #dfdfdf;
+ }
+
+ .column_attribute {
+ font-size: 100%;
+ }
+}
diff --git a/themes/pmahomme/css/rte.css.php b/themes/pmahomme/css/rte.css.php
index 0db21a805c..55d7832e9a 100644
--- a/themes/pmahomme/css/rte.css.php
+++ b/themes/pmahomme/css/rte.css.php
@@ -38,6 +38,12 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) {
-webkit-box-sizing: border-box;
}
+.rte_table input[type=checkbox],
+.rte_table input[type=radio] {
+ width: auto;
+ margin-right: 6px;
+}
+
.rte_table .routine_params_table {
width: 100%;
}
diff --git a/themes/pmahomme/img/b_selboard.png b/themes/pmahomme/img/b_selboard.png
deleted file mode 100644
index 3caa94971b..0000000000
--- a/themes/pmahomme/img/b_selboard.png
+++ /dev/null
Binary files differ
diff --git a/themes/pmahomme/info.inc.php b/themes/pmahomme/info.inc.php
index 0c32532d17..cd47da6d19 100644
--- a/themes/pmahomme/info.inc.php
+++ b/themes/pmahomme/info.inc.php
@@ -18,4 +18,3 @@
$theme_name = 'pmahomme';
$theme_full_version = '1.1';
-?>
diff --git a/themes/pmahomme/layout.inc.php b/themes/pmahomme/layout.inc.php
index 2822b678c7..ccb8c1194d 100644
--- a/themes/pmahomme/layout.inc.php
+++ b/themes/pmahomme/layout.inc.php
@@ -75,30 +75,3 @@ $GLOBALS['cfg']['ThColor'] = '#000';
$GLOBALS['cfg']['BgOne'] = '#E5E5E5';
// table data row background, alternate
$GLOBALS['cfg']['BgTwo'] = '#D5D5D5';
-
-/**
- * Chart colors
- */
-
- $GLOBALS['cfg']['chartColor'] = array(
- 'gradientIntensity' => 50,
- // The style of the chart title.
- 'titleColor' => '#000',
- 'titleBgColor' => '#E5E5E5',
- // Chart border (0 for no border)
- 'border' => '#ccc',
- // Chart background color.
- 'bgColor' => '#FBFBFB',
- // when graph area gradient is used, this is the color of the graph
- // area border
- 'graphAreaColor' => '#D5D9DD',
- // the background color of the graph area
- 'graphAreaGradientColor' => $GLOBALS['cfg']['BgTwo'],
- // the color of the grid lines in the graph area
- 'gridColor' => '#E6E6E6',
- // the color of the scale and the labels
- 'scaleColor' => '#D5D9DD',
-
- );
-
-?>
diff --git a/themes/pmahomme/sprites.lib.php b/themes/pmahomme/sprites.lib.php
index 1e02829d98..56ea19049e 100644
--- a/themes/pmahomme/sprites.lib.php
+++ b/themes/pmahomme/sprites.lib.php
@@ -817,4 +817,3 @@ function PMA_sprites()
),
);
}
-?>
diff --git a/themes/sprites.css.php b/themes/sprites.css.php
index 58a33f7edf..f458077eea 100644
--- a/themes/sprites.css.php
+++ b/themes/sprites.css.php
@@ -11,7 +11,7 @@ if (! defined('PMA_MINIMUM_COMMON')) {
exit();
}
-$bg = $_SESSION['PMA_Theme']->getImgPath() . 'sprites.png';
+$bg = $_SESSION['PMA_Theme']->getImgPath() . 'sprites.png?v=' . urlencode(PMA_VERSION);
/* Check if there is a valid data file for sprites */
if (is_readable($_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php')) {
diff --git a/transformation_overview.php b/transformation_overview.php
index 5bd19bf1a1..8a3450d2ba 100644
--- a/transformation_overview.php
+++ b/transformation_overview.php
@@ -71,4 +71,3 @@ $th = array(
</table>
<?php
} // End of foreach ($transformation_types)
-?>
diff --git a/transformation_wrapper.php b/transformation_wrapper.php
index ac0b04973d..69b9f3ed5f 100644
--- a/transformation_wrapper.php
+++ b/transformation_wrapper.php
@@ -145,4 +145,3 @@ if (! isset($_REQUEST['resize'])) {
ImageDestroy($srcImage);
ImageDestroy($destImage);
}
-?>
diff --git a/url.php b/url.php
index 82b224311b..eec78a52b1 100644
--- a/url.php
+++ b/url.php
@@ -16,9 +16,9 @@ require_once './libraries/common.inc.php';
*/
require_once './libraries/js_escape.lib.php';
-if (! PMA_isValid($_GET['url'])
- || ! preg_match('/^https?:\/\/[^\n\r]*$/', $_GET['url'])
- || ! PMA_isAllowedDomain($_GET['url'])
+if (! PMA_isValid($_REQUEST['url'])
+ || ! preg_match('/^https?:\/\/[^\n\r]*$/', $_REQUEST['url'])
+ || ! PMA_isAllowedDomain($_REQUEST['url'])
) {
header('Location: ' . $cfg['PmaAbsoluteUri']);
} else {
@@ -28,11 +28,10 @@ if (! PMA_isValid($_GET['url'])
// external site.
echo "<script type='text/javascript'>
window.onload=function(){
- window.location='" . PMA_escapeJsString($_GET['url']) . "';
+ window.location='" . PMA_escapeJsString($_REQUEST['url']) . "';
}
</script>";
// Display redirecting msg on screen.
- printf(__('Taking you to %s.'), htmlspecialchars($_GET['url']));
+ printf(__('Taking you to %s.'), htmlspecialchars($_REQUEST['url']));
}
die();
-?>
diff --git a/user_password.php b/user_password.php
index c9313fc500..71e5b4e3ce 100644
--- a/user_password.php
+++ b/user_password.php
@@ -12,6 +12,11 @@
*/
require_once './libraries/common.inc.php';
+/**
+ * Libraries needed for some functions
+ */
+require_once './libraries/server_privileges.lib.php';
+
$response = PMA_Response::getInstance();
$header = $response->getHeader();
$scripts = $header->getScripts();
@@ -62,6 +67,7 @@ if (isset($msg)) {
}
require_once './libraries/display_change_password.lib.php';
+
echo PMA_getHtmlForChangePassword($username, $hostname);
exit;
@@ -131,10 +137,48 @@ function PMA_changePassword($password, $message, $change_password_message)
global $auth_plugin;
$hashing_function = PMA_changePassHashingFunction();
- $sql_query = 'SET password = '
- . (($password == '') ? '\'\'' : $hashing_function . '(\'***\')');
+
+ $orig_auth_plugin = null;
+
+ $row = $GLOBALS['dbi']->fetchSingleRow('SELECT CURRENT_USER() as user');
+ $curr_user = $row['user'];
+ list($username, $hostname) = explode('@', $curr_user);
+
+ if (PMA_Util::getServerType() === 'MySQL' && PMA_MYSQL_INT_VERSION >= 50706) {
+
+ if (isset($_REQUEST['pw_hash']) && ! empty($_REQUEST['pw_hash'])) {
+ $orig_auth_plugin = $_REQUEST['pw_hash'];
+ } else {
+ $orig_auth_plugin = PMA_getCurrentAuthenticationPlugin(
+ 'change', $username, $hostname
+ );
+ }
+
+ $sql_query = 'ALTER USER \'' . $username . '\'@\'' . $hostname
+ . '\' IDENTIFIED WITH ' . $orig_auth_plugin . ' BY '
+ . (($password == '') ? '\'\'' : '\'***\'');
+ } else {
+ // For MySQL versions 5.6.6+,
+ // explicitly set value of `old_passwords` so that
+ // it does not give an error while using
+ // the PASSWORD() function
+ if (PMA_MYSQL_INT_VERSION >= 50606) {
+ $orig_auth_plugin = PMA_getCurrentAuthenticationPlugin(
+ 'change', $username, $hostname
+ );
+ if ($orig_auth_plugin == 'sha256_password') {
+ $value = 2;
+ } else {
+ $value = 0;
+ }
+ $GLOBALS['dbi']->tryQuery('SET `old_passwords` = ' . $value . ';');
+ }
+ $sql_query = 'SET password = '
+ . (($password == '') ? '\'\'' : $hashing_function . '(\'***\')');
+ }
PMA_changePassUrlParamsAndSubmitQuery(
- $password, $sql_query, $hashing_function
+ $username, $hostname, $password,
+ $sql_query, $hashing_function, $orig_auth_plugin
);
$auth_plugin->handlePasswordChange($password);
@@ -160,19 +204,31 @@ function PMA_changePassHashingFunction()
/**
* Generate the error url and submit the query
*
+ * @param string $username Username
+ * @param string $hostname Hostname
* @param string $password Password
* @param string $sql_query SQL query
* @param string $hashing_function Hashing function
+ * @param string $auth_plugin Authentication Plugin
*
* @return void
*/
function PMA_changePassUrlParamsAndSubmitQuery(
- $password, $sql_query, $hashing_function
+ $username, $hostname, $password, $sql_query, $hashing_function, $auth_plugin
) {
$err_url = 'user_password.php' . PMA_URL_getCommon();
- $local_query = 'SET password = ' . (($password == '')
- ? '\'\''
- : $hashing_function . '(\'' . PMA_Util::sqlAddSlashes($password) . '\')');
+ if (PMA_Util::getServerType() === 'MySQL' && PMA_MYSQL_INT_VERSION >= 50706) {
+ $local_query = 'ALTER USER \'' . $username . '\'@\'' . $hostname . '\''
+ . ' IDENTIFIED with ' . $auth_plugin . ' BY '
+ . (($password == '')
+ ? '\'\''
+ : '\'' . PMA_Util::sqlAddSlashes($password) . '\'');
+ } else {
+ $local_query = 'SET password = ' . (($password == '')
+ ? '\'\''
+ : $hashing_function . '(\'' . PMA_Util::sqlAddSlashes($password)
+ . '\')');
+ }
if (! @$GLOBALS['dbi']->tryQuery($local_query)) {
PMA_Util::mysqlDie($GLOBALS['dbi']->getError(), $sql_query, false, $err_url);
}
@@ -197,4 +253,3 @@ function PMA_changePassDisplayPage($message, $sql_query)
. '<strong>' . __('Back') . '</strong></a>';
exit;
}
-?>
diff --git a/version_check.php b/version_check.php
index 0f2e8bab7f..ae097e88df 100644
--- a/version_check.php
+++ b/version_check.php
@@ -26,5 +26,3 @@ if (empty($version)) {
)
);
}
-
-?>
diff --git a/view_create.php b/view_create.php
index 0cf2c3047b..5ea2aa3364 100644
--- a/view_create.php
+++ b/view_create.php
@@ -8,10 +8,8 @@
* @package PhpMyAdmin
*/
-/**
- *
- */
require_once './libraries/common.inc.php';
+require_once './libraries/SystemDatabase.class.php';
/**
* Runs common work
@@ -85,67 +83,68 @@ if (isset($_REQUEST['createview']) || isset($_REQUEST['alterview'])) {
}
}
- if ($GLOBALS['dbi']->tryQuery($sql_query)) {
-
- include_once './libraries/tbl_views.lib.php';
-
- // If different column names defined for VIEW
- $view_columns = array();
- if (isset($_REQUEST['view']['column_names'])) {
- $view_columns = explode(',', $_REQUEST['view']['column_names']);
+ if (!$GLOBALS['dbi']->tryQuery($sql_query)) {
+ if (! isset($_REQUEST['ajax_dialog'])) {
+ $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
+ return;
}
- $column_map = PMA_getColumnMap($_REQUEST['view']['as'], $view_columns);
- $pma_tranformation_data = PMA_getExistingTransformationData($GLOBALS['db']);
+ $response = PMA_Response::getInstance();
+ $response->addJSON(
+ 'message',
+ PMA_Message::error(
+ "<i>" . htmlspecialchars($sql_query) . "</i><br /><br />"
+ . $GLOBALS['dbi']->getError()
+ )
+ );
+ $response->isSuccess(false);
+ exit;
+ }
- if ($pma_tranformation_data !== false) {
+ // If different column names defined for VIEW
+ $view_columns = array();
+ if (isset($_REQUEST['view']['column_names'])) {
+ $view_columns = explode(',', $_REQUEST['view']['column_names']);
+ }
- // SQL for store new transformation details of VIEW
- $new_transformations_sql = PMA_getNewTransformationDataSql(
- $pma_tranformation_data, $column_map, $_REQUEST['view']['name'],
- $GLOBALS['db']
- );
+ $column_map = $GLOBALS['dbi']->getColumnMapFromSql(
+ $_REQUEST['view']['as'], $view_columns
+ );
- // Store new transformations
- if ($new_transformations_sql != '') {
- $GLOBALS['dbi']->tryQuery($new_transformations_sql);
- }
+ $systemDb = $GLOBALS['dbi']->getSystemDatabase();
+ $pma_transformation_data = $systemDb->getExistingTransformationData(
+ $GLOBALS['db']
+ );
- }
- unset($pma_tranformation_data);
+ if ($pma_transformation_data !== false) {
- if (! isset($_REQUEST['ajax_dialog'])) {
- $message = PMA_Message::success();
- include 'tbl_structure.php';
- } else {
- $response = PMA_Response::getInstance();
- $response->addJSON(
- 'message',
- PMA_Util::getMessage(
- PMA_Message::success(), $sql_query
- )
- );
- $response->isSuccess(true);
+ // SQL for store new transformation details of VIEW
+ $new_transformations_sql = $systemDb->getNewTransformationDataSql(
+ $pma_transformation_data, $column_map,
+ $_REQUEST['view']['name'], $GLOBALS['db']
+ );
+
+ // Store new transformations
+ if ($new_transformations_sql != '') {
+ $GLOBALS['dbi']->tryQuery($new_transformations_sql);
}
- exit;
+ }
+ unset($pma_transformation_data);
+ if (! isset($_REQUEST['ajax_dialog'])) {
+ $message = PMA_Message::success();
+ include 'tbl_structure.php';
} else {
- if (! isset($_REQUEST['ajax_dialog'])) {
- $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
- } else {
- $response = PMA_Response::getInstance();
- $response->addJSON(
- 'message',
- PMA_Message::error(
- "<i>" . htmlspecialchars($sql_query) . "</i><br /><br />"
- . $GLOBALS['dbi']->getError()
- )
- );
- $response->isSuccess(false);
- exit;
- }
+ $response = PMA_Response::getInstance();
+ $response->addJSON(
+ 'message',
+ PMA_Util::getMessage(PMA_Message::success(), $sql_query)
+ );
+ $response->isSuccess(true);
}
+
+ exit;
}
// prefill values if not already filled from former submission
@@ -228,7 +227,7 @@ $htmlString .= '<select>'
if ($view['operation'] == 'create') {
$htmlString .= '<tr><td class="nowrap">' . __('VIEW name') . '</td>'
. '<td><input type="text" size="20" name="view[name]"'
- . ' onfocus="this.select()"'
+ . ' onfocus="this.select()" maxlength="64"'
. ' value="' . htmlspecialchars($view['name']) . '" />'
. '</td></tr>';
} else {
@@ -245,8 +244,7 @@ $htmlString .= '<tr><td class="nowrap">' . __('Column names') . '</td>'
$htmlString .= '<tr><td class="nowrap">AS</td>'
. '<td>'
- . '<textarea name="view[as]" rows="' . $cfg['TextareaRows'] . '"'
- . ' cols="' . $cfg['TextareaCols'] . '" dir="' . $text_dir . '"';
+ . '<textarea name="view[as]" rows="15" cols="40" dir="' . $text_dir . '"';
if ($GLOBALS['cfg']['TextareaAutoSelect'] || true) {
$htmlString .= ' onclick="selectContent(this, sql_box_locked, true)"';
}
@@ -288,4 +286,3 @@ $htmlString .= '</form>'
. '</div>';
echo $htmlString;
-?>
diff --git a/view_operations.php b/view_operations.php
index 153249a3df..4e6e923cd8 100644
--- a/view_operations.php
+++ b/view_operations.php
@@ -26,7 +26,7 @@ $url_query .= '&amp;goto=view_operations.php&amp;back=view_operations.php';
$url_params['goto'] = $url_params['back'] = 'view_operations.php';
/**
- * Gets tables informations
+ * Gets tables information
*/
require './libraries/tbl_info.inc.php';
@@ -71,7 +71,7 @@ if (isset($result)) {
unset($warning_messages);
}
echo PMA_Util::getMessage(
- $_message, $sql_query, $_type, $is_view = true
+ $_message, $sql_query, $_type
);
unset($_message, $_type);
}
@@ -136,4 +136,3 @@ echo PMA_getDeleteDataOrTableLink(
echo '</ul>';
echo '</fieldset>';
echo '</div>';
-?>
diff --git a/webapp.php b/webapp.php
index 9e8ac85f5e..4aa8005309 100644
--- a/webapp.php
+++ b/webapp.php
@@ -52,4 +52,3 @@ $zip->setDoWrite();
$zip->addFile($ini_file, 'webapp.ini');
$zip->addFile(file_get_contents($icon), 'phpMyAdmin.ico');
$zip->file();
-?>