/**
* @package akeebabackup
* @copyright Copyright (c)2006-2025 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
"use strict";
// Object initialisation
if (typeof akeebabackup == "undefined")
{
var akeebabackup = {};
}
if (typeof akeebabackup.Dbfilters == "undefined")
{
akeebabackup.Dbfilters = {
currentRoot: null
}
}
akeebabackup.Dbfilters.activeRootChanged = function ()
{
var elRoot = document.getElementById("active_root");
var data = {
root: elRoot.options[elRoot.selectedIndex].value
};
akeebabackup.Dbfilters.load(data);
};
akeebabackup.Dbfilters.activeTabRootChanged = function ()
{
var elRoot = document.getElementById("active_root");
akeebabackup.Dbfilters.loadTab(elRoot.options[elRoot.selectedIndex].value);
};
/**
* Loads the contents of a database
*
* @param data
*/
akeebabackup.Dbfilters.load = function (data)
{
// Add the verb to the data
data.verb = "list";
// Assemble the data array and send the AJAX request
var new_data = {
action: JSON.stringify(data)
};
akeebabackup.System.doAjax(new_data, function (response)
{
akeebabackup.Dbfilters.render(response);
}, null, false, 15000);
};
/**
* Toggles a database filter
* @param data
* @param caller
* @param callback
*/
akeebabackup.Dbfilters.toggle = function (data, caller, callback)
{
akeebabackup.Fsfilters.toggle(data, caller, callback);
};
/**
* Renders the Database Filters page
* @param data
* @return
*/
akeebabackup.Dbfilters.render = function (data)
{
akeebabackup.Dbfilters.currentRoot = data.root;
// ----- Render the tables
var aktables = document.getElementById("tables");
aktables.innerHTML = "";
for (var table in data.tables)
{
if (!data.tables.hasOwnProperty(table))
{
continue;
}
var dbef = data.tables[table];
var uielement = document.createElement("div");
uielement.className = "table-container d-flex my-1 py-1 border-bottom";
var available_filters = ["tables", "tabledata"];
for (var counter = 0; counter < available_filters.length; counter++)
{
var filter = available_filters[counter];
var ui_icon = document.createElement("span");
ui_icon.className = "table-icon-container btn btn-sm btn-light me-1 hasTooltip";
ui_icon.setAttribute("title", Joomla.Text._("COM_AKEEBABACKUP_DBFILTER_TYPE_" + filter.toUpperCase()));
switch (filter)
{
case "tables":
ui_icon.insertAdjacentHTML(
"beforeend",
"<span class=\"ak-toggle-button fa fa-ban\"></span>"
);
break;
case "tabledata":
ui_icon.insertAdjacentHTML("beforeend", "<span class=\"ak-toggle-button fa fa-database\"></span>");
break;
}
switch (dbef[filter])
{
case 2:
ui_icon.classList.remove('btn-light');
ui_icon.classList.add('btn-danger');
break;
case 1:
ui_icon.classList.remove('btn-light');
ui_icon.classList.add('btn-warning');
// Don't break; we have to add the handler!
case 0:
ui_icon.addEventListener("click", function (ui_icon, table, filter)
{
return function ()
{
var new_data = {
root: data.root,
node: table,
filter: filter,
verb: "toggle"
};
akeebabackup.Dbfilters.toggle(new_data, ui_icon);
};
}(ui_icon, table, filter))
}
uielement.appendChild(ui_icon);
}
// Add the table label
var iconclass = "akion-link";
var icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_MISC";
switch (dbef.type)
{
case "table":
iconclass = "fa fa-table";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_TABLE";
break;
case "view":
iconclass = "fa fa-th-list";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_VIEW";
break;
case "procedure":
iconclass = "fa fa-cube";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_PROCEDURE";
break;
case "function":
iconclass = "fa fa-code";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_FUNCTION";
break;
case "trigger":
iconclass = "fa fa-bolt";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_TRIGGER";
break;
case "temp":
case "memory":
iconclass = "fa fa-ghost";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_TEMP";
break;
default:
iconclass = "fa fa-question-circle";
icontip = "COM_AKEEBABACKUP_DBFILTER_TABLE_UNKNOWN";
break;
}
var uiTableNameContainer = document.createElement("span");
var uiTableSizeContainer = document.createElement("span");
var uiTableType = document.createElement("span");
var uiSeparator = document.createElement("span");
uiTableNameContainer.className = "table-name flex-grow-1";
uiTableNameContainer.textContent = table;
uiTableSizeContainer.className = "table-rowcount text-muted fst-italic";
if (dbef.rows)
{
uiTableSizeContainer.textContent = dbef.rows;
uiTableSizeContainer.setAttribute("title", Joomla.Text._("COM_AKEEBABACKUP_DBFILTER_TABLE_META_ROWCOUNT"));
}
uiTableType.className = "table-icon-container table-icon-noclick table-icon-small hasTooltip";
uiTableType.setAttribute("title", Joomla.Text._(icontip, dbef.type));
var uiTableTypeIcon = document.createElement("span");
uiTableTypeIcon.className = iconclass + ' me-2';
uiTableType.appendChild(uiTableTypeIcon);
uiSeparator.className = "table-icon-container table-icon-noclick table-icon-small";
var uiSeparatorIcon = document.createElement("span");
uiSeparatorIcon.className = "fa fa-ellipsis-v mx-2";
uiSeparatorIcon.style.color = "#cccccc";
uiSeparator.appendChild(uiSeparatorIcon);
uielement.appendChild(uiSeparator);
uielement.appendChild(uiTableType);
uielement.appendChild(uiTableNameContainer);
uielement.appendChild(uiTableSizeContainer);
// Render
aktables.appendChild(uielement);
}
};
/**
* Loads the tabular view of the Database Filter for a given root
* @param root
* @return
*/
akeebabackup.Dbfilters.loadTab = function (root)
{
var data = {
verb: "tab",
root: root
};
// Assemble the data array and send the AJAX request
var new_data = {
action: JSON.stringify(data)
};
akeebabackup.System.doAjax(new_data, function (response)
{
akeebabackup.Dbfilters.renderTab(response);
}, null, false, 15000);
};
/**
* Add a row in the tabular view of the Filesystems Filter
* @param def
* @param append_to_here
* @return
*/
akeebabackup.Dbfilters.addRow = function (def, append_to_here)
{
// Turn def.type into something human readable
var type_text = Joomla.Text._("COM_AKEEBABACKUP_DBFILTER_TYPE_" + def.type.toUpperCase());
if (type_text == null)
{
type_text = def.type;
}
var elRow = document.createElement("tr");
var elFilterType = document.createElement("td");
var elFilterItem = document.createElement("td");
elRow.className = "ak_filter_row";
// Filter title
elFilterType.className = "ak_filter_type";
elFilterType.textContent = type_text;
// Filter item
elFilterItem.className = "ak_filter_item";
// delete button, edit button, filter name
var elDeleteContainer = document.createElement("span");
var elEditContainer = document.createElement("span");
var elFilterName = document.createElement("span");
elDeleteContainer.className = "ak_filter_tab_icon_container btn btn-sm btn-danger me-2";
elDeleteContainer.addEventListener("click", function ()
{
if (def.node == "")
{
// An empty filter is normally not saved to the database; it's a new record row which has to be removed...
var elRemove = this.parentNode.parentNode;
elRemove.parentNode.removeChild(elRemove);
return;
}
var elRoot = document.getElementById("active_root");
var new_data = {
root: elRoot.options[elRoot.selectedIndex].value,
node: def.node,
filter: def.type,
verb: "remove"
};
akeebabackup.Dbfilters.toggle(new_data, this, function (response, caller)
{
if (response.success)
{
var elRemove = caller.parentNode.parentNode;
elRemove.parentNode.removeChild(elRemove);
}
});
});
var elDeleteIcon = document.createElement("span");
elDeleteIcon.className = "ak-toggle-button icon-trash deletebutton";
elDeleteContainer.appendChild(elDeleteIcon);
elEditContainer.className = "ak_filter_tab_icon_container btn btn-sm btn-primary me-2";
elEditContainer.addEventListener("click", function ()
{
// If I'm editing there's an input box appended to the parent element of this edit button
var inputBox = this.parentNode.querySelector("input");
// So, if I'm already editing quit; we mustn't show multiple edit boxes!
if (inputBox != null)
{
return;
}
// Hide the text label
this.parentNode.querySelector("span.ak_filter_name").style.display = "none";
var elInput = document.createElement("input");
elInput.className = "form-input";
elInput.setAttribute("type", "text");
elInput.setAttribute("size", 60);
elInput.value = this.parentNode.querySelector("span.ak_filter_name").textContent;
this.parentNode.appendChild(elInput);
elInput.addEventListener("blur", function ()
{
var new_value = this.value;
var that = this;
if (new_value == "")
{
// Well, if the user meant to remove the filter, let's help him!
akeebabackup.System.triggerEvent(that.parentNode.querySelector("span.deletebutton"), "click");
return;
}
// First, remove the old filter
var elRoot = document.getElementById("active_root");
var new_data = {
root: elRoot.options[elRoot.selectedIndex].value,
old_node: def.node,
new_node: new_value,
filter: def.type,
verb: "swap"
};
var elEditContainer = that.parentNode.querySelector("span.editcontainer");
akeebabackup.Dbfilters.toggle(
new_data,
elEditContainer,
function (response, caller)
{
// Remove the editor
var elFilterName = that.parentNode.querySelector("span.ak_filter_name");
elFilterName.style.display = "inline-block";
elFilterName.textContent = new_value;
that.parentNode.removeChild(that);
def.node = new_value;
}
);
});
elInput.focus();
});
var elEditIcon = document.createElement("span");
elEditIcon.className = "ak-toggle-button fa fa-edit editbutton";
elEditContainer.appendChild(elEditIcon);
elFilterName.className = "ak_filter_name";
elFilterName.textContent = def.node;
elFilterItem.appendChild(elDeleteContainer);
elFilterItem.appendChild(elEditContainer);
elFilterItem.appendChild(elFilterName);
elRow.appendChild(elFilterType);
elRow.appendChild(elFilterItem);
append_to_here.appendChild(elRow);
};
akeebabackup.Dbfilters.addNew = function (filtertype)
{
// Add a row below ourselves
var new_def = {
type: filtertype,
node: ""
};
akeebabackup.Dbfilters.addRow(new_def, document.getElementById("ak_list_table").children[1]);
var trList = document.getElementById("ak_list_table").children[1].children;
var lastTr = trList[trList.length - 1];
akeebabackup.System.triggerEvent(lastTr.querySelector("span.editbutton"), "click");
};
/**
* Renders the tabular view of the Database Filter
* @param data
* @return
*/
akeebabackup.Dbfilters.renderTab = function (data)
{
var tbody = document.getElementById("ak_list_contents");
tbody.innerHTML = "";
if (data?.list?.length)
{
data.list.forEach(def => akeebabackup.Dbfilters.addRow(def, tbody));
}
};
/**
* Activates the exclusion filters for non-CMS tables
*/
akeebabackup.Dbfilters.excludeNonCMS = function ()
{
var tables = document.getElementById("tables").children;
for (var counter = 0; counter < tables.length; counter++)
{
var element = tables[counter];
// Get the table name
var tablename = element.querySelector("span.table-name").textContent;
var prefix = tablename.substr(0, 3);
// If the prefix is not #__ it's a core table and I have to exclude it
if (prefix !== "#__")
{
var iconContainer = element.querySelector("span.table-icon-container");
var icon = iconContainer.querySelector("span.ak-toggle-button");
if (!iconContainer.classList.contains('btn-warning') && !iconContainer.classList.contains('btn-danger'))
{
akeebabackup.System.triggerEvent(icon, 'click');
}
}
}
};
/**
* Wipes out the database filters
* @return
*/
akeebabackup.Dbfilters.nuke = function ()
{
var data = {
root: akeebabackup.Dbfilters.currentRoot,
verb: "reset"
};
var new_data = {
action: JSON.stringify(data)
};
akeebabackup.System.doAjax(new_data, function (response)
{
akeebabackup.Dbfilters.render(response);
}, null, false, 15000);
};
akeebabackup.System.documentReady(function ()
{
var guiData = Joomla.getOptions("akeebabackup.Databasefilters.guiData", null);
var viewType = Joomla.getOptions("akeebabackup.Databasefilters.viewType", null);
var elActiveRoot = document.getElementById("active_root");
switch (viewType)
{
// ========== LIST VIEW (DEFAULT) ==========
case "list":
elActiveRoot.addEventListener(
"change", akeebabackup.Dbfilters.activeRootChanged
);
akeebabackup.Dbfilters.render(guiData);
document.getElementById("comAkeebaDatabasefiltersExcludeNonCMS")
.addEventListener("click", function ()
{
akeebabackup.Dbfilters.excludeNonCMS();
return false;
});
document.getElementById("comAkeebaDatabasefiltersNuke")
.addEventListener("click", function ()
{
akeebabackup.Dbfilters.nuke();
return false;
});
break;
// ========== TABULAR VIEW ==========
case "tabular":
elActiveRoot.addEventListener("change", akeebabackup.Dbfilters.activeTabRootChanged);
akeebabackup.Dbfilters.renderTab(guiData);
document.getElementById("comAkeebaDatabasefiltersAddNewTables")
.addEventListener("click", function ()
{
akeebabackup.Dbfilters.addNew("tables");
return false;
});
document.getElementById("comAkeebaDatabasefiltersAddNewTableData")
.addEventListener("click", function ()
{
akeebabackup.Dbfilters.addNew("tabledata");
return false;
});
break;
}
akeebabackup.Fsfilters.initTooltips();
});