aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/templates/table
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/templates/table')
-rw-r--r--srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig12
-rw-r--r--srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig5
-rw-r--r--srcs/phpmyadmin/templates/table/chart/tbl_chart.twig159
-rw-r--r--srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig80
-rw-r--r--srcs/phpmyadmin/templates/table/index_form.twig223
-rw-r--r--srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig19
-rw-r--r--srcs/phpmyadmin/templates/table/operations/view.twig31
-rw-r--r--srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig22
-rw-r--r--srcs/phpmyadmin/templates/table/relation/common_form.twig223
-rw-r--r--srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig9
-rw-r--r--srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig136
-rw-r--r--srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig18
-rw-r--r--srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig3
-rw-r--r--srcs/phpmyadmin/templates/table/search/fields_table.twig33
-rw-r--r--srcs/phpmyadmin/templates/table/search/form_tag.twig4
-rw-r--r--srcs/phpmyadmin/templates/table/search/geom_func.twig19
-rw-r--r--srcs/phpmyadmin/templates/table/search/input_box.twig97
-rw-r--r--srcs/phpmyadmin/templates/table/search/replace_preview.twig39
-rw-r--r--srcs/phpmyadmin/templates/table/search/rows_normal.twig39
-rw-r--r--srcs/phpmyadmin/templates/table/search/rows_zoom.twig74
-rw-r--r--srcs/phpmyadmin/templates/table/search/selection_form.twig226
-rw-r--r--srcs/phpmyadmin/templates/table/search/zoom_result_form.twig86
-rw-r--r--srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig31
-rw-r--r--srcs/phpmyadmin/templates/table/structure/display_partitions.twig145
-rw-r--r--srcs/phpmyadmin/templates/table/structure/display_structure.twig516
-rw-r--r--srcs/phpmyadmin/templates/table/structure/display_table_stats.twig169
-rw-r--r--srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig14
-rw-r--r--srcs/phpmyadmin/templates/table/tracking/main.twig132
-rw-r--r--srcs/phpmyadmin/templates/table/tracking/report_table.twig27
-rw-r--r--srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig56
-rw-r--r--srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig33
31 files changed, 2680 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig b/srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig
new file mode 100644
index 0000000..f2ec2ba
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig
@@ -0,0 +1,12 @@
+<td{{ nowrap ? ' class="nowrap"' }}>
+ {{ is_selected ? '<strong>' }}
+ <a class="foreign_value" data-key="{{ keyname }}" href="#" title="
+ {%- trans 'Use this value' %}{{ title is not empty ? ': ' ~ title }}">
+ {% if nowrap %}
+ {{ keyname }}
+ {% else %}
+ {{ description }}
+ {% endif %}
+ </a>
+ {{ is_selected ? '</strong>' }}
+</td>
diff --git a/srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig b/srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig
new file mode 100644
index 0000000..4de9b81
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig
@@ -0,0 +1,5 @@
+{% if foreign_data.disp_row is iterable and
+ (show_all and foreign_data.the_total > max_rows) %}
+ <input class="btn btn-secondary" type="submit" id="foreign_showAll" name="foreign_showAll" value="
+ {%- trans 'Show all' %}">
+{% endif %}
diff --git a/srcs/phpmyadmin/templates/table/chart/tbl_chart.twig b/srcs/phpmyadmin/templates/table/chart/tbl_chart.twig
new file mode 100644
index 0000000..4201599
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/chart/tbl_chart.twig
@@ -0,0 +1,159 @@
+<script type="text/javascript">
+ url_query = '{{ url_query }}';
+</script>
+{# Display Chart options #}
+<div id="div_view_options">
+ <form method="post" id="tblchartform" action="tbl_chart.php" class="ajax">
+ {{ get_hidden_inputs(url_params) }}
+ <fieldset>
+ <legend>
+ {% trans 'Display chart' %}
+ </legend>
+ <div class="chartOption">
+ <div class="formelement">
+ <input type="radio" name="chartType" value="bar" id="radio_bar">
+ <label for ="radio_bar">{% trans %}Bar{% context %}Chart type{% endtrans %}</label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="column" id="radio_column">
+ <label for ="radio_column">{% trans %}Column{% context %}Chart type{% endtrans %}</label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="line" id="radio_line" checked="checked">
+ <label for ="radio_line">{% trans %}Line{% context %}Chart type{% endtrans %}</label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="spline" id="radio_spline">
+ <label for ="radio_spline">{% trans %}Spline{% context %}Chart type{% endtrans %}</label>
+ </div>
+ <div class="formelement">
+ <input type="radio" name="chartType" value="area" id="radio_area">
+ <label for ="radio_area">{% trans %}Area{% context %}Chart type{% endtrans %}</label>
+ </div>
+ <span class="span_pie hide">
+ <input type="radio" name="chartType" value="pie" id="radio_pie">
+ <label for ="radio_pie">{% trans %}Pie{% context %}Chart type{% endtrans %}</label>
+ </span>
+ <span class="span_timeline hide">
+ <input type="radio" name="chartType" value="timeline" id="radio_timeline">
+ <label for ="radio_timeline">{% trans %}Timeline{% context %}Chart type{% endtrans %}</label>
+ </span>
+ <span class="span_scatter hide">
+ <input type="radio" name="chartType" value="scatter" id="radio_scatter">
+ <label for ="radio_scatter">{% trans %}Scatter{% context %}Chart type{% endtrans %}</label>
+ </span>
+ <br><br>
+ <span class="barStacked hide">
+ <input type="checkbox" name="barStacked" value="1" id="checkbox_barStacked">
+ <label for ="checkbox_barStacked">{% trans 'Stacked' %}</label>
+ </span>
+ <br><br>
+ <label for ="chartTitle">{% trans 'Chart title:' %}</label>
+ <input type="text" name="chartTitle" id="chartTitle">
+ </div>
+ {% set xaxis = null %}
+ <div class="chartOption">
+ <label for="select_chartXAxis">{% trans 'X-Axis:' %}</label>
+ <select name="chartXAxis" id="select_chartXAxis">
+ {% for idx, key in keys %}
+ {% if xaxis is same as(null) %}
+ {% set xaxis = idx %}
+ {% endif %}
+ {% if xaxis is same as(idx) %}
+ <option value="{{ idx }}" selected="selected">{{ key }}</option>
+ {% else %}
+ <option value="{{ idx }}">{{ key }}</option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ <br>
+ <label for="select_chartSeries">
+ {% trans 'Series:' %}
+ </label>
+ <select name="chartSeries" id="select_chartSeries" multiple="multiple">
+ {% for idx, key in keys %}
+ {% if fields_meta[idx].type in numeric_types %}
+ {% if idx == xaxis and numeric_column_count > 1 %}
+ <option value="{{ idx }}">{{ key }}</option>
+ {% else %}
+ <option value="{{ idx }}" selected="selected">{{ key }}</option>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </select>
+ <input type="hidden" name="dateTimeCols" value="
+ {% set date_time_types = ['date', 'datetime', 'timestamp'] %}
+ {% for idx, key in keys %}
+ {% if fields_meta[idx].type in date_time_types %}
+ {{ idx ~ ' ' }}
+ {% endif %}
+ {% endfor %}">
+ <input type="hidden" name="numericCols" value="
+ {% for idx, key in keys %}
+ {% if fields_meta[idx].type in numeric_types %}
+ {{ idx ~ ' ' }}
+ {% endif %}
+ {% endfor %}">
+ </div>
+ <div class="chartOption">
+ <label for="xaxis_panel">
+ {% trans 'X-Axis label:' %}
+ </label>
+ <input style="margin-top:0;" type="text" name="xaxis_label" id="xaxis_label" value="{{ xaxis == -1 ? 'X Values'|trans : keys[xaxis] }}">
+ <br>
+ <label for="yaxis_label">
+ {% trans 'Y-Axis label:' %}
+ </label>
+ <input type="text" name="yaxis_label" id="yaxis_label" value="{% trans 'Y Values' %}">
+ <br>
+ </div>
+ <div class="clearfloat"></div>
+ <div>
+ <input type="checkbox" id="chkAlternative" name="chkAlternative" value="alternativeFormat">
+ <label for="chkAlternative">{% trans 'Series names are in a column' %}</label>
+ <br>
+ <label for="select_seriesColumn">
+ {% trans 'Series column:' %}
+ </label>
+ <select name="chartSeriesColumn" id="select_seriesColumn" disabled>
+ {% for idx, key in keys %}
+ <option value="{{ idx }}"
+ {% if idx == 1 %}
+ selected="selected"
+ {% endif %}>
+ {{ key }}
+ </option>
+ {% set series_column = idx %}
+ {% endfor %}
+ </select>
+ <label for="select_valueColumn">
+ {% trans 'Value Column:' %}
+ </label>
+ <select name="chartValueColumn" id="select_valueColumn" disabled>
+ {% set selected = false %}
+ {% for idx, key in keys %}
+ {% if fields_meta[idx].type in numeric_types %}
+ {% if not selected and idx != xaxis and idx != series_column %}
+ <option value="{{ idx }}" selected="selected">{{ key }}</option>
+ {% set selected = true %}
+ {% else %}
+ <option value="{{ idx }}">{{ key }}</option>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </select>
+ </div>
+ {{ get_start_and_number_of_rows_panel(sql_query) }}
+ <div class="clearfloat"></div>
+ <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">
+ {{ get_image('b_saveimage', 'Save chart as image'|trans) }}
+ </a>
+ </div>
+ <div id="querychart" dir="ltr">
+ </div>
+ </div>
+ </fieldset>
+ </form>
+</div>
diff --git a/srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig b/srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig
new file mode 100644
index 0000000..9e82e2e
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig
@@ -0,0 +1,80 @@
+<div id="div_view_options">
+ <fieldset>
+ <legend>{% trans 'Display GIS Visualization' %}</legend>
+ <div id="gis_div" style="position:relative;">
+ <form method="post" action="tbl_gis_visualization.php">
+ {{ get_hidden_inputs(url_params) }}
+ <label for="labelColumn">
+ {% trans "Label column" %}
+ </label>
+ <select name="visualizationSettings[labelColumn]" id="labelColumn" class="autosubmit">
+ <option value="">{% trans "-- None --" %}</option>
+ {% for value in label_candidates %}
+ <option value="{{ value }}"{{ value == visualization_settings['labelColumn'] ? ' selected="selected"' }}>
+ {{ value }}
+ </option>
+ {% endfor %}
+ </select>
+ <label for="spatialColumn">
+ {% trans "Spatial column" %}
+ </label>
+ <select name="visualizationSettings[spatialColumn]" id="spatialColumn" class="autosubmit">
+ {% for value in spatial_candidates %}
+ <option value="{{ value }}"{{ value == visualization_settings['spatialColumn'] ? ' selected="selected"' }}>
+ {{ value }}
+ </option>
+ {% endfor %}
+ </select>
+ <input type="hidden" name="displayVisualization" value="redraw">
+ <tr>
+ <td class="choice" colspan="2">
+ <input type="checkbox"
+ name="visualizationSettings[choice]"
+ id="choice" value="useBaseLayer"
+ {% if visualization_settings['choice'] is defined %}
+ checked="checked"
+ {% endif %}>
+ <label for="choice" id="labelChoice">
+ {% trans "Use OpenStreetMaps as Base Layer" %}
+ </label>
+ </td>
+ </tr>
+ {{ get_start_and_number_of_rows_panel(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;">
+ {{ get_image('b_saveimage', 'Save'|trans) }}
+ </span>
+ <ul>
+ <li class="warp_link">
+ <a href="{{ download_url|raw }}&fileFormat=png" class="disableAjax">PNG</a>
+ </li>
+ <li class="warp_link">
+ <a href="{{ download_url|raw }}&fileFormat=pdf" class="disableAjax">PDF</a>
+ </li>
+ <li class="warp_link">
+ <a href="{{ download_url|raw }}&fileFormat=svg" class="disableAjax">SVG</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <div class="clearfloat"></div>
+
+ <div id="placeholder"
+ style="width:{{ visualization_settings['width'] }}px;height:{{ visualization_settings['height'] }}px;">
+ {{ visualization|raw }}
+ </div>
+ <div id="openlayersmap"></div>
+ <input type="hidden" id="pmaThemeImage" value="{{ pma_theme_image }}">
+ <script language="javascript" type="text/javascript">
+ function drawOpenLayers()
+ {
+ {{ draw_ol|raw }}
+ }
+ </script>
+ </fieldset>
+</div>
diff --git a/srcs/phpmyadmin/templates/table/index_form.twig b/srcs/phpmyadmin/templates/table/index_form.twig
new file mode 100644
index 0000000..6364599
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/index_form.twig
@@ -0,0 +1,223 @@
+<form action="tbl_indexes.php"
+ method="post"
+ name="index_frm"
+ id="index_frm"
+ class="ajax">
+
+ {{ get_hidden_inputs(form_params) }}
+
+ <fieldset id="index_edit_fields">
+ <div class="index_info">
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_index_name">
+ {% trans 'Index name:' %}
+ {{ show_hint('"PRIMARY" <b>must</b> be the name of and <b>only of</b> a primary key!'|trans) }}
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Key_name]"
+ id="input_index_name"
+ size="25"
+ maxlength="64"
+ value="{{ index.getName() }}"
+ onfocus="this.select()">
+ </div>
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="select_index_choice">
+ {% trans 'Index choice:' %}
+ {{ show_mysql_docu('ALTER_TABLE') }}
+ </label>
+ </strong>
+ </div>
+ {{ index.generateIndexChoiceSelector(create_edit_table)|raw }}
+ </div>
+
+ {% include 'div_for_slider_effect.twig' with {
+ 'id': 'indexoptions',
+ 'message': 'Advanced Options'|trans,
+ 'initial_sliders_state': default_sliders_state
+ } only %}
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_key_block_size">
+ {% trans 'Key block size:' %}
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Key_block_size]"
+ id="input_key_block_size"
+ size="30"
+ value="{{ index.getKeyBlockSize() }}">
+ </div>
+
+ <div>
+
+ <div class="label">
+ <strong>
+ <label for="select_index_type">
+ {% trans 'Index type:' %}
+ {{ show_mysql_docu('ALTER_TABLE') }}
+ </label>
+ </strong>
+ </div>
+ {{ index.generateIndexTypeSelector()|raw }}
+ </div>
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_parser">
+ {% trans 'Parser:' %}
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Parser]"
+ id="input_parse"
+ size="30"
+ value="{{ index.getParser() }}">
+ </div>
+
+ <div>
+ <div class="label">
+ <strong>
+ <label for="input_index_comment">
+ {% trans 'Comment:' %}
+ </label>
+ </strong>
+ </div>
+
+ <input type="text"
+ name="index[Index_comment]"
+ id="input_index_comment"
+ size="30"
+ maxlength="1024"
+ value="{{ index.getComment() }}">
+ </div>
+ </div>
+ <!-- end of indexoptions div -->
+
+ <div class="clearfloat"></div>
+
+ <table id="index_columns">
+ <thead>
+ <tr>
+ <th></th>
+ <th>
+ {% trans 'Column' %}
+ </th>
+ <th>
+ {% trans 'Size' %}
+ </th>
+ </tr>
+ </thead>
+ {% set spatial_types = [
+ 'geometry',
+ 'point',
+ 'linestring',
+ 'polygon',
+ 'multipoint',
+ 'multilinestring',
+ 'multipolygon',
+ 'geomtrycollection'
+ ] %}
+ <tbody>
+ {% for column in index.getColumns() %}
+ <tr class="noclick">
+ <td>
+ <span class="drag_icon" title="{% trans 'Drag to reorder' %}"></span>
+ </td>
+ <td>
+ <select name="index[columns][names][]">
+ <option value="">
+ -- {% trans 'Ignore' %} --
+ </option>
+ {% for field_name, field_type in fields %}
+ {% if (index.getChoice() != 'FULLTEXT'
+ or field_type matches '/(char|text)/i')
+ and (index.getChoice() != 'SPATIAL'
+ or field_type in spatial_types) %}
+
+ <option value="{{ field_name }}"
+ {%- if field_name == column.getName() %}
+ selected="selected"
+ {%- endif %}>
+ {{ field_name }} [{{ field_type }}]
+ </option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ </td>
+ <td>
+ <input type="text"
+ size="5"
+ onfocus="this.select()"
+ name="index[columns][sub_parts][]"
+ value="{{ index.getChoice() != 'SPATIAL' ?
+ column.getSubPart() }}">
+ </td>
+ </tr>
+ {% endfor %}
+ {% if add_fields > 0 %}
+ {% for i in range(1, add_fields) %}
+ <tr class="noclick">
+ <td>
+ <span class="drag_icon" title="{% trans 'Drag to reorder' %}"></span>
+ </td>
+ <td>
+ <select name="index[columns][names][]">
+ <option value="">-- {% trans 'Ignore' %} --</option>
+ {% set j = 0 %}
+ {% for field_name, field_type in fields %}
+ {% if create_edit_table %}
+ {% set col_index = field_type[1] %}
+ {% set field_type = field_type[0] %}
+ {% endif %}
+ {% set j = j + 1 %}
+ <option value="{{ col_index is defined ?
+ col_index : field_name }}"
+ {{- j == i ? ' selected="selected"' }}>
+ {{ field_name }} [{{ field_type }}]
+ </option>
+ {% endfor %}
+ </select>
+ </td>
+ <td>
+ <input type="text"
+ size="5"
+ onfocus="this.select()"
+ name="index[columns][sub_parts][]"
+ value="">
+ </td>
+ </tr>
+ {% endfor %}
+ {% endif %}
+ </tbody>
+ </table>
+ <div class="add_more">
+
+ <div class="slider"></div>
+ <div class="add_fields hide">
+ <input class="btn btn-secondary" type="submit"
+ id="add_fields"
+ value="{{ 'Add %s column(s) to index'|trans|format(1) }}">
+ </div>
+ </div>
+ </fieldset>
+ <fieldset class="tblFooters">
+ <button class="btn btn-secondary" type="submit" id="preview_index_frm">{% trans 'Preview SQL' %}</button>
+ <input class="btn btn-primary" type="submit" id="save_index_frm" value="{% trans 'Go' %}">
+ </fieldset>
+</form>
diff --git a/srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig b/srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig
new file mode 100644
index 0000000..86a8215
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig
@@ -0,0 +1,19 @@
+<form id="continueForm" method="post" action="tbl_replace.php" name="continueForm">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="goto" value="{{ goto }}">
+ <input type="hidden" name="err_url" value="{{ err_url }}">
+ <input type="hidden" name="sql_query" value="{{ sql_query }}">
+
+ {% if has_where_clause %}
+ {% for key_id, where_clause in where_clause_array %}
+ <input type="hidden" name="where_clause[{{ key_id }}]" value="
+ {{- where_clause|trim }}">
+ {% endfor %}
+ {% endif %}
+
+ {% set insert_rows %}
+ <input type="number" name="insert_rows" id="insert_rows" value="
+ {{- insert_rows_default }}" min="1">
+ {% endset %}
+ {{ 'Continue insertion with %s rows'|trans|format(insert_rows)|raw }}
+</form>
diff --git a/srcs/phpmyadmin/templates/table/operations/view.twig b/srcs/phpmyadmin/templates/table/operations/view.twig
new file mode 100644
index 0000000..e590532
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/operations/view.twig
@@ -0,0 +1,31 @@
+<!-- VIEW operations -->
+<div>
+ <form method="post" action="view_operations.php">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="reload" value="1">
+ <fieldset>
+ <legend>{% trans 'Operations' %}</legend>
+ <table>
+ <!-- Change view name -->
+ <tr>
+ <td>{% trans 'Rename view to' %}</td>
+ <td><input type="text" name="new_name" onfocus="this.select()"
+ value="{{ table }}"
+ required>
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ <fieldset class="tblFooters">
+ <input type="hidden" name="submitoptions" value="1">
+ <input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
+ </fieldset>
+ </form>
+</div>
+
+<div>
+ <fieldset class="caution">
+ <legend>{% trans 'Delete data or table' %}</legend>
+ <ul>{{ delete_data_or_table_link | raw }}</ul>
+ </fieldset>
+</div>
diff --git a/srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig b/srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig
new file mode 100644
index 0000000..2aae85a
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig
@@ -0,0 +1,22 @@
+{% if cfg_relation['relwork'] or is_foreign_key_supported %}
+ <ul id="topmenu2">
+ {{ get_html_tab({
+ 'icon': 'b_props',
+ 'link': 'tbl_structure.php',
+ 'text': 'Table structure'|trans,
+ 'id': 'table_strucuture_id'
+ }, url_params) }}
+ {{ get_html_tab({
+ 'icon': 'b_relations',
+ 'link': 'tbl_relation.php',
+ 'text': 'Relation view'|trans,
+ 'id': 'table_relation_id'
+ }, url_params) }}
+ </ul>
+ <div class="clearfloat"></div>
+{% endif %}
+
+<div id="structure_content">
+ {% block content %}
+ {% endblock %}
+</div>
diff --git a/srcs/phpmyadmin/templates/table/relation/common_form.twig b/srcs/phpmyadmin/templates/table/relation/common_form.twig
new file mode 100644
index 0000000..e85c6ce
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/relation/common_form.twig
@@ -0,0 +1,223 @@
+{% extends 'table/page_with_secondary_tabs.twig' %}
+
+{% block content %}
+<form method="post" action="tbl_relation.php">
+ {{ get_hidden_inputs(db, table) }}
+ {# InnoDB #}
+ {% if is_foreign_key_supported(tbl_storage_engine) %}
+ <fieldset>
+ <legend>{% trans 'Foreign key constraints' %}</legend>
+ <div class="responsivetable jsresponsive">
+ <table id="foreign_keys" class="relationalTable">
+ <thead><tr>
+ <th>{% trans 'Actions' %}</th>
+ <th>{% trans 'Constraint properties' %}</th>
+ {% if tbl_storage_engine|upper == 'INNODB' %}
+ <th>
+ {% trans 'Column' %}
+ {{ show_hint('Creating a foreign key over a non-indexed column would automatically create an index on it. Alternatively, you can define an index below, before creating the foreign key.'|trans) }}
+ </th>
+ {% else %}
+ <th>
+ {% trans 'Column' %}
+ {{ show_hint('Only columns with index will be displayed. You can define an index below.'|trans) }}
+ </th>
+ {% endif %}
+ <th colspan="3">
+ {% trans 'Foreign key constraint' %}
+ ({{ tbl_storage_engine }})
+ </th>
+ </tr>
+ <tr>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th>{% trans 'Database' %}</th>
+ <th>{% trans 'Table' %}</th>
+ <th>{% trans 'Column' %}</th>
+ </tr></thead>
+ {% set i = 0 %}
+ {% if existrel_foreign is not empty %}
+ {% for key, one_key in existrel_foreign %}
+ {# Foreign database dropdown #}
+ {% set foreign_db = one_key['ref_db_name'] is defined
+ and one_key['ref_db_name'] is not null
+ ? one_key['ref_db_name'] : db %}
+ {% set foreign_table = false %}
+ {% if foreign_db %}
+ {% set foreign_table = one_key['ref_table_name'] is defined
+ and one_key['ref_table_name'] is not null
+ ? one_key['ref_table_name'] : false %}
+ {% endif %}
+ {% set unique_columns = [] %}
+ {% if foreign_db and foreign_table %}
+ {% set table_obj = table_get(foreign_table, foreign_db) %}
+ {% set unique_columns = table_obj.getUniqueColumns(false, false) %}
+ {% endif %}
+ {% include 'table/relation/foreign_key_row.twig' with {
+ 'i': i,
+ 'one_key': one_key,
+ 'column_array': column_array,
+ 'options_array': options_array,
+ 'tbl_storage_engine': tbl_storage_engine,
+ 'db': db,
+ 'table': table,
+ 'url_params': url_params,
+ 'databases': databases,
+ 'foreign_db': foreign_db,
+ 'foreign_table': foreign_table,
+ 'unique_columns': unique_columns
+ } only %}
+ {% set i = i + 1 %}
+ {% endfor %}
+ {% endif %}
+ {% include 'table/relation/foreign_key_row.twig' with {
+ 'i': i,
+ 'one_key': [],
+ 'column_array': column_array,
+ 'options_array': options_array,
+ 'tbl_storage_engine': tbl_storage_engine,
+ 'db': db,
+ 'table': table,
+ 'url_params': url_params,
+ 'databases': databases,
+ 'foreign_db': foreign_db,
+ 'foreign_table': foreign_table,
+ 'unique_columns': unique_columns
+ } only %}
+ {% set i = i + 1 %}
+ <tr>
+ <th colspan="6">
+ <a class="formelement clearfloat add_foreign_key" href="">
+ {% trans '+ Add constraint' %}
+ </a>
+ </th>
+ </tr>
+ </table>
+ </div>
+ </fieldset>
+ {% endif %}
+
+ {% if cfg_relation['relwork'] %}
+ {% if is_foreign_key_supported(tbl_storage_engine) %}
+ {% include 'div_for_slider_effect.twig' with {
+ 'id': 'ir_div',
+ 'message': 'Internal relationships'|trans,
+ 'initial_sliders_state': default_sliders_state
+ } only %}
+ {% endif %}
+
+ <fieldset>
+ <legend>
+ {% trans 'Internal relationships' %}
+ {{ show_docu('config', 'cfg_Servers_relation') }}
+ </legend>
+ <table id="internal_relations" class="relationalTable">
+ <tr>
+ <th>{% trans 'Column' %}</th>
+ <th>{% trans 'Internal relation' %}
+ {% if is_foreign_key_supported(tbl_storage_engine) %}
+ {{ show_hint('An internal relation is not necessary when a corresponding FOREIGN KEY relation exists.'|trans) }}
+ {% endif %}
+ </th>
+ {% set saved_row_cnt = save_row|length - 1 %}
+ {% for i in 0..saved_row_cnt %}
+ {% set myfield = save_row[i]['Field'] %}
+ {# Use an md5 as array index to avoid having special characters
+ in the name attribute (see bug #1746964 ) #}
+ {% set myfield_md5 = column_hash_array[myfield] %}
+
+ {% set foreign_table = false %}
+ {% set foreign_column = false %}
+
+ {# Database dropdown #}
+ {% if existrel[myfield] is defined %}
+ {% set foreign_db = existrel[myfield]['foreign_db'] %}
+ {% else %}
+ {% set foreign_db = db %}
+ {% endif %}
+
+ {# Table dropdown #}
+ {% set tables = [] %}
+ {% if foreign_db %}
+ {% if existrel[myfield] is defined %}
+ {% set foreign_table = existrel[myfield]['foreign_table'] %}
+ {% endif %}
+ {% set tables = dbi.getTables(foreign_db) %}
+ {% endif %}
+
+ {# Column dropdown #}
+ {% set unique_columns = [] %}
+ {% if foreign_db and foreign_table %}
+ {% if existrel[myfield] is defined %}
+ {% set foreign_column = existrel[myfield]['foreign_field'] %}
+ {% endif %}
+ {% set table_obj = table_get(foreign_table, foreign_db) %}
+ {% set unique_columns = table_obj.getUniqueColumns(false, false) %}
+ {% endif %}
+
+ <tr>
+ <td class="vmiddle">
+ <strong>{{ myfield }}</strong>
+ <input type="hidden" name="fields_name[{{ myfield_md5 }}]"
+ value="{{ myfield }}">
+ </td>
+
+ <td>
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_db[' ~ myfield_md5 ~ ']',
+ 'title': 'Database'|trans,
+ 'values': databases,
+ 'foreign': foreign_db
+ } only %}
+
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_table[' ~ myfield_md5 ~ ']',
+ 'title': 'Table'|trans,
+ 'values': tables,
+ 'foreign': foreign_table
+ } only %}
+
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_column[' ~ myfield_md5 ~ ']',
+ 'title': 'Column'|trans,
+ 'values': unique_columns,
+ 'foreign': foreign_column
+ } only %}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ </fieldset>
+ {% if is_foreign_key_supported(tbl_storage_engine) %}
+ </div>
+ {% endif %}
+ {% endif %}
+
+ {% if cfg_relation['displaywork'] %}
+ {% set disp = get_display_field(db, table) %}
+ <fieldset>
+ <label>{% trans 'Choose column to display:' %}</label>
+ <select name="display_field">
+ <option value="">---</option>
+ {% for row in save_row %}
+ <option value="{{ row['Field'] }}"
+ {%- if disp is defined and row['Field'] == disp %}
+ selected="selected"
+ {%- endif %}>
+ {{ row['Field'] }}
+ </option>
+ {% endfor %}
+ </select>
+ </fieldset>
+ {% endif %}
+
+ <fieldset class="tblFooters">
+ <input class="btn btn-secondary preview_sql" type="button" value="{% trans 'Preview SQL' %}">
+ <input class="btn btn-primary" type="submit" value="{% trans 'Save' %}">
+ </fieldset>
+</form>
+{% if foreignKeySupported %}
+ {{ displayIndexesHtml|raw }}
+{% endif %}
+{% endblock %}
diff --git a/srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig b/srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig
new file mode 100644
index 0000000..ff179bc
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig
@@ -0,0 +1,9 @@
+{{ dropdown_question is not empty ? dropdown_question -}}
+<select name="{{ select_name }}">
+{% for one_value, one_label in choices %}
+ <option value="{{ one_value }}"
+ {%- if selected_value == one_value %} selected="selected"{% endif %}>
+ {{ one_label }}
+ </option>
+{% endfor %}
+</select>
diff --git a/srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig b/srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig
new file mode 100644
index 0000000..3df6c34
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig
@@ -0,0 +1,136 @@
+<tr>
+ {# Drop key anchor #}
+ <td>
+ {% set js_msg = '' %}
+ {% set this_params = null %}
+ {% if one_key['constraint'] is defined %}
+ {% set drop_fk_query = 'ALTER TABLE ' ~ backquote(db) ~ '.' ~ backquote(table)
+ ~ ' DROP FOREIGN KEY '
+ ~ backquote(one_key['constraint']) ~ ';'
+ %}
+ {% set this_params = url_params %}
+ {% set this_params = {
+ 'goto': 'tbl_relation.php',
+ 'back': 'tbl_relation.php',
+ 'sql_query': drop_fk_query,
+ 'message_to_show': 'Foreign key constraint %s has been dropped'|trans|format(
+ one_key['constraint']
+ )
+ } %}
+ {% set js_msg = 'ALTER TABLE ' ~ db ~ '.' ~ table ~ ' DROP FOREIGN KEY ' ~ one_key['constraint'] ~ ';'|js_format %}
+ {% endif %}
+ {% if one_key['constraint'] is defined %}
+ <input type="hidden" class="drop_foreign_key_msg" value="
+ {{- js_msg }}">
+ {% set drop_url = 'sql.php' ~ get_common(this_params) %}
+ {% set drop_str = get_icon('b_drop', 'Drop'|trans) %}
+ {{ link_or_button(drop_url, drop_str, {'class': 'drop_foreign_key_anchor ajax'}) }}
+ {% endif %}
+ </td>
+ <td>
+ <span class="formelement clearfloat">
+ <input type="text" name="constraint_name[{{ i }}]" value="
+ {{- one_key['constraint'] is defined ? one_key['constraint'] -}}
+ " placeholder="{% trans 'Constraint name' %}" maxlength="64">
+ </span>
+ <div class="floatleft">
+ {# 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. #}
+ {% set on_delete = one_key['on_delete'] is defined
+ ? one_key['on_delete'] : 'RESTRICT' %}
+ {% set on_update = one_key['on_update'] is defined
+ ? one_key['on_update'] : 'RESTRICT' %}
+ <span class="formelement">
+ {% include 'table/relation/dropdown_generate.twig' with {
+ 'dropdown_question': 'ON DELETE',
+ 'select_name': 'on_delete[' ~ i ~ ']',
+ 'choices': options_array,
+ 'selected_value': on_delete
+ } only %}
+ </span>
+ <span class="formelement">
+ {% include 'table/relation/dropdown_generate.twig' with {
+ 'dropdown_question': 'ON UPDATE',
+ 'select_name': 'on_update[' ~ i ~ ']',
+ 'choices': options_array,
+ 'selected_value': on_update
+ } only %}
+ </span>
+ </div>
+ </td>
+ <td>
+ {% if one_key['index_list'] is defined %}
+ {% for key, column in one_key['index_list'] %}
+ <span class="formelement clearfloat">
+ {% include 'table/relation/dropdown_generate.twig' with {
+ 'dropdown_question': '',
+ 'select_name': 'foreign_key_fields_name[' ~ i ~ '][]',
+ 'choices': column_array,
+ 'selected_value': column
+ } only %}
+ </span>
+ {% endfor %}
+ {% else %}
+ <span class="formelement clearfloat">
+ {% include 'table/relation/dropdown_generate.twig' with {
+ 'dropdown_question': '',
+ 'select_name': 'foreign_key_fields_name[' ~ i ~ '][]',
+ 'choices': column_array,
+ 'selected_value': ''
+ } only %}
+ </span>
+ {% endif %}
+ <a class="formelement clearfloat add_foreign_key_field" data-index="
+ {{- i }}" href="">
+ {% trans '+ Add column' %}
+ </a>
+ </td>
+ {% set tables = [] %}
+ {% if foreign_db %}
+ {% set tables = get_tables(foreign_db, tbl_storage_engine) %}
+ {% endif %}
+ <td>
+ <span class="formelement clearfloat">
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_foreign_db[' ~ i ~ ']',
+ 'title': 'Database'|trans,
+ 'values': databases,
+ 'foreign': foreign_db
+ } only %}
+ </span>
+ </td>
+ <td>
+ <span class="formelement clearfloat">
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_foreign_table[' ~ i ~ ']',
+ 'title': 'Table'|trans,
+ 'values': tables,
+ 'foreign': foreign_table
+ } only %}
+ </span>
+ </td>
+ <td>
+ {% if foreign_db and foreign_table %}
+ {% for foreign_column in one_key['ref_index_list'] %}
+ <span class="formelement clearfloat">
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_foreign_column[' ~ i ~ '][]',
+ 'title': 'Column'|trans,
+ 'values': unique_columns,
+ 'foreign': foreign_column
+ } only %}
+ </span>
+ {% endfor %}
+ {% else %}
+ <span class="formelement clearfloat">
+ {% include 'table/relation/relational_dropdown.twig' with {
+ 'name': 'destination_foreign_column[' ~ i ~ '][]',
+ 'title': 'Column'|trans,
+ 'values': [],
+ 'foreign': ''
+ } only %}
+ </span>
+ {% endif %}
+ </td>
+</tr>
diff --git a/srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig b/srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig
new file mode 100644
index 0000000..9d5f3c9
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig
@@ -0,0 +1,18 @@
+<select name="{{ name }}" title="{{ title }}">
+ <option value=""></option>
+ {% set seen_key = false %}
+ {% for value in values %}
+ <option value="{{ value }}"
+ {%- if foreign is not same as(false) and value == foreign %}
+ selected="selected"
+ {%- set seen_key = true -%}
+ {%- endif %}>
+ {{ value }}
+ </option>
+ {% endfor %}
+ {% if foreign is not same as(false) and not seen_key %}
+ <option value="{{ foreign }}" selected="selected">
+ {{ foreign }}
+ </option>
+ {% endif %}
+</select>
diff --git a/srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig b/srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig
new file mode 100644
index 0000000..b72e530
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig
@@ -0,0 +1,3 @@
+<select id="ColumnOperator{{ search_index }}" name="criteriaColumnOperators[{{ search_index }}]">
+ {{ type_operators|raw }}
+</select>
diff --git a/srcs/phpmyadmin/templates/table/search/fields_table.twig b/srcs/phpmyadmin/templates/table/search/fields_table.twig
new file mode 100644
index 0000000..8b74939
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/fields_table.twig
@@ -0,0 +1,33 @@
+<table class="data"{{ search_type == 'zoom' ? ' id="tableFieldsId"' }}>
+ <thead>
+ <tr>
+ {% if geom_column_flag %}
+ <th>{% trans 'Function' %}</th>
+ {% endif %}
+ <th>{% trans 'Column' %}</th>
+ <th>{% trans 'Type' %}</th>
+ <th>{% trans 'Collation' %}</th>
+ <th>{% trans 'Operator' %}</th>
+ <th>{% trans 'Value' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% if search_type == 'zoom' %}
+ {% include 'table/search/rows_zoom.twig' with {
+ 'self': self,
+ 'column_names': column_names,
+ 'keys': keys,
+ 'criteria_column_names': criteria_column_names,
+ 'criteria_column_types': criteria_column_types
+ } only %}
+ {% else %}
+ {% include 'table/search/rows_normal.twig' with {
+ 'self': self,
+ 'geom_column_flag': geom_column_flag,
+ 'column_names': column_names,
+ 'column_types': column_types,
+ 'column_collations': column_collations
+ } only %}
+ {% endif %}
+ </tbody>
+</table>
diff --git a/srcs/phpmyadmin/templates/table/search/form_tag.twig b/srcs/phpmyadmin/templates/table/search/form_tag.twig
new file mode 100644
index 0000000..1017abd
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/form_tag.twig
@@ -0,0 +1,4 @@
+<form method="post" action="{{ script_name }}" name="insertForm" id="{{ form_id }}" class="ajax lock-page">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="goto" value="{{ goto }}">
+ <input type="hidden" name="back" value="{{ script_name }}">
diff --git a/srcs/phpmyadmin/templates/table/search/geom_func.twig b/srcs/phpmyadmin/templates/table/search/geom_func.twig
new file mode 100644
index 0000000..f7a7415
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/geom_func.twig
@@ -0,0 +1,19 @@
+{# Displays 'Function' column if it is present #}
+<td>
+ {% set geom_types = get_gis_datatypes() %}
+ {% if column_types[column_index] in geom_types %}
+ <select class="geom_func" name="geom_func[{{ column_index }}]">
+ {# get the relevant list of GIS functions #}
+ {% set funcs = get_gis_functions(column_types[column_index], true, true) %}
+
+ {% for func_name, func in funcs %}
+ {% set name = func['display'] is defined ? func['display'] : func_name %}
+ <option value="{{ name }}">
+ {{ name }}
+ </option>
+ {% endfor %}
+ </select>
+ {% else %}
+ &nbsp;
+ {% endif %}
+</td>
diff --git a/srcs/phpmyadmin/templates/table/search/input_box.twig b/srcs/phpmyadmin/templates/table/search/input_box.twig
new file mode 100644
index 0000000..5c30535
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/input_box.twig
@@ -0,0 +1,97 @@
+{# Get inputbox based on different column types (Foreign key, geometrical, enum) #}
+{% if foreigners and search_column_in_foreigners(foreigners, column_name) %}
+ {% if foreign_data['disp_row'] is iterable %}
+ <select name="criteriaValues[{{ column_index }}]"
+ id="{{ column_id }}{{ column_index }}">
+ {{ foreign_dropdown(
+ foreign_data['disp_row'],
+ foreign_data['foreign_field'],
+ foreign_data['foreign_display'],
+ '',
+ foreign_max_limit
+ ) }}
+ </select>
+ {% elseif foreign_data['foreign_link'] == true %}
+ <input type="text"
+ id="{{ column_id }}{{ column_index }}"
+ name="criteriaValues[{{ column_index }}]"
+ id="field_{{ column_name_hash }}[{{ column_index }}]"
+ class="textfield"
+ {% if criteria_values[column_index] is defined %}
+ value="{{ criteria_values[column_index] }}"
+ {% endif %}>
+ <a class="ajax browse_foreign" href="browse_foreigners.php" data-post="
+ {{- get_common({'db': db, 'table': table}, '') -}}
+ &amp;field={{ column_name|url_encode }}&amp;fieldkey=
+ {{- column_index }}&amp;fromsearch=1">
+ {{ titles['Browse']|replace({"'": "\\'"})|raw }}
+ </a>
+ {% endif %}
+{% elseif column_type in get_gis_datatypes() %}
+ <input type="text"
+ name="criteriaValues[{{ column_index }}]"
+ size="40"
+ class="textfield"
+ id="field_{{ column_index }}">
+ {% if in_fbs %}
+ {% set edit_url = 'gis_data_editor.php' ~ get_common() %}
+ {% set edit_str = get_icon('b_edit', 'Edit/Insert'|trans) %}
+ <span class="open_search_gis_editor">
+ {{ link_or_button(edit_url, edit_str, [], '_blank') }}
+ </span>
+ {% endif %}
+{% elseif column_type starts with 'enum'
+ or (column_type starts with 'set' and in_zoom_search_edit) %}
+ {% set in_zoom_search_edit = false %}
+ {% set value = column_type|e|slice(5, -1)|replace({'&#039;': ''})|split(', ') %}
+ {% set cnt_value = value|length %}
+ {#
+ 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 (column_type starts with 'enum' and not in_zoom_search_edit)
+ or (column_type starts with 'set' and in_zoom_search_edit) %}
+ <select name="criteriaValues[{{ column_index }}]"
+ id="{{ column_id }}{{ column_index }}">
+ {% else %}
+ <select name="criteriaValues[{{ column_index }}]"
+ id="{{ column_id }}{{ column_index }}"
+ multiple="multiple"
+ size="{{ min(3, cnt_value) }}">
+ {% endif %}
+ {# Add select options #}
+ <option value=""></option>
+ {% for i in 0..cnt_value - 1 %}
+ {% if criteria_values[column_index] is defined
+ and criteria_values[column_index] is iterable
+ and value[i] in criteria_values[column_index] %}
+ <option value="{{ value[i]|raw }}" selected>
+ {{ value[i]|raw }}
+ </option>
+ {% else %}
+ <option value="{{ value[i]|raw }}">
+ {{ value[i]|raw }}
+ </option>
+ {% endif %}
+ {% endfor %}
+ </select>
+{% else %}
+ {% set the_class = 'textfield' %}
+ {% if column_type == 'date' %}
+ {% set the_class = the_class ~ ' datefield' %}
+ {% elseif column_type == 'datetime' or column_type starts with 'timestamp' %}
+ {% set the_class = the_class ~ ' datetimefield' %}
+ {% elseif column_type starts with 'bit' %}
+ {% set the_class = the_class ~ ' bit' %}
+ {% endif %}
+ <input type="text"
+ name="criteriaValues[{{ column_index }}]"
+ size="40"
+ class="{{ the_class }}"
+ id="{{ column_id }}{{ column_index }}"
+ {% if criteria_values[column_index] is defined %}
+ value="{{ criteria_values[column_index] }}"
+ {%- endif %}>
+{% endif %}
diff --git a/srcs/phpmyadmin/templates/table/search/replace_preview.twig b/srcs/phpmyadmin/templates/table/search/replace_preview.twig
new file mode 100644
index 0000000..e7a2423
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/replace_preview.twig
@@ -0,0 +1,39 @@
+<form method="post"
+ action="tbl_find_replace.php"
+ name="previewForm"
+ id="previewForm">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="replace" value="true">
+ <input type="hidden" name="columnIndex" value="{{ column_index }}">
+ <input type="hidden" name="findString" value="{{ find }}">
+ <input type="hidden" name="replaceWith" value="{{ replace_with }}">
+ <input type="hidden" name="useRegex" value="{{ use_regex }}">
+
+ <fieldset id="fieldset_find_replace_preview">
+ <legend>{% trans 'Find and replace - preview' %}</legend>
+ <table id="previewTable">
+ <thead>
+ <tr>
+ <th>{% trans 'Count' %}</th>
+ <th>{% trans 'Original string' %}</th>
+ <th>{% trans 'Replaced string' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% if result is iterable %}
+ {% for row in result %}
+ <tr>
+ <td class="right">{{ row[2] }}</td>{# count #}
+ <td>{{ row[0] }}</td>{# original #}
+ <td>{{ row[1] }}</td>{# replaced #}
+ </tr>
+ {% endfor %}
+ {% endif %}
+ </tbody>
+ </table>
+ </fieldset>
+
+ <fieldset class="tblFooters">
+ <input class="btn btn-secondary" type="submit" name="replace" value="{% trans 'Replace' %}">
+ </fieldset>
+</form>
diff --git a/srcs/phpmyadmin/templates/table/search/rows_normal.twig b/srcs/phpmyadmin/templates/table/search/rows_normal.twig
new file mode 100644
index 0000000..5e21efa
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/rows_normal.twig
@@ -0,0 +1,39 @@
+{% for column_index in 0..column_names|length - 1 %}
+ <tr class="noclick">
+ {# If 'Function' column is present trying to change comment #}
+ {% if geom_column_flag %}
+ {% include 'table/search/geom_func.twig' with {
+ 'column_index': column_index,
+ 'column_types': column_types
+ } only %}
+ {% endif %}
+ {# Displays column's name, type, collation and value #}
+ <th>
+ {{ column_names[column_index] }}
+ </th>
+ {% set properties = self.getColumnProperties(column_index, column_index) %}
+ <td dir="ltr">
+ {{ properties['type'] }}
+ </td>
+ <td>
+ {{ properties['collation'] }}
+ </td>
+ <td>
+ {{ properties['func']|raw }}
+ </td>
+ {# here, the data-type attribute is needed for a date/time picker #}
+ <td data-type="{{ properties['type'] }}">
+ {{ properties['value']|raw }}
+ {# Displays hidden fields #}
+ <input type="hidden"
+ name="criteriaColumnNames[{{ column_index }}]"
+ value="{{ column_names[column_index] }}">
+ <input type="hidden"
+ name="criteriaColumnTypes[{{ column_index }}]"
+ value="{{ column_types[column_index] }}">
+ <input type="hidden"
+ name="criteriaColumnCollations[{{ column_index }}]"
+ value="{{ column_collations[column_index] }}">
+ </td>
+ </tr>
+{% endfor %}
diff --git a/srcs/phpmyadmin/templates/table/search/rows_zoom.twig b/srcs/phpmyadmin/templates/table/search/rows_zoom.twig
new file mode 100644
index 0000000..dc46f1d
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/rows_zoom.twig
@@ -0,0 +1,74 @@
+{# Get already set search criteria (if any) #}
+{% set type = [] %}
+{% set collation = [] %}
+{% set func = [] %}
+{% set value = [] %}
+
+{% for i in 0..3 %}
+ {# After X-Axis and Y-Axis column rows, display additional criteria option #}
+ {% if i == 2 %}
+ <tr>
+ <td>
+ {% trans 'Additional search criteria' %}
+ </td>
+ </tr>
+ {% endif %}
+ <tr class="noclick">
+ <th>
+ <select name="criteriaColumnNames[]" id="tableid_{{ i }}" >
+ <option value="pma_null">
+ {% trans 'None' %}
+ </option>
+ {% for j in 0..column_names|length - 1 %}
+ {% if criteria_column_names[i] is defined
+ and criteria_column_names[i] == column_names[j] %}
+ <option value="{{ column_names[j] }}" selected="selected">
+ {{ column_names[j] }}
+ </option>
+ {% else %}
+ <option value="{{ column_names[j] }}">
+ {{ column_names[j] }}
+ </option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ </th>
+ {% if criteria_column_names[i] is defined
+ and criteria_column_names[i] != 'pma_null' %}
+ {% set key = keys[criteria_column_names[i]] %}
+ {% set properties = self.getColumnProperties(i, key) %}
+ {% set type = type|merge({i: properties['type']}) %}
+ {% set collation = collation|merge({i: properties['collation']}) %}
+ {% set func = func|merge({i: properties['func']}) %}
+ {% set value = value|merge({i: properties['value']}) %}
+ {% endif %}
+ {# Column type #}
+ <td dir="ltr">
+ {{ type[i] is defined ? type[i] }}
+ </td>
+ {# Column Collation #}
+ <td>
+ {{ collation[i] is defined ? collation[i] }}
+ </td>
+ {# Select options for column operators #}
+ <td>
+ {{ func[i] is defined ? func[i]|raw }}
+ </td>
+ {# Inputbox for search criteria value #}
+ <td>
+ </td>
+ <td>
+ {{ value[i] is defined ? value[i]|raw }}
+ {# Displays hidden fields #}
+ <input type="hidden"
+ name="criteriaColumnTypes[{{ i }}]"
+ id="types_{{ i }}"
+ {%- if criteria_column_types[i] is defined %}
+ value="{{ criteria_column_types[i] }}"
+ {%- endif %}>
+ <input type="hidden"
+ name="criteriaColumnCollations[{{ i }}]"
+ id="collations_{{ i }}">
+ </td>
+ </tr>
+{% endfor %}
diff --git a/srcs/phpmyadmin/templates/table/search/selection_form.twig b/srcs/phpmyadmin/templates/table/search/selection_form.twig
new file mode 100644
index 0000000..2ba4d60
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/selection_form.twig
@@ -0,0 +1,226 @@
+{% if search_type == 'zoom' %}
+ {% include 'table/search/form_tag.twig' with {
+ 'script_name': 'tbl_zoom_select.php',
+ 'form_id': 'zoom_search_form',
+ 'db': db,
+ 'table': table,
+ 'goto': goto
+ } only %}
+ <fieldset id="fieldset_zoom_search">
+ <fieldset id="inputSection">
+ <legend>
+ {% trans 'Do a "query by example" (wildcard: "%") for two different columns' %}
+ </legend>
+ {% include 'table/search/fields_table.twig' with {
+ 'self': self,
+ 'search_type': search_type,
+ 'geom_column_flag': geom_column_flag,
+ 'column_names': column_names,
+ 'column_types': column_types,
+ 'column_collations': column_collations,
+ 'keys' : keys,
+ 'criteria_column_names': criteria_column_names,
+ 'criteria_column_types': criteria_column_types
+ } only %}<table class="data">
+ {# Select options for data label #}
+ <tr>
+ <td>
+ <label for="dataLabel">
+ {% trans 'Use this column to label each point' %}
+ </label>
+ </td>
+ <td>
+ <select name="dataLabel" id="dataLabel" >
+ <option value = "">
+ {% trans 'None' %}
+ </option>
+ {% for i in 0..column_names|length - 1 %}
+ {% if data_label is defined and data_label == column_names[i]|e %}
+ <option value="{{ column_names[i] }}" selected="selected">
+ {{ column_names[i] }}
+ </option>
+ {% else %}
+ <option value="{{ column_names[i] }}" >
+ {{ column_names[i] }}
+ </option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ </td>
+ </tr>
+ {# Inputbox for changing default maximum rows to plot #}
+ <tr>
+ <td>
+ <label for="maxRowPlotLimit">
+ {% trans 'Maximum rows to plot' %}
+ </label>
+ </td>
+ <td>
+ <input type="number"
+ name="maxPlotLimit"
+ id="maxRowPlotLimit"
+ required="required"
+ value="{{ max_plot_limit }}">
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </fieldset>
+{% elseif search_type == 'normal' %}
+ {% include 'table/search/form_tag.twig' with {
+ 'script_name': 'tbl_select.php',
+ 'form_id': 'tbl_search_form',
+ 'db': db,
+ 'table': table,
+ 'goto': goto
+ } only %}
+ <fieldset id="fieldset_table_search">
+ <fieldset id="fieldset_table_qbe">
+ <legend>
+ {% trans 'Do a "query by example" (wildcard: "%")' %}
+ </legend>
+ <div class="responsivetable jsresponsive">
+ {% include 'table/search/fields_table.twig' with {
+ 'self': self,
+ 'search_type': search_type,
+ 'geom_column_flag': geom_column_flag,
+ 'column_names': column_names,
+ 'column_types': column_types,
+ 'column_collations': column_collations,
+ 'criteria_column_names': criteria_column_names,
+ 'criteria_column_types': criteria_column_types
+ } only %}
+ </div>
+ <div id="gis_editor"></div>
+ <div id="popup_background"></div>
+ </fieldset>
+ {% include 'div_for_slider_effect.twig' with {
+ 'id': 'searchoptions',
+ 'message': 'Options'|trans,
+ 'initial_sliders_state': default_sliders_state
+ } only %}
+
+ {# Displays columns select list for selecting distinct columns in the search #}
+ <fieldset id="fieldset_select_fields">
+ <legend>
+ {% trans 'Select columns (at least one):' %}
+ </legend>
+ <select name="columnsToDisplay[]"
+ size="{{ min(column_names|length, 10) }}"
+ multiple="multiple">
+ {% for each_field in column_names %}
+ <option value="{{ each_field }}"
+ selected="selected">
+ {{ each_field }}
+ </option>
+ {% endfor %}
+ </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>{% trans 'Or' %}</em>
+ {% trans 'Add search conditions (body of the "where" clause):' %}
+ </legend>
+ {{ show_mysql_docu('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>{% trans 'Number of rows per page' %}</legend>
+ <input type="number"
+ name="session_max_rows"
+ required="required"
+ min="1"
+ value="{{ max_rows }}"
+ class="textfield">
+ </fieldset>
+
+ {# Displays option for ordering search results by a column value (Asc or Desc) #}
+ <fieldset id="fieldset_display_order">
+ <legend>{% trans 'Display order:' %}</legend>
+ <select name="orderByColumn"><option value="--nil--"></option>
+ {% for each_field in column_names %}
+ <option value="{{ each_field }}">
+ {{ each_field }}
+ </option>
+ {% endfor %}
+ </select>
+
+ {{ get_radio_fields(
+ 'order',
+ {
+ 'ASC': 'Ascending'|trans,
+ 'DESC': 'Descending'|trans
+ },
+ 'ASC',
+ false,
+ true,
+ 'formelement'
+ ) }}
+
+ </fieldset>
+ <div class="clearfloat"></div>
+ </fieldset>
+{% elseif search_type == 'replace' %}
+ {% include 'table/search/form_tag.twig' with {
+ 'script_name': 'tbl_find_replace.php',
+ 'form_id': 'find_replace_form',
+ 'db': db,
+ 'table': table,
+ 'goto': goto
+ } only %}
+ <fieldset id="fieldset_find_replace">
+ <fieldset id="fieldset_find">
+ <legend>
+ {% trans 'Find and replace' %}
+ </legend>{% trans 'Find:' %}
+ <input type="text" value="" name="find" required>
+ {% trans 'Replace with:' %}
+ <input type="text" value="" name="replaceWith">
+
+ {% trans 'Column:' %}
+ <select name="columnIndex">
+ {% for i in 0..column_names|length - 1 %}
+ {% set type = types[column_names[i]] %}
+
+ {% if sql_types.getTypeClass(type) == 'CHAR' %}
+ <option value="{{ i }}">
+ {{- column_names[i] -}}
+ </option>
+ {% endif %}
+ {% endfor %}
+ </select>
+
+ {% include 'checkbox.twig' with {
+ 'html_field_id': 'useRegex',
+ 'html_field_name': 'useRegex',
+ 'label': 'Use regular expression'|trans,
+ 'checked': false,
+ 'onclick': false
+ } only %}
+ </fieldset>
+ </fieldset>
+{% else %}
+ {% include 'table/search/form_tag.twig' with {
+ 'script_name': '',
+ 'form_id': '',
+ 'db': db,
+ 'table': table,
+ 'goto': goto
+ } only %}
+{% endif %}
+
+{# Displays selection form's footer elements #}
+ <fieldset class="tblFooters">
+ <input class="btn btn-primary" type="submit"
+ name="{{ search_type == 'zoom' ? 'zoom_submit' : 'submit' }}"
+ {{ search_type == 'zoom' ? 'id="inputFormSubmitId"' }}
+ value="{% trans 'Go' %}">
+ </fieldset>
+</form>
+<div id="sqlqueryresultsouter"></div>
diff --git a/srcs/phpmyadmin/templates/table/search/zoom_result_form.twig b/srcs/phpmyadmin/templates/table/search/zoom_result_form.twig
new file mode 100644
index 0000000..7543f85
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/search/zoom_result_form.twig
@@ -0,0 +1,86 @@
+<form method="post" action="tbl_zoom_select.php" name="displayResultForm" id="zoom_display_form" class="ajax">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="goto" value="{{ goto }}">
+ <input type="hidden" name="back" value="tbl_zoom_select.php">
+
+ <fieldset id="displaySection">
+ <legend>{% trans 'Browse/Edit the points' %}</legend>
+
+ {# JSON encode the data(query result) #}
+ <center>
+ {% if zoom_submit and data is not empty %}
+ <div id="resizer">
+ <center>
+ <a id="help_dialog" href="#">
+ {% trans 'How to use' %}
+ </a>
+ </center>
+ <div id="querydata" class="hide">
+ {{ data_json }}
+ </div>
+ <div id="querychart"></div>
+ <button class="button-reset">
+ {% trans 'Reset zoom' %}
+ </button>
+ </div>
+ {% endif %}
+ </center>
+
+ {# Displays rows in point edit form #}
+ <div id="dataDisplay" class="hide">
+ <table>
+ <thead>
+ <tr>
+ <th>{% trans 'Column' %}</th>
+ <th>{% trans 'Null' %}</th>
+ <th>{% trans 'Value' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for column_index in 0..column_names|length - 1 %}
+ {% set field_popup = column_names[column_index] %}
+ {% set foreign_data = get_foreign_data(
+ foreigners,
+ field_popup,
+ false,
+ '',
+ ''
+ ) %}
+ <tr class="noclick">
+ <th>{{ column_names[column_index] }}</th>
+ {# Null checkbox if column can be null #}
+ <th>
+ {% if column_null_flags[column_index] == 'YES' %}
+ <input type="checkbox" class="checkbox_null"
+ name="criteriaColumnNullFlags[{{ column_index }}]"
+ id="edit_fields_null_id_{{ column_index }}">
+ {% endif %}
+ </th>
+ {# Column's Input box #}
+ <th>
+ {% include 'table/search/input_box.twig' with {
+ 'str': '',
+ 'column_type': column_types[column_index],
+ 'column_id': column_types[column_index] ? 'edit_fieldID_' : 'fieldID_',
+ 'in_zoom_search_edit': true,
+ 'foreigners': foreigners,
+ 'column_name': field_popup,
+ 'column_name_hash': column_name_hashes[field_popup],
+ 'foreign_data': foreign_data,
+ 'table': table,
+ 'column_index': column_index,
+ 'foreign_max_limit': foreign_max_limit,
+ 'criteria_values': '',
+ 'db': db,
+ 'titles': titles,
+ 'in_fbs': false
+ } only %}
+ </th>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ <input type="hidden" id="queryID" name="sql_query">
+ </fieldset>
+</form>
diff --git a/srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig b/srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig
new file mode 100644
index 0000000..d9c629c
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig
@@ -0,0 +1,31 @@
+<li class="{{ class }}">
+{% if type == 'text'
+ or type == 'blob'
+ or tbl_storage_engine == 'ARCHIVE'
+ or has_field %}
+ {{ titles['No' ~ action]|raw }}
+{% else %}
+ <a rel="samepage" class="ajax add_key print_ignore
+ {%- if has_link_class %}
+ add_primary_key_anchor
+ {%- elseif action == 'Index' %}
+ add_index_anchor
+ {%- elseif action == 'Unique' %}
+ add_unique_anchor
+ {%- elseif action == 'Spatial' %}
+ add_spatial_anchor
+ {%- endif %}" href="tbl_structure.php" data-post="{{ url_query|raw -}}
+ &amp;add_key=1&amp;sql_query=
+ {{- ('ALTER TABLE ' ~
+ backquote(table) ~
+ (is_primary ? (primary ? ' DROP PRIMARY KEY,')) ~
+ ' ' ~
+ syntax ~
+ '(' ~
+ backquote(row['Field']) ~
+ ');')|url_encode -}}
+ &amp;message_to_show={{ message|format(row['Field']|e)|url_encode }}">
+ {{ titles[action]|raw }}
+ </a>
+{% endif %}
+</li>
diff --git a/srcs/phpmyadmin/templates/table/structure/display_partitions.twig b/srcs/phpmyadmin/templates/table/structure/display_partitions.twig
new file mode 100644
index 0000000..b10a0bc
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/structure/display_partitions.twig
@@ -0,0 +1,145 @@
+<div id="partitions">
+ <fieldset>
+ <legend>
+ {% trans 'Partitions' %}
+ {{ show_mysql_docu('partitioning') }}
+ </legend>
+ {% if partitions is empty %}
+ {{ 'No partitioning defined!'|trans|notice }}
+ {% else %}
+ <p>
+ {% trans 'Partitioned by:' %}
+ <code>{{ partition_method }}({{ partition_expression }})</code>
+ </p>
+ {% if has_sub_partitions %}
+ <p>
+ {% trans 'Sub partitioned by:' %}
+ <code>{{ sub_partition_method }}({{ sub_partition_expression }})</code>
+ <p>
+ {% endif %}
+ <table>
+ <thead>
+ <tr>
+ <th colspan="2">#</th>
+ <th>{% trans 'Partition' %}</th>
+ {% if has_description %}
+ <th>{% trans 'Expression' %}</th>
+ {% endif %}
+ <th>{% trans 'Rows' %}</th>
+ <th>{% trans 'Data length' %}</th>
+ <th>{% trans 'Index length' %}</th>
+ <th>{% trans 'Comment' %}</th>
+ <th colspan="{{ range_or_list ? '7' : '6' }}">
+ {% trans 'Action' %}
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for partition in partitions %}
+ <tr class="noclick{{ has_sub_partitions ? ' marked' }}">
+ {% if has_sub_partitions %}
+ <td>{{ partition.getOrdinal() }}</td>
+ <td></td>
+ {% else %}
+ <td colspan="2">{{ partition.getOrdinal() }}</td>
+ {% endif %}
+ <th>{{ partition.getName() }}</th>
+ {% if has_description %}
+ <td>
+ <code>
+ {{- partition.getExpression() -}}
+ {{- partition.getMethod() == 'LIST' ? ' IN (' : ' < ' -}}
+ {{- partition.getDescription() -}}
+ {{- partition.getMethod() == 'LIST' ? ')' -}}
+ </code>
+ </td>
+ {% endif %}
+ <td class="value">{{ partition.getRows() }}</td>
+ <td class="value">
+ {% set data_length = format_byte_down(
+ partition.getDataLength(),
+ 3,
+ 1
+ ) %}
+ <span>{{ data_length[0] }}</span>
+ <span class="unit">{{ data_length[1] }}</span>
+ </td>
+ <td class="value">
+ {% set index_length = format_byte_down(
+ partition.getIndexLength(),
+ 3,
+ 1
+ ) %}
+ <span>{{ index_length[0] }}</span>
+ <span class="unit">{{ index_length[1] }}</span>
+ </td>
+ <td>{{ partition.getComment() }}</td>
+ {% for action, icon in action_icons %}
+ <td>
+ <a href="tbl_structure.php" data-post="{{ url_query -}}
+ &amp;partition_maintenance=1&amp;sql_query=
+ {{- ("ALTER TABLE " ~ backquote(table) ~ " " ~ action
+ ~ " PARTITION " ~ partition.getName())|url_encode }}"
+ id="partition_action_{{ action }}"
+ name="partition_action_{{ action }}"
+ class="ajax">
+ {{ icon|raw }}
+ </a>
+ </td>
+ {% endfor %}
+
+ {% if has_sub_partitions %}
+ {% for sub_partition in partition.getSubPartitions() %}
+ <tr class="noclick">
+ <td></td>
+ <td>{{ sub_partition.getOrdinal() }}</td>
+ <td>{{ sub_partition.getName() }}</td>
+ {% if has_description %}
+ <td></td>
+ {% endif %}
+ <td class="value">{{ sub_partition.getRows() }}</td>
+ <td class="value">
+ {% set data_length = format_byte_down(
+ sub_partition.getDataLength(),
+ 3,
+ 1
+ ) %}
+ <span>{{ data_length[0] }}</span>
+ <span class="unit">{{ data_length[1] }}</span>
+ </td>
+ <td class="value">
+ {% set index_length = format_byte_down(
+ sub_partition.getIndexLength(),
+ 3,
+ 1
+ ) %}
+ <span>{{ index_length[0] }}</span>
+ <span class="unit">{{ index_length[1] }}</span>
+ </td>
+ <td>{{ sub_partition.getComment() }}</td>
+ <td colspan="{{ range_or_list ? '7' : '6' }}"></td>
+ </tr>
+ {% endfor %}
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ </fieldset>
+ <fieldset class="tblFooters print_ignore">
+ <form action="tbl_structure.php" method="post">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="edit_partitioning" value="true">
+ {% if partitions is empty %}
+ <input class="btn btn-secondary" type="submit" name="edit_partitioning" value="{% trans 'Partition table' %}">
+ {% else %}
+ {{ link_or_button(remove_url, 'Remove partitioning'|trans, {
+ 'class': 'button ajax',
+ 'id': 'remove_partitioning'
+ }) }}
+ <input class="btn btn-secondary" type="submit" name="edit_partitioning" value="{% trans 'Edit partitioning' %}">
+ {% endif %}
+ </form>
+ </fieldset>
+</div>
diff --git a/srcs/phpmyadmin/templates/table/structure/display_structure.twig b/srcs/phpmyadmin/templates/table/structure/display_structure.twig
new file mode 100644
index 0000000..16e11db
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/structure/display_structure.twig
@@ -0,0 +1,516 @@
+{% extends 'table/page_with_secondary_tabs.twig' %}
+{% block content %}
+<form method="post" action="tbl_structure.php" name="fieldsForm" id="fieldsForm"
+ class="ajax{{ hide_structure_actions ? ' HideStructureActions' }}">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="table_type" value=
+ {%- if db_is_system_schema -%}
+ "information_schema"
+ {%- elseif tbl_is_view -%}
+ "view"
+ {%- else -%}
+ "table"
+ {%- endif %}>
+ <div class="responsivetable">
+ <table id="tablestructure" class="data topmargin">
+ {# Table header #}
+ <thead>
+ <tr>
+ <th class="print_ignore"></th>
+ <th>#</th>
+ <th>{% trans 'Name' %}</th>
+ <th>{% trans 'Type' %}</th>
+ <th>{% trans 'Collation' %}</th>
+ <th>{% trans 'Attributes' %}</th>
+ <th>{% trans 'Null' %}</th>
+ <th>{% trans 'Default' %}</th>
+ {% if show_column_comments -%}
+ <th>{% trans 'Comments' %}</th>
+ {%- endif %}
+ <th>{% trans 'Extra' %}</th>
+ {# @see table/structure.js, function moreOptsMenuResize() #}
+ {% if not db_is_system_schema and not tbl_is_view %}
+ <th colspan="{{ show_icons('ActionLinksMode') ? '8' : '9' -}}
+ " class="action print_ignore">{% trans 'Action' %}</th>
+ {% endif %}
+ </tr>
+ </thead>
+ <tbody>
+ {# Table body #}
+ {% set rownum = 0 %}
+ {% for row in fields %}
+ {% set rownum = rownum + 1 %}
+
+ {% set extracted_columnspec = extracted_columnspecs[rownum] %}
+ {% set field_name = row['Field']|e %}
+ {# For column comments #}
+ {% set comments = row_comments[rownum] %}
+ {# Underline commented fields and display a hover-title (CSS only) #}
+
+ <tr>
+ <td class="center print_ignore">
+ <input type="checkbox" class="checkall" name="selected_fld[]" value="{{ row['Field'] }}" id="checkbox_row_{{ rownum }}">
+ </td>
+ <td class="right">{{ rownum }}</td>
+ <th class="nowrap">
+ <label for="checkbox_row_{{ rownum }}">
+ {% if displayed_fields[rownum].comment is defined %}
+ <span class="commented_column" title="{{ displayed_fields[rownum].comment }}">{{ displayed_fields[rownum].text }}</span>
+ {% else %}
+ {{ displayed_fields[rownum].text }}
+ {% endif %}
+ {{ displayed_fields[rownum].icon|raw }}
+ </label>
+ </th>
+ <td{{ 'set' != extracted_columnspec['type'] and 'enum' != extracted_columnspec['type'] ? ' class="nowrap"' }}>
+ <bdo dir="ltr" lang="en">
+ {{ extracted_columnspec['displayed_type']|raw }}
+ {% if relation_commwork and relation_mimework and browse_mime
+ and mime_map[row['Field']]['mimetype'] is defined %}
+ <br>{% trans 'Media (MIME) type:' %} {{ mime_map[row['Field']]['mimetype']|replace({'_': '/'})|lower }}
+ {% endif %}
+ </bdo>
+ </td>
+ <td>
+ {% if row['Collation'] is not empty %}
+ <dfn title="{{ collations[row['Collation']].description }}">{{ collations[row['Collation']].name }}</dfn>
+ {% endif %}
+ </td>
+ <td class="column_attribute nowrap">{{ attributes[rownum] }}</td>
+ <td>{{ row['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td>
+ <td class="nowrap">
+ {% if row['Default'] is not null %}
+ {% if extracted_columnspec['type'] == 'bit' %}
+ {{ row['Default']|convert_bit_default_value }}
+ {% else %}
+ {{ row['Default'] }}
+ {% endif %}
+ {% elseif row['Null'] == 'YES' %}
+ <em>NULL</em>
+ {% else %}
+ <em>{% trans %}None{% context %}None for default{% endtrans %}</em>
+ {% endif %}
+ </td>
+ {% if show_column_comments %}
+ <td>
+ {{ comments }}
+ </td>
+ {% endif %}
+ <td class="nowrap">{{ row['Extra']|upper }}</td>
+ {% if not tbl_is_view and not db_is_system_schema %}
+ <td class="edit center print_ignore">
+ <a class="change_column_anchor ajax" href="tbl_structure.php
+ {{- url_query }}&amp;field={{ row['Field']|url_encode }}&amp;change_column=1">
+ {{ titles['Change']|raw }}
+ </a>
+ </td>
+ <td class="drop center print_ignore">
+ <a class="drop_column_anchor ajax" href="sql.php" data-post="{{ url_query }}&amp;sql_query=
+ {{- ('ALTER TABLE ' ~ backquote(table)
+ ~ ' DROP ' ~ backquote(row['Field']) ~ ';')|url_encode -}}
+ &amp;dropped_column={{ row['Field']|url_encode }}&amp;purge=1&amp;message_to_show=
+ {{- ('Column %s has been dropped.'|trans|format(row['Field']|e))|url_encode }}">
+ {{ titles['Drop']|raw }}
+ </a>
+ </td>
+ {% endif %}
+
+ {% if not tbl_is_view and not db_is_system_schema %}
+ {% set type = extracted_columnspec['print_type'] is not empty ? extracted_columnspec['print_type'] %}
+ <td class="print_ignore">
+ <ul class="table-structure-actions resizable-menu">
+ {% if hide_structure_actions %}
+ <li class="submenu shown">
+ <a href="#" class="tab nowrap">{{ get_icon('b_more', 'More'|trans) }}</a>
+ <ul>
+ {% endif %}
+ {# Add primary #}
+ {% include 'table/structure/action_row_in_structure_table.twig' with {
+ 'type': type,
+ 'tbl_storage_engine': tbl_storage_engine,
+ 'class': 'primary nowrap',
+ 'has_field': primary and primary.hasColumn(field_name),
+ 'has_link_class': true,
+ 'url_query': url_query,
+ 'primary': primary,
+ 'syntax': 'ADD PRIMARY KEY',
+ 'message': 'A primary key has been added on %s.'|trans,
+ 'action': 'Primary',
+ 'titles': titles,
+ 'row': row,
+ 'is_primary': true,
+ 'table': table
+ } only %}
+
+ {# Add unique #}
+ {% include 'table/structure/action_row_in_structure_table.twig' with {
+ 'type': type,
+ 'tbl_storage_engine': tbl_storage_engine,
+ 'class': 'add_unique unique nowrap',
+ 'has_field': field_name in columns_with_unique_index,
+ 'has_link_class': false,
+ 'url_query': url_query,
+ 'primary': primary,
+ 'syntax': 'ADD UNIQUE',
+ 'message': 'An index has been added on %s.'|trans,
+ 'action': 'Unique',
+ 'titles': titles,
+ 'row': row,
+ 'is_primary': false,
+ 'table': table
+ } only %}
+
+ {# Add index #}
+ {% include 'table/structure/action_row_in_structure_table.twig' with {
+ 'type': type,
+ 'tbl_storage_engine': tbl_storage_engine,
+ 'class': 'add_index nowrap',
+ 'has_field': false,
+ 'has_link_class': false,
+ 'url_query': url_query,
+ 'primary': primary,
+ 'syntax': 'ADD INDEX',
+ 'message': 'An index has been added on %s.'|trans,
+ 'action': 'Index',
+ 'titles': titles,
+ 'row': row,
+ 'is_primary': false,
+ 'table': table
+ } only %}
+
+ {# Add spatial #}
+ {% set spatial_types = [
+ 'geometry',
+ 'point',
+ 'linestring',
+ 'polygon',
+ 'multipoint',
+ 'multilinestring',
+ 'multipolygon',
+ 'geomtrycollection'
+ ] %}
+ {% include 'table/structure/action_row_in_structure_table.twig' with {
+ 'type': type,
+ 'tbl_storage_engine': tbl_storage_engine,
+ 'class': 'spatial nowrap',
+ 'has_field': type not in spatial_types and
+ (tbl_storage_engine == 'MYISAM' or mysql_int_version >= 50705),
+ 'has_link_class': false,
+ 'url_query': url_query,
+ 'primary': primary,
+ 'syntax': 'ADD SPATIAL',
+ 'message': 'An index has been added on %s.'|trans,
+ 'action': 'Spatial',
+ 'titles': titles,
+ 'row': row,
+ 'is_primary': false,
+ 'table': table
+ } only %}
+
+ {# FULLTEXT is possible on TEXT, CHAR and VARCHAR #}
+ <li class="fulltext nowrap">
+ {% if tbl_storage_engine is not empty and (
+ tbl_storage_engine == 'MYISAM'
+ or tbl_storage_engine == 'ARIA'
+ or tbl_storage_engine == 'MARIA'
+ or (tbl_storage_engine == 'INNODB' and mysql_int_version >= 50604)
+ ) and ('text' in type or 'char' in type) %}
+ <a rel="samepage" class="ajax add_key add_fulltext_anchor" href="tbl_structure.php"
+ data-post="{{- url_query|raw }}&amp;add_key=1&amp;sql_query=
+ {{- ('ALTER TABLE ' ~ backquote(table)
+ ~ ' ADD FULLTEXT(' ~ backquote(row['Field'])
+ ~ ');')|url_encode }}&amp;message_to_show=
+ {{- ('An index has been added on %s.'|trans|format(row['Field']|e))|url_encode }}">
+ {{ titles['IdxFulltext']|raw }}
+ </a>
+ {% else %}
+ {{ titles['NoIdxFulltext']|raw }}
+ {% endif %}
+ </li>
+
+ {# Distinct value action #}
+ <li class="browse nowrap">
+ <a href="sql.php" data-post="{{ url_query|raw }}&amp;sql_query=
+ {{- ('SELECT COUNT(*) AS ' ~ backquote('Rows'|trans)
+ ~ ', ' ~ backquote(row['Field'])
+ ~ ' FROM ' ~ backquote(table)
+ ~ ' GROUP BY ' ~ backquote(row['Field'])
+ ~ ' ORDER BY ' ~ backquote(row['Field']))|url_encode -}}
+ &amp;is_browse_distinct=1">
+ {{ titles['DistinctValues']|raw }}
+ </a>
+ </li>
+ {% if central_columns_work %}
+ <li class="browse nowrap">
+ {% if row['Field'] in central_list %}
+ <a href="#" class="central_columns remove_button">
+ {{ get_icon('centralColumns_delete', 'Remove from central columns'|trans) }}
+ </a>
+ {% else %}
+ <a href="#" class="central_columns add_button">
+ {{ get_icon('centralColumns_add', 'Add to central columns'|trans) }}
+ </a>
+ {% endif %}
+ </li>
+ {% endif %}
+ {% if hide_structure_actions %}
+ </ul>
+ </li>
+ {% endif %}
+ </ul>
+ </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ <div class="print_ignore">
+ {% include 'select_all.twig' with {
+ 'pma_theme_image': pma_theme_image,
+ 'text_dir': text_dir,
+ 'form_name': 'fieldsForm'
+ } only %}
+
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Browse'|trans,
+ 'b_browse',
+ 'browse'
+ ) }}
+
+ {% if not tbl_is_view and not db_is_system_schema %}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit change_columns_anchor ajax',
+ 'Change'|trans,
+ 'b_edit',
+ 'change'
+ ) }}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Drop'|trans,
+ 'b_drop',
+ 'drop'
+ ) }}
+
+ {% if tbl_storage_engine != 'ARCHIVE' %}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Primary'|trans,
+ 'b_primary',
+ 'primary'
+ ) }}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Unique'|trans,
+ 'b_unique',
+ 'unique'
+ ) }}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Index'|trans,
+ 'b_index',
+ 'index'
+ ) }}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Fulltext'|trans,
+ 'b_ftext',
+ 'ftext'
+ ) }}
+
+ {% if tbl_storage_engine is not empty and (
+ tbl_storage_engine == 'MYISAM'
+ or tbl_storage_engine == 'ARIA'
+ or tbl_storage_engine == 'MARIA') %}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Fulltext'|trans,
+ 'b_ftext',
+ 'ftext'
+ ) }}
+ {% endif %}
+
+ {% if central_columns_work %}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Add to central columns'|trans,
+ 'centralColumns_add',
+ 'add_to_central_columns'
+ ) }}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Remove from central columns'|trans,
+ 'centralColumns_delete',
+ 'remove_from_central_columns'
+ ) }}
+ {% endif %}
+ {% endif %}
+ {% endif %}
+ </div>
+</form>
+<hr class="print_ignore">
+<div id="move_columns_dialog" class="hide" title="{% trans 'Move columns' %}">
+ <p>{% trans 'Move the columns by dragging them up and down.' %}</p>
+ <form action="tbl_structure.php" name="move_column_form" id="move_column_form">
+ <div>
+ {{ get_hidden_inputs(db, table) }}
+ <ul></ul>
+ </div>
+ </form>
+</div>
+{# Work on the table #}
+<div id="structure-action-links">
+ {% if tbl_is_view and not db_is_system_schema %}
+ {% set edit_view_url = 'view_create.php' ~ edit_view_url %}
+ {{ link_or_button(
+ edit_view_url,
+ get_icon('b_edit', 'Edit view'|trans, true)
+ ) }}
+ {% endif %}
+ <a href="#" id="printView">{{ get_icon('b_print', 'Print'|trans, true) }}</a>
+ {% if not tbl_is_view and not db_is_system_schema %}
+ {# Only display propose table structure for MySQL < 8.0 #}
+ {% if mysql_int_version < 80000 or is_mariadb %}
+ <a href="sql.php" data-post="{{ url_query|raw }}&amp;session_max_rows=all&amp;sql_query=
+ {{- ('SELECT * FROM ' ~ backquote(table) ~ ' PROCEDURE ANALYSE()')|url_encode -}}
+ " style="margin-right: 0;">
+ {{ get_icon(
+ 'b_tblanalyse',
+ 'Propose table structure'|trans,
+ true
+ ) }}
+ </a>
+ {{ show_mysql_docu('procedure_analyse') }}
+ {% endif %}
+ {% if is_active %}
+ <a href="tbl_tracking.php{{ url_query|raw }}">
+ {{ get_icon('eye', 'Track table'|trans, true) }}
+ </a>
+ {% endif %}
+ <a href="#" id="move_columns_anchor">
+ {{ get_icon('b_move', 'Move columns'|trans, true) }}
+ </a>
+ <a href="normalization.php{{ url_query|raw }}">
+ {{ get_icon('normalize', 'Normalize'|trans, true) }}
+ </a>
+ {% endif %}
+ {% if tbl_is_view and not db_is_system_schema %}
+ {% if is_active %}
+ <a href="tbl_tracking.php{{ url_query|raw }}">
+ {{ get_icon('eye', 'Track view'|trans, true) }}
+ </a>
+ {% endif %}
+ {% endif %}
+</div>
+{% if not tbl_is_view and not db_is_system_schema %}
+ <form method="post" action="tbl_addfield.php" id="addColumns" name="addColumns">
+ {{ get_hidden_inputs(db, table) }}
+ {% if show_icons('ActionLinksMode') %}
+ {{ get_image('b_insrow', 'Add column'|trans) }}&nbsp;
+ {% endif %}
+ {% set num_fields -%}
+ <input type="number" name="num_fields" value="1" onfocus="this.select()" min="1" required>
+ {%- endset %}
+ {{ 'Add %s column(s)'|trans|format(num_fields)|raw }}
+ <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">
+ <option value="first" data-pos="first">
+ {% trans 'at beginning of table' %}
+ </option>
+ {% for one_column_name in columns_list %}
+ <option value="{{ one_column_name }}"
+ {{- loop.revindex0 == 0 ? ' selected="selected"' }}>
+ {{ 'after %s'|trans|format(one_column_name) }}
+ </option>
+ {% endfor %}
+ </select>
+ <input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
+ </form>
+{% endif %}
+
+{# Displays indexes #}
+{% if not tbl_is_view and not db_is_system_schema
+ and 'ARCHIVE' != tbl_storage_engine %}
+ {{ displayIndexesHtml|raw }}
+{% endif %}
+
+{# Display partition details #}
+{% if have_partitioning %}
+ {# Detect partitioning #}
+ {% if partition_names is not empty and partition_names[0] is not null %}
+ {% set first_partition = partitions[0] %}
+ {% set range_or_list = first_partition.getMethod() == 'RANGE'
+ or first_partition.getMethod() == 'RANGE COLUMNS'
+ or first_partition.getMethod() == 'LIST'
+ or first_partition.getMethod() == 'LIST COLUMNS' %}
+ {% set sub_partitions = first_partition.getSubPartitions() %}
+ {% set has_sub_partitions = first_partition.hasSubPartitions() %}
+ {% if has_sub_partitions %}
+ {% set first_sub_partition = sub_partitions[0] %}
+ {% endif %}
+
+ {% set action_icons = {
+ 'ANALYZE': get_icon('b_search', 'Analyze'|trans),
+ 'CHECK': get_icon('eye', 'Check'|trans),
+ 'OPTIMIZE': get_icon('normalize', 'Optimize'|trans),
+ 'REBUILD': get_icon('s_tbl', 'Rebuild'|trans),
+ 'REPAIR': get_icon('b_tblops', 'Repair'|trans),
+ 'TRUNCATE': get_icon('b_empty', 'Truncate'|trans),
+ } %}
+ {% if range_or_list %}
+ {% set action_icons = action_icons|merge({'DROP': get_icon('b_drop', 'Drop'|trans)}) %}
+ {% endif %}
+
+ {# open Slider Effect div #}
+ {% include 'div_for_slider_effect.twig' with {
+ 'id': 'partitions-2',
+ 'message': 'Partitions'|trans,
+ 'initial_sliders_state': default_sliders_state
+ } only %}
+
+ {% set remove_sql = 'ALTER TABLE ' ~ backquote(table) ~ ' REMOVE PARTITIONING' %}
+ {% set remove_url = 'sql.php' ~ url_query ~ '&sql_query=' ~ remove_sql|url_encode %}
+
+ {% include 'table/structure/display_partitions.twig' with {
+ 'db': db,
+ 'table': table,
+ 'url_query': url_query,
+ 'partitions': partitions,
+ 'partition_method': first_partition.getMethod(),
+ 'partition_expression': first_partition.getExpression(),
+ 'has_description': first_partition.getDescription() is not empty,
+ 'has_sub_partitions': has_sub_partitions,
+ 'sub_partition_method': has_sub_partitions ? first_sub_partition.getMethod(),
+ 'sub_partition_expression': has_sub_partitions ? first_sub_partition.getExpression(),
+ 'action_icons': action_icons,
+ 'range_or_list': range_or_list,
+ 'remove_url': remove_url
+ } only %}
+ {% else %}
+ {% include 'table/structure/display_partitions.twig' with {
+ 'db': db,
+ 'table': table
+ } only %}
+ {% endif %}
+ {# For closing Slider effect div #}
+ </div>
+{% endif %}
+
+{# Displays Space usage and row statistics #}
+{% if show_stats %}
+ {{ table_stats|raw }}
+{% endif %}
+<div class="clearfloat"></div>
+{% endblock %}
diff --git a/srcs/phpmyadmin/templates/table/structure/display_table_stats.twig b/srcs/phpmyadmin/templates/table/structure/display_table_stats.twig
new file mode 100644
index 0000000..01c74ae
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/structure/display_table_stats.twig
@@ -0,0 +1,169 @@
+<div id="tablestatistics">
+ <fieldset>
+ <legend>{% trans 'Information' %}</legend>
+ {% if showtable['TABLE_COMMENT'] %}
+ <p>
+ <strong>{% trans 'Table comments:' %}</strong>
+ {{ showtable['TABLE_COMMENT'] }}
+ </p>
+ {% endif %}
+ <a id="showusage"></a>
+
+ {% if not tbl_is_view and not db_is_system_schema %}
+ <table id="tablespaceusage" class="width100 data">
+ <caption class="tblHeaders">{% trans 'Space usage' %}</caption>
+ <tbody>
+ <tr>
+ <th class="name">{% trans 'Data' %}</th>
+ <td class="value">{{ data_size }}</td>
+ <td class="unit">{{ data_unit }}</td>
+ </tr>
+
+ {% if index_size is defined %}
+ <tr>
+ <th class="name">{% trans 'Index' %}</th>
+ <td class="value">{{ index_size }}</td>
+ <td class="unit">{{ index_unit }}</td>
+ </tr>
+ {% endif %}
+
+ {% if free_size is defined %}
+ <tr>
+ <th class="name">{% trans 'Overhead' %}</th>
+ <td class="value">{{ free_size }}</td>
+ <td class="unit">{{ free_unit }}</td>
+ </tr>
+ <tr>
+ <th class="name">{% trans 'Effective' %}</th>
+ <td class="value">{{ effect_size }}</td>
+ <td class="unit">{{ effect_unit }}</td>
+ </tr>
+ {% endif %}
+
+ {% if tot_size is defined and mergetable == false %}
+ <tr>
+ <th class="name">{% trans 'Total' %}</th>
+ <td class="value">{{ tot_size }}</td>
+ <td class="unit">{{ tot_unit }}</td>
+ </tr>
+ {% endif %}
+
+ {# Optimize link if overhead #}
+ {% if free_size is defined
+ and (tbl_storage_engine == 'MYISAM'
+ or tbl_storage_engine == 'ARIA'
+ or tbl_storage_engine == 'MARIA'
+ or tbl_storage_engine == 'BDB')
+ or (tbl_storage_engine == 'INNODB' and innodb_file_per_table == true) %}
+ <tr class="tblFooters print_ignore">
+ <td colspan="3" class="center">
+ <a href="sql.php" data-post="{{ url_query }}&amp;pos=0&amp;sql_query=
+ {{- ('OPTIMIZE TABLE ' ~ backquote(table))|url_encode }}">
+ {{ get_icon('b_tbloptimize', 'Optimize table'|trans) }}
+ </a>
+ </td>
+ </tr>
+ {% endif %}
+ </tbody>
+ </table>
+ {% endif %}
+
+ {% set avg_size = avg_size is defined ? avg_size : null %}
+ {% set avg_unit = avg_unit is defined ? avg_unit : null %}
+ <table id="tablerowstats" class="width100 data">
+ <caption class="tblHeaders">{% trans 'Row statistics' %}</caption>
+ <tbody>
+ {% if showtable['Row_format'] is defined %}
+ <tr>
+ <th class="name">{% trans 'Format' %}</th>
+ {% if showtable['Row_format'] == 'Fixed' %}
+ <td class="value">{% trans 'static' %}</td>
+ {% elseif showtable['Row_format'] == 'Dynamic' %}
+ <td class="value">{% trans 'dynamic' %}</td>
+ {% else %}
+ <td class="value">{{ showtable['Row_format'] }}</td>
+ {% endif %}
+ </tr>
+ {% endif %}
+
+ {% if showtable['Create_options'] is not empty %}
+ <tr>
+ <th class="name">{% trans 'Options' %}</th>
+ {% if showtable['Create_options'] == 'partitioned' %}
+ <td class="value">{% trans 'partitioned' %}</td>
+ {% else %}
+ <td class="value">{{ showtable['Create_options'] }}</td>
+ {% endif %}
+ </tr>
+ {% endif %}
+
+ {% if table_collation is not empty %}
+ <tr>
+ <th class="name">{% trans 'Collation' %}</th>
+ <td class="value">
+ <dfn title="{{ table_collation.description }}">
+ {{ table_collation.name }}
+ </dfn>
+ </td>
+ </tr>
+ {% endif %}
+
+ {% if not is_innodb and showtable['Rows'] is defined %}
+ <tr>
+ <th class="name">{% trans 'Rows' %}</th>
+ <td class="value">{{ format_number(showtable['Rows'], 0) }}</td>
+ </tr>
+ {% endif %}
+
+ {% if not is_innodb
+ and showtable['Avg_row_length'] is defined
+ and showtable['Avg_row_length'] > 0 %}
+ <tr>
+ <th class="name">{% trans 'Row length' %}</th>
+ {% set avg_row_length = format_byte_down(showtable['Avg_row_length'], 6, 1) %}
+ <td class="value">{{ avg_row_length[0] }} {{ avg_row_length[1] }}</td>
+ </tr>
+ {% endif %}
+
+ {% if not is_innodb
+ and showtable['Data_length'] is defined
+ and showtable['Rows'] is defined
+ and showtable['Rows'] > 0
+ and mergetable == false %}
+ <tr>
+ <th class="name">{% trans 'Row size' %}</th>
+ <td class="value">{{ avg_size }} {{ avg_unit }}</td>
+ </tr>
+ {% endif %}
+
+ {% if showtable['Auto_increment'] is defined %}
+ <tr>
+ <th class="name">{% trans 'Next autoindex' %}</th>
+ <td class="value">{{ format_number(showtable['Auto_increment'], 0) }}</td>
+ </tr>
+ {% endif %}
+
+ {% if showtable['Create_time'] is defined %}
+ <tr>
+ <th class="name">{% trans 'Creation' %}</th>
+ <td class="value">{{ localised_date(showtable['Create_time']|date('U')) }}</td>
+ </tr>
+ {% endif %}
+
+ {% if showtable['Update_time'] is defined %}
+ <tr>
+ <th class="name">{% trans 'Last update' %}</th>
+ <td class="value">{{ localised_date(showtable['Update_time']|date('U')) }}</td>
+ </tr>
+ {% endif %}
+
+ {% if showtable['Check_time'] is defined %}
+ <tr>
+ <th class="name">{% trans 'Last check' %}</th>
+ <td class="value">{{ localised_date(showtable['Check_time']|date('U')) }}</td>
+ </tr>
+ {% endif %}
+ </tbody>
+ </table>
+ </fieldset>
+</div>
diff --git a/srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig b/srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig
new file mode 100644
index 0000000..7cf5e8d
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig
@@ -0,0 +1,14 @@
+<form action="tbl_structure.php" method="post">
+ {{ get_hidden_inputs(db, table) }}
+ <input type="hidden" name="edit_partitioning" value="true">
+
+ <fieldset>
+ <legend>{% trans 'Edit partitioning' %}</legend>
+ {% include 'columns_definitions/partitions.twig' with {
+ 'partition_details': partition_details
+ } only %}
+ </fieldset>
+ <fieldset class="tblFooters">
+ <input class="btn btn-primary" type="submit" name="save_partitioning" value="{% trans 'Save' %}">
+ </fieldset>
+</form>
diff --git a/srcs/phpmyadmin/templates/table/tracking/main.twig b/srcs/phpmyadmin/templates/table/tracking/main.twig
new file mode 100644
index 0000000..ff6c5c4
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/tracking/main.twig
@@ -0,0 +1,132 @@
+{% if selectable_tables_num_rows > 0 %}
+ <form method="post" action="tbl_tracking.php{{ url_query|raw }}">
+ {{ get_hidden_inputs(db, table) }}
+ <select name="table" class="autosubmit">
+ {% for entry in selectable_tables_entries %}
+ <option value="{{ entry.table_name }}"
+ {{- entry.table_name == selected_table ? ' selected' }}>
+ {{ entry.db_name }}.{{ entry.table_name }}
+ {% if entry.is_tracked %}
+ ({% trans 'active' %})
+ {% else %}
+ ({% trans 'not active' %})
+ {% endif %}
+ </option>
+ {% endfor %}
+ </select>
+ <input type="hidden" name="show_versions_submit" value="1">
+ </form>
+{% endif %}
+<br>
+{% if last_version > 0 %}
+ <form method="post" action="tbl_tracking.php" name="versionsForm" id="versionsForm" class="ajax">
+ {{ get_hidden_inputs(db, table) }}
+ <table id="versions" class="data">
+ <thead>
+ <tr>
+ <th></th>
+ <th>{% trans 'Version' %}</th>
+ <th>{% trans 'Created' %}</th>
+ <th>{% trans 'Updated' %}</th>
+ <th>{% trans 'Status' %}</th>
+ <th>{% trans 'Action' %}</th>
+ <th>{% trans 'Show' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for version in versions %}
+ <tr>
+ <td class="center">
+ <input type="checkbox" name="selected_versions[]"
+ class="checkall" id="selected_versions_{{- version['version']|escape }}"
+ value="{{- version['version']|escape }}">
+ </td>
+ <td class="floatright">
+ <label for="selected_versions_{{- version['version']|escape }}">
+ <b>{{ version['version']|escape }}</b>
+ </label>
+ </td>
+ <td>{{ version['date_created']|escape }}</td>
+ <td>{{ version['date_updated']|escape }}</td>
+ {% if version['tracking_active'] == 1 %}
+ {% set last_version_status = 1 %}
+ <td>{% trans 'active' %}</td>
+ {% else %}
+ {% set last_version_status = 0 %}
+ <td>{% trans 'not active' %}</td>
+ {% endif %}
+ <td>
+ <a class="delete_version_anchor ajax" href="tbl_tracking.php" data-post="
+ {{- get_common(url_params|merge({
+ 'version': version['version'],
+ 'submit_delete_version': true
+ }), '') }}">
+ {{ get_icon('b_drop', 'Delete version'|trans) }}
+ </a>
+ </td>
+ <td>
+ <a href="tbl_tracking.php" data-post="
+ {{- get_common(url_params|merge({
+ 'version': version['version'],
+ 'report': 'true'
+ }), '') }}">
+ {{ get_icon('b_report', 'Tracking report'|trans) }}
+ </a>
+ <a href="tbl_tracking.php" data-post="
+ {{- get_common(url_params|merge({
+ 'version': version['version'],
+ 'snapshot': 'true'
+ }), '') }}">
+ {{ get_icon('b_props', 'Structure snapshot'|trans) }}
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% include 'select_all.twig' with {
+ 'pma_theme_image': pmaThemeImage,
+ 'text_dir': text_dir,
+ 'form_name': 'versionsForm',
+ } only %}
+ {{ get_button_or_image(
+ 'submit_mult',
+ 'mult_submit',
+ 'Delete version'|trans,
+ 'b_drop',
+ 'delete_version'
+ ) }}
+ </form>
+ {% set last_version_element = versions|first %}
+ <div>
+ <form method="post" action="tbl_tracking.php{{ url_query|raw }}">
+ {{ get_hidden_inputs(db, table) }}
+ <fieldset>
+ <legend>
+ {% if last_version_element['tracking_active'] == 0 %}
+ {% set legend = 'Activate tracking for %s'|trans %}
+ {% set value = 'activate_now' %}
+ {% set button = 'Activate now'|trans %}
+ {% else %}
+ {% set legend = 'Deactivate tracking for %s'|trans %}
+ {% set value = 'deactivate_now' %}
+ {% set button = 'Deactivate now'|trans %}
+ {% endif %}
+
+ {{ legend|format(db ~ '.' ~ table) }}
+ </legend>
+ <input type="hidden" name="version" value="{{ last_version }}">
+ <input type="hidden" name="toggle_activation" value="{{ value }}">
+ <input class="btn btn-secondary" type="submit" value="{{ button }}">
+ </fieldset>
+ </form>
+ </div>
+{% endif %}
+{% include 'create_tracking_version.twig' with {
+ 'url_query': url_query,
+ 'last_version': last_version,
+ 'db': db,
+ 'selected': [table],
+ 'type': type,
+ 'default_statements': default_statements,
+} only %}
diff --git a/srcs/phpmyadmin/templates/table/tracking/report_table.twig b/srcs/phpmyadmin/templates/table/tracking/report_table.twig
new file mode 100644
index 0000000..fe00526
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/tracking/report_table.twig
@@ -0,0 +1,27 @@
+<table id="{{ table_id }}" class="data">
+ <thead>
+ <tr>
+ <th>{% trans %}#{% context %}Number{% endtrans %}</th>
+ <th>{% trans 'Date' %}</th>
+ <th>{% trans 'Username' %}</th>
+ <th>{{ header_message }}</th>
+ <th>{% trans 'Action' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for entry in entries %}
+ <tr class="noclick">
+ <td class="right"><small>{{ entry.line_number }}</small></td>
+ <td><small>{{ entry.date }}</small></td>
+ <td><small>{{ entry.username }}</small></td>
+ <td>{{ entry.formated_statement|raw }}</td>
+ <td class="nowrap">
+ <a class="delete_entry_anchor ajax" href="tbl_tracking.php" data-post="
+ {{- entry.url_params|raw }}">
+ {{ drop_image_or_text|raw }}
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
diff --git a/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig
new file mode 100644
index 0000000..4ef8c21
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig
@@ -0,0 +1,56 @@
+<h3>{% trans 'Structure' %}</h3>
+<table id="tablestructure" class="data">
+ <thead>
+ <tr>
+ <th>{% trans %}#{% context %}Number{% endtrans %}</th>
+ <th>{% trans 'Column' %}</th>
+ <th>{% trans 'Type' %}</th>
+ <th>{% trans 'Collation' %}</th>
+ <th>{% trans 'Null' %}</th>
+ <th>{% trans 'Default' %}</th>
+ <th>{% trans 'Extra' %}</th>
+ <th>{% trans 'Comment' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% set index = 1 %}
+ {% for field in columns %}
+ <tr class="noclick">
+ <td>{{ index }}</td>
+ {% set index = index + 1 %}
+ <td>
+ <strong>
+ {{ field['Field'] }}
+ {% if field['Key'] == 'PRI' %}
+ {{ get_image('b_primary', 'Primary'|trans) }}
+ {% elseif field['Key'] is not empty %}
+ {{ get_image('bd_primary', 'Index'|trans) }}
+ {% endif %}
+ </strong>
+ </td>
+ <td>{{ field['Type'] }}</td>
+ <td>{{ field['Collation'] }}</td>
+ <td>{{ field['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td>
+ <td>
+ {% if field['Default'] is defined %}
+ {% set extracted_columnspec = extract_column_spec(field['Type']) %}
+ {% if extracted_columnspec['type'] == 'bit' %}
+ {# here, $field['Default'] contains something like b'010' #}
+ {{ field['Default']|convert_bit_default_value }}
+ {% else %}
+ {{ field['Default'] }}
+ {% endif %}
+ {% else %}
+ {% if field['Null'] == 'YES' %}
+ <em>NULL</em>
+ {% else %}
+ <em>{% trans %}None{% context %}None for default{% endtrans %}</em>
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>{{ field['Extra'] }}</td>
+ <td>{{ field['Comment'] }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
diff --git a/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig
new file mode 100644
index 0000000..a919252
--- /dev/null
+++ b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig
@@ -0,0 +1,33 @@
+<h3>{% trans 'Indexes' %}</h3>
+<table id="tablestructure_indexes" class="data">
+ <thead>
+ <tr>
+ <th>{% trans 'Keyname' %}</th>
+ <th>{% trans 'Type' %}</th>
+ <th>{% trans 'Unique' %}</th>
+ <th>{% trans 'Packed' %}</th>
+ <th>{% trans 'Column' %}</th>
+ <th>{% trans 'Cardinality' %}</th>
+ <th>{% trans 'Collation' %}</th>
+ <th>{% trans 'Null' %}</th>
+ <th>{% trans 'Comment' %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for index in indexes %}
+ <tr class="noclick">
+ <td>
+ <strong>{{ index['Key_name'] }}</strong>
+ </td>
+ <td>{{ index['Index_type'] }}</td>
+ <td>{{ index['Non_unique'] == 0 ? 'Yes'|trans : 'No'|trans }}</td>
+ <td>{{ index['Packed'] != '' ? 'Yes'|trans : 'No'|trans }}</td>
+ <td>{{ index['Column_name'] }}</td>
+ <td>{{ index['Cardinality'] }}</td>
+ <td>{{ index['Collation'] }}</td>
+ <td>{{ index['Null'] }}</td>
+ <td>{{ index['Comment'] }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>