diff --git a/README.md b/README.md index a3130edd2..c51792fe5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have! -You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.9) with **ALL** its features and **ALL** concepts totally open-source and free! +You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.10) with **ALL** its features and **ALL** concepts totally open-source and free! > Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45) @@ -140,11 +140,11 @@ TODO + *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) + *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder) + *First Build*: 30th April, 2015 -+ *Last Build*: 30th October, 2022 -+ *Version*: 3.1.9 ++ *Last Build*: 2nd November, 2022 ++ *Version*: 3.1.10 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **333093** ++ *Line count*: **333951** + *Field count*: **2004** + *File count*: **2183** + *Folder count*: **381** diff --git a/admin/README.txt b/admin/README.txt index a3130edd2..c51792fe5 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have! -You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.9) with **ALL** its features and **ALL** concepts totally open-source and free! +You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.1.10) with **ALL** its features and **ALL** concepts totally open-source and free! > Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45) @@ -140,11 +140,11 @@ TODO + *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) + *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder) + *First Build*: 30th April, 2015 -+ *Last Build*: 30th October, 2022 -+ *Version*: 3.1.9 ++ *Last Build*: 2nd November, 2022 ++ *Version*: 3.1.10 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **333093** ++ *Line count*: **333951** + *Field count*: **2004** + *File count*: **2183** + *Folder count*: **381** diff --git a/admin/assets/css/search.css b/admin/assets/css/search.css index 2731fc5aa..4e3931cb1 100644 --- a/admin/assets/css/search.css +++ b/admin/assets/css/search.css @@ -10,4 +10,28 @@ /* CSS Document */ - +.selected { + background-color:#d7d8db !important +} +tr.selected td { + background-color:#d7d8db !important +} +tr { + cursor:pointer +} +.found_code { + color: #46a546; + font-weight: bolder; +} +.search_details_title { + font-size: large; + font-weight: bolder; +} +.small_column { + padding: 2px; + text-align: center; +} +th.small_column { + padding: 2px !important; + text-align: center !important; +} diff --git a/admin/assets/js/search.js b/admin/assets/js/search.js index d82a07a7d..5262954d8 100644 --- a/admin/assets/js/search.js +++ b/admin/assets/js/search.js @@ -20,19 +20,236 @@ const doSearch = async (signal, tables) => { // load the result table const resultsTable = new DataTable('#search_results_table'); + // get the search mode + let typeSearch = modeObject.querySelector('input[type=\'radio\']:checked').value; + // set some search values let searchValue = searchObject.value; let replaceValue = replaceObject.value; // add the form data formData.append('table_name', ''); + formData.append('type_search', typeSearch); formData.append('search_value', searchValue); formData.append('replace_value', replaceValue); formData.append('match_case', matchObject.checked ? 1 : 0); formData.append('whole_word', wholeObject.checked ? 1 : 0); formData.append('regex_search', regexObject.checked ? 1 : 0); - let abort_this_search_value = false; + let abort_this_search_values = false; + + // reset the progress bar + searchProgressBarObject.style.width = '0%'; + searchProgressBarObject.innerHTML = '0%'; + + // show the progress bar + searchProgressObject.style.display = ''; + + // start search timer + startSearchTimer(); + + let total = 0; + let progress = tables.length; + let index; + + for (index = 0; index < progress; index++) { + + let tableName = tables[index]; + + // add the table name + formData.set('table_name', tableName); + + let options = { + signal: signal, + method: 'POST', // *GET, POST, PUT, DELETE, etc. + body: formData + } + + if (abort_this_search_values) { + break; + } + const response = await fetch(Url + 'doSearch', options).then(response => { + total++; + // calculate the percent + let percent = 100.0 * (total / progress); + // update the progress bar + searchProgressBarObject.style.width = percent.toFixed(2) + '%'; + searchProgressBarObject.innerHTML = percent.toFixed(2) + '%'; + // when complete hide the progress bar + if (progress == total) { + searchProgressBarObject.innerHTML = Joomla.JText._('COM_COMPONENTBUILDER_SEARCH_FINISHED_IN') + ' ' + getSearchLenght() + ' ' + Joomla.JText._('COM_COMPONENTBUILDER_SECONDS'); + setTimeout(function () { + searchProgressObject.style.display = 'none'; + }, 3000); + } + // return the json response + if (response.ok) { + return response.json(); + } + }).then((data) => { + if (typeof data.success !== 'undefined') { + UIkit.notify(data.success, {pos:'top-right', timeout : 200, status:'success'}); + //} else if (typeof data.not_found !== 'undefined') { + // UIkit.notify(data.not_found, {pos:'bottom-right', timeout : 200}); + } + if (typeof data.items !== 'undefined') { + addTableItems(resultsTable, data.items, typeSearch); + } + }).catch(error => { + console.log(error); + }); + } + } catch (error) { + console.log(error); + } finally { + // Executed regardless if we caught the error + } +}; + + +/** + * JS Function to start search timer + */ +const startSearchTimer = () => { + startSearchTime = new Date(); +}; + +/** + * JS Function to get search lenght + */ +const getSearchLenght = () => { + // set ending time + endSearchTime = new Date(); + + // get diff in ms + var timeDiff = endSearchTime - startSearchTime; + + // strip the ms + timeDiff /= 1000; + + // get seconds + return Math.round(timeDiff); +} + +/** + * JS Function to fetch selected item + */ +const getSelectedItem = async (table, row, field, line) => { + try { + // get the search mode + let mode = modeObject.querySelector('input[type=\'radio\']:checked').value; + + // build form + const formData = new FormData(); + + formData.append('field_name', field); + formData.append('row_id', row); + formData.append('table_name', table); + formData.append('search_value', searchObject.value); + formData.append('replace_value', replaceObject.value); + formData.append('match_case', matchObject.checked ? 1 : 0); + formData.append('whole_word', wholeObject.checked ? 1 : 0); + formData.append('regex_search', regexObject.checked ? 1 : 0); + + // get search value + if (mode == 1) { + // calling URL + postURL = Url + 'getSearchValue'; + } else { + // add the line value + formData.append('line_nr', line); + // calling URL + postURL = Url + 'getReplaceValue'; + } + + let options = { + method: 'POST', // *GET, POST, PUT, DELETE, etc. + body: formData + } + + const response = await fetch(postURL, options).then(response => { + if (response.ok) { + return response.json(); + } + }).then((data) => { + if (typeof data.success !== 'undefined') { + UIkit.notify(data.success, {pos:'top-right', status:'success'}); + } + if (typeof data.value !== 'undefined') { + addSelectedItem(data.value, table, row, field, line); + } + }).catch(error => { + console.log(error); + }); + } catch (error) { + console.log(error); + } finally { + // Executed regardless if we caught the error + } +}; + +/** + * JS Function to check if we should save/update the all current found items + */ +const replaceAllCheck = () => { + // load question + let question = Joomla.JText._('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_REPLACE_BALLB_SEARCH_RESULTS') + '
' + + Joomla.JText._('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_BYOU_HAVE_BEEN_WARNEDB') + '

' + + Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_THEREFORE_ABSOLUTELY_SURE_YOU_WANT_TO_CONTINUE'); + // do check + UIkit.modal.confirm(question, function () { + // we clear the table again + clearAll(); + + // show the search settings again + showSearch(); + + // clear search values + clearSearch(); + + // Create new controller and issue new request + controller = new AbortController(); + + // check if any specific table was set + let tables = []; + let table = tableObject.value; + if (table != -1) { + tables.push(table); + replaceAll(controller.signal, tables); + } else { + replaceAll(controller.signal, searchTables); + } + }); +}; + +/** + * JS Function to execute the search + */ +const replaceAll = async (signal, tables) => { + try { + // build form + const formData = new FormData(); + + // load the result table + const resultsTable = new DataTable('#search_results_table'); + + // get the search mode + let typeSearch = modeObject.querySelector('input[type=\'radio\']:checked').value; + + // set some search values + let searchValue = searchObject.value; + let replaceValue = replaceObject.value; + + // add the form data + formData.append('table_name', ''); + formData.append('type_search', typeSearch); + formData.append('search_value', searchValue); + formData.append('replace_value', replaceValue); + formData.append('match_case', matchObject.checked ? 1 : 0); + formData.append('whole_word', wholeObject.checked ? 1 : 0); + formData.append('regex_search', regexObject.checked ? 1 : 0); + + let abort_this_replace_values = false; let total = 0; let index; @@ -50,19 +267,19 @@ const doSearch = async (signal, tables) => { body: formData } - if (abort_this_search_value) { - console.log('Aborting this searchValue:' + searchValue); + if (abort_this_replace_values) { break; } - const response = await fetch(Url + 'doSearch', options).then(response => { + const response = await fetch(Url + 'replaceAll', options).then(response => { total++; if (response.ok) { return response.json(); } }).then((data) => { - if (typeof data.items !== 'undefined') { - console.log('++ Fetched for ' + searchValue + ' [' + tableName + ']'); - addTableItems(resultsTable, data.items); + if (typeof data.success !== 'undefined') { + UIkit.notify(data.success, {pos:'top-right', timeout : 200, status:'success'}); + } else if (typeof data.error !== 'undefined') { + UIkit.notify(data.error, {pos:'bottom-right', timeout : 200}); } }).catch(error => { console.log(error); @@ -76,51 +293,49 @@ const doSearch = async (signal, tables) => { }; /** - * JS Function to fetch selected item + * JS Function to check if we should save/update the current selected item */ -const getSelectedItem = async (table, row, field, line) => { +const setValueCheck = (row, field, table) => { + // load question + let question = Joomla.JText._('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_ROW') + ' (' + row + ') -> (' + field + ') ' + + Joomla.JText._('COM_COMPONENTBUILDER_FIELD_IN_THE') + ' (' + table + ') ' + Joomla.JText._('COM_COMPONENTBUILDER_TABLE') + '.

' + + Joomla.JText._('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_ARE_YOU_SURE_YOU_WANT_TO_CONTINUE'); + // do check + UIkit.modal.confirm(question, function () { + setValue(row, field, table); + }); +}; + +/** + * JS Function to set the current selected item + */ +const setValue = async (row, field, table) => { try { - // get the search mode - let mode = modeObject.querySelector('input[type=\'radio\']:checked').value; + // get the value from the editor + let value = editorObject.getValue(); // build form const formData = new FormData(); - // get search value - if (mode == 1) { - formData.append('field_name', field); - formData.append('row_id', row); - formData.append('table_name', table); - - // calling URL - getURL = Url + 'getSearchValue'; - } else { - formData.append('field_name', field); - formData.append('row_id', row); - formData.append('line_nr', line); - formData.append('table_name', table); - formData.append('search_value', searchObject.value); - formData.append('replace_value', replaceObject.value); - formData.append('match_case', matchObject.checked ? 1 : 0); - formData.append('whole_word', wholeObject.checked ? 1 : 0); - formData.append('regex_search', regexObject.checked ? 1 : 0); - - // calling URL - getURL = Url + 'getReplaceValue'; - } + formData.append('value', value); + formData.append('row_id', row); + formData.append('field_name', field); + formData.append('table_name', table); let options = { method: 'POST', // *GET, POST, PUT, DELETE, etc. body: formData } - const response = await fetch(getURL, options).then(response => { + const response = await fetch(Url + 'setValue', options).then(response => { if (response.ok) { return response.json(); } }).then((data) => { - if (typeof data.value !== 'undefined') { - addSelectedItem(data.value, table, row, field, line); + if (typeof data.success !== 'undefined') { + UIkit.notify(data.success, {pos:'top-right', status:'success'}); + clearSelectedItem(); + tableActiveObject.remove().draw(); } }).catch(error => { console.log(error); @@ -130,7 +345,7 @@ const getSelectedItem = async (table, row, field, line) => { } finally { // Executed regardless if we caught the error } -} +}; /** * JS Function to add item to the editor @@ -139,8 +354,33 @@ const addSelectedItem = async (value, table, row, field, line) => { // display area if (value.length > 1) { + // add value to editor editorObject.setValue(value); - editorNoticeObject.innerHTML = 'Table: ' + table + '(id:' + row + ') | Field: ' + field + '(line:' + line + ')'; + + // set item details notice area + itemNoticeObject.style.display = ''; + itemEditButtonObject.innerHTML = editButtonSelected; + itemTableNameObject.innerHTML = table; + itemRowIdObject.innerHTML = row; + itemFieldNameObject.innerHTML = field; + itemLineNumberObject.innerHTML = line; + // set button and editor line if we have a line number + if (typeof line == 'number') { + // show and set the save button + buttonUpdateItemObject.style.display = ''; + buttonUpdateItemObject.setAttribute('onclick',"setValueCheck(" + row + ", '" + field + "', '" + table + "');"); + + // get top of the code line + let top = editorObject.charCoords({line: line, ch: 0}, "local").top; + // scroll to the line + editorObject.scrollTo(null, top - 12); + // select the line + editorObject.setCursor(line - 1); + } else { + // no line so no data we can't save this data + buttonUpdateItemObject.setAttribute('onclick', ""); + buttonUpdateItemObject.style.display = 'none'; + } } } @@ -150,7 +390,15 @@ const addSelectedItem = async (value, table, row, field, line) => { const clearSelectedItem = async () => { // display area editorObject.setValue(''); - editorNoticeObject.innerHTML = ''; + // clear notice area + itemNoticeObject.style.display = 'none'; + itemEditButtonObject.innerHTML = '...'; + itemTableNameObject.innerHTML = '...'; + itemRowIdObject.innerHTML = '...'; + itemFieldNameObject.innerHTML = '...'; + itemLineNumberObject.innerHTML = '...'; + // clear update button + buttonUpdateItemObject.setAttribute('onclick', ''); } /** @@ -159,6 +407,9 @@ const clearSelectedItem = async () => { const clearTableItems = async () => { let table = new DataTable('#search_results_table'); table.clear().draw( true ); + + // hide the update all items + buttonUpdateAllObject.style.display = 'none'; } /** @@ -168,19 +419,43 @@ const clearAll = async () => { // clear all details clearTableItems(); clearSelectedItem(); + searchedObject.innerHTML = '....'; +} + +/** + * JS Function to clear the search and replace values + */ +const clearSearch = async () => { + // clear the search and replace values + searchObject.value = ''; + replaceObject.value = ''; } /** * JS Function to add items to the table */ -const addTableItems = async (table, items) => { +const addTableItems = async (table, items, typeSearch) => { table.rows.add(items).draw( false ); + if (typeSearch == 2) { + buttonUpdateAllObject.style.display = ''; // TODO should only show once all items are loaded + } else { + buttonUpdateAllObject.style.display = 'none'; // TODO should only show once all items are loaded + } } /** - * JS Function to execute (A) on search text change , (B) on search options changes + * JS Function to execute (A) on search/replace text change , (B) on search options changes */ const onChange = () => { + // get replace value if set + const replaceValue = replaceObject.value; + if (replaceValue.length > 0) { + // set the searched value + replacedObject.innerHTML = htmlentities(replaceValue); + } else { + replacedObject.innerHTML = ''; + } + // get search value const searchValue = searchObject.value; if (searchValue.length > 2) { // Cancel any ongoing requests @@ -189,6 +464,9 @@ const onChange = () => { // we clear the table again clearAll(); + // set the searched value + searchedObject.innerHTML = htmlentities(searchValue); + // Create new controller and issue new request controller = new AbortController(); @@ -206,3 +484,241 @@ const onChange = () => { clearAll(); } }; + +/** + * JS Function to hide search settings and show table search + */ +const showSearch = () => { + searchSettingsObject.style.display = ''; + searchDetailsObject.style.display = 'none'; + replaceDetailsObject.style.display = 'none'; + tableSearchObject.style.display = 'none'; + tableLengthObject.style.display = 'none'; +}; + +/** + * JS Function to show search settings and hide table search + */ +const hideSearch = () => { + searchSettingsObject.style.display = 'none'; + searchDetailsObject.style.display = ''; + tableSearchObject.style.display = ''; + tableLengthObject.style.display = ''; + // check if we are in replace mode + let mode = modeObject.querySelector('input[type=\'radio\']:checked').value; + if (mode == 2) { + replaceDetailsObject.style.display = ''; + } +}; + + +function htmlentities(string, quoteStyle, charset, doubleEncode) { + // discuss at: https://locutus.io/php/htmlentities/ + // original by: Kevin van Zonneveld (https://kvz.io) + // revised by: Kevin van Zonneveld (https://kvz.io) + // revised by: Kevin van Zonneveld (https://kvz.io) + // improved by: nobbler + // improved by: Jack + // improved by: RafaƂ Kukawski (https://blog.kukawski.pl) + // improved by: Dj (https://locutus.io/php/htmlentities:425#comment_134018) + // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman) + // bugfixed by: Brett Zamir (https://brett-zamir.me) + // input by: Ratheous + // note 1: function is compatible with PHP 5.2 and older + // example 1: htmlentities('Kevin & van Zonneveld') + // returns 1: 'Kevin & van Zonneveld' + // example 2: htmlentities("foo'bar","ENT_QUOTES") + // returns 2: 'foo'bar' + const hashMap = getHtmlTranslationTable('HTML_ENTITIES', quoteStyle) + string = string === null ? '' : string + '' + if (!hashMap) { + return false + } + if (quoteStyle && quoteStyle === 'ENT_QUOTES') { + hashMap["'"] = ''' + } + doubleEncode = doubleEncode === null || !!doubleEncode + const regex = new RegExp('&(?:#\\d+|#x[\\da-f]+|[a-zA-Z][\\da-z]*);|[' + + Object.keys(hashMap) + .join('') + // replace regexp special chars + .replace(/([()[\]{}\-.*+?^$|/\\])/g, '\\$1') + ']', + 'g') + return string.replace(regex, function (ent) { + if (ent.length > 1) { + return doubleEncode ? hashMap['&'] + ent.substr(1) : ent + } + return hashMap[ent] + }) +} + +function getHtmlTranslationTable(table, quoteStyle) { // eslint-disable-line camelcase + // discuss at: https://locutus.io/php/get_html_translation_table/ + // original by: Philip Peterson + // revised by: Kevin van Zonneveld (https://kvz.io) + // bugfixed by: noname + // bugfixed by: Alex + // bugfixed by: Marco + // bugfixed by: madipta + // bugfixed by: Brett Zamir (https://brett-zamir.me) + // bugfixed by: T.Wild + // improved by: KELAN + // improved by: Brett Zamir (https://brett-zamir.me) + // input by: Frank Forte + // input by: Ratheous + // note 1: It has been decided that we're not going to add global + // note 1: dependencies to Locutus, meaning the constants are not + // note 1: real constants, but strings instead. Integers are also supported if someone + // note 1: chooses to create the constants themselves. + // example 1: get_html_translation_table('HTML_SPECIALCHARS') + // returns 1: {'"': '"', '&': '&', '<': '<', '>': '>'} + + const entities = {} + const hashMap = {} + let decimal + const constMappingTable = {} + const constMappingQuoteStyle = {} + let useTable = {} + let useQuoteStyle = {} + + // Translate arguments + constMappingTable[0] = 'HTML_SPECIALCHARS' + constMappingTable[1] = 'HTML_ENTITIES' + constMappingQuoteStyle[0] = 'ENT_NOQUOTES' + constMappingQuoteStyle[2] = 'ENT_COMPAT' + constMappingQuoteStyle[3] = 'ENT_QUOTES' + + useTable = !isNaN(table) + ? constMappingTable[table] + : table + ? table.toUpperCase() + : 'HTML_SPECIALCHARS' + + useQuoteStyle = !isNaN(quoteStyle) + ? constMappingQuoteStyle[quoteStyle] + : quoteStyle + ? quoteStyle.toUpperCase() + : 'ENT_COMPAT' + + if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') { + throw new Error('Table: ' + useTable + ' not supported') + } + + entities['38'] = '&' + if (useTable === 'HTML_ENTITIES') { + entities['160'] = ' ' + entities['161'] = '¡' + entities['162'] = '¢' + entities['163'] = '£' + entities['164'] = '¤' + entities['165'] = '¥' + entities['166'] = '¦' + entities['167'] = '§' + entities['168'] = '¨' + entities['169'] = '©' + entities['170'] = 'ª' + entities['171'] = '«' + entities['172'] = '¬' + entities['173'] = '­' + entities['174'] = '®' + entities['175'] = '¯' + entities['176'] = '°' + entities['177'] = '±' + entities['178'] = '²' + entities['179'] = '³' + entities['180'] = '´' + entities['181'] = 'µ' + entities['182'] = '¶' + entities['183'] = '·' + entities['184'] = '¸' + entities['185'] = '¹' + entities['186'] = 'º' + entities['187'] = '»' + entities['188'] = '¼' + entities['189'] = '½' + entities['190'] = '¾' + entities['191'] = '¿' + entities['192'] = 'À' + entities['193'] = 'Á' + entities['194'] = 'Â' + entities['195'] = 'Ã' + entities['196'] = 'Ä' + entities['197'] = 'Å' + entities['198'] = 'Æ' + entities['199'] = 'Ç' + entities['200'] = 'È' + entities['201'] = 'É' + entities['202'] = 'Ê' + entities['203'] = 'Ë' + entities['204'] = 'Ì' + entities['205'] = 'Í' + entities['206'] = 'Î' + entities['207'] = 'Ï' + entities['208'] = 'Ð' + entities['209'] = 'Ñ' + entities['210'] = 'Ò' + entities['211'] = 'Ó' + entities['212'] = 'Ô' + entities['213'] = 'Õ' + entities['214'] = 'Ö' + entities['215'] = '×' + entities['216'] = 'Ø' + entities['217'] = 'Ù' + entities['218'] = 'Ú' + entities['219'] = 'Û' + entities['220'] = 'Ü' + entities['221'] = 'Ý' + entities['222'] = 'Þ' + entities['223'] = 'ß' + entities['224'] = 'à' + entities['225'] = 'á' + entities['226'] = 'â' + entities['227'] = 'ã' + entities['228'] = 'ä' + entities['229'] = 'å' + entities['230'] = 'æ' + entities['231'] = 'ç' + entities['232'] = 'è' + entities['233'] = 'é' + entities['234'] = 'ê' + entities['235'] = 'ë' + entities['236'] = 'ì' + entities['237'] = 'í' + entities['238'] = 'î' + entities['239'] = 'ï' + entities['240'] = 'ð' + entities['241'] = 'ñ' + entities['242'] = 'ò' + entities['243'] = 'ó' + entities['244'] = 'ô' + entities['245'] = 'õ' + entities['246'] = 'ö' + entities['247'] = '÷' + entities['248'] = 'ø' + entities['249'] = 'ù' + entities['250'] = 'ú' + entities['251'] = 'û' + entities['252'] = 'ü' + entities['253'] = 'ý' + entities['254'] = 'þ' + entities['255'] = 'ÿ' + } + + if (useQuoteStyle !== 'ENT_NOQUOTES') { + entities['34'] = '"' + } + if (useQuoteStyle === 'ENT_QUOTES') { + entities['39'] = ''' + } + entities['60'] = '<' + entities['62'] = '>' + + // ascii decimals to real symbols + for (decimal in entities) { + if (entities.hasOwnProperty(decimal)) { + hashMap[String.fromCharCode(decimal)] = entities[decimal] + } + } + + return hashMap +} diff --git a/admin/controllers/ajax.json.php b/admin/controllers/ajax.json.php index f6271d5a8..e27dd76da 100644 --- a/admin/controllers/ajax.json.php +++ b/admin/controllers/ajax.json.php @@ -1640,14 +1640,15 @@ class ComponentbuilderControllerAjax extends BaseController try { $table_nameValue = $jinput->get('table_name', NULL, 'WORD'); + $type_searchValue = $jinput->get('type_search', 1, 'INT'); $search_valueValue = $jinput->get('search_value', NULL, 'RAW'); $match_caseValue = $jinput->get('match_case', 0, 'INT'); $whole_wordValue = $jinput->get('whole_word', 0, 'INT'); $regex_searchValue = $jinput->get('regex_search', 0, 'INT'); $component_idValue = $jinput->get('component_id', 0, 'INT'); - if($table_nameValue && $user->id != 0 && $search_valueValue) + if($table_nameValue && $user->id != 0 && $type_searchValue && $search_valueValue) { - $result = $this->getModel('ajax')->doSearch($table_nameValue, $search_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue, $component_idValue); + $result = $this->getModel('ajax')->doSearch($table_nameValue, $type_searchValue, $search_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue, $component_idValue); } else { @@ -1735,9 +1736,14 @@ class ComponentbuilderControllerAjax extends BaseController $field_nameValue = $jinput->get('field_name', NULL, 'WORD'); $row_idValue = $jinput->get('row_id', NULL, 'INT'); $table_nameValue = $jinput->get('table_name', NULL, 'WORD'); - if($field_nameValue && $user->id != 0 && $row_idValue && $table_nameValue) + $search_valueValue = $jinput->get('search_value', NULL, 'RAW'); + $replace_valueValue = $jinput->get('replace_value', NULL, 'RAW'); + $match_caseValue = $jinput->get('match_case', 0, 'INT'); + $whole_wordValue = $jinput->get('whole_word', 0, 'INT'); + $regex_searchValue = $jinput->get('regex_search', 0, 'INT'); + if($field_nameValue && $user->id != 0 && $row_idValue && $table_nameValue && $search_valueValue) { - $result = $this->getModel('ajax')->getSearchValue($field_nameValue, $row_idValue, $table_nameValue); + $result = $this->getModel('ajax')->getSearchValue($field_nameValue, $row_idValue, $table_nameValue, $search_valueValue, $replace_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue); } else { diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index 2f32d3cd7..14dfa3342 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -1312,6 +1312,7 @@ COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_CONTINUE="Are you sure you w COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_REPLACE_YOUR_LOCAL_SNIPPET_WITH_THIS_JCB_COMMUNITY_SNIPPET="Are you sure you would like to replace your local snippet with this JCB community snippet?" COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_UPDATE_YOUR_LOCAL_SNIPPET_WITH_THIS_NEWER_JCB_COMMUNITY_SNIPPET="Are you sure you would like to update your local snippet with this newer JCB community snippet?" COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_UPDATE_YOUR_LOCAL_SNIPPET_WITH_THIS_OLDER_JCB_COMMUNITY_SNIPPET="Are you sure you would like to update your local snippet with this older JCB community snippet?" +COM_COMPONENTBUILDER_ARE_YOU_THEREFORE_ABSOLUTELY_SURE_YOU_WANT_TO_CONTINUE="Are you therefore absolutely sure you want to continue?" COM_COMPONENTBUILDER_AUTHOR="Author" COM_COMPONENTBUILDER_AUTHOR_EMAIL="Author Email" COM_COMPONENTBUILDER_AUTHOR_NAME="Author Name" @@ -4706,6 +4707,7 @@ COM_COMPONENTBUILDER_EDIT_CREATED_DATE="Edit Created Date" COM_COMPONENTBUILDER_EDIT_CREATED_DATE_DESC="Allows users in this group to edit created date." COM_COMPONENTBUILDER_EDIT_S="Edit %s" COM_COMPONENTBUILDER_EDIT_S_FOR_THIS_S="Edit %s for this %s" +COM_COMPONENTBUILDER_EDIT_S_S_DIRECTLY="Edit %s (%s) directly" COM_COMPONENTBUILDER_EDIT_VERSIONS="Edit Version" COM_COMPONENTBUILDER_EDIT_VERSIONS_DESC="Allows users in this group to edit versions." COM_COMPONENTBUILDER_EDIT_VIEW="Edit View" @@ -5034,6 +5036,7 @@ $mediumkey = ComponentbuilderHelper::getCryptKey('medium'); $medium = new FOFEncryptAes($mediumkey);" COM_COMPONENTBUILDER_FIELD_INITIATOR_ON_SAVE_MODEL_LABEL="Initiator
on save model" COM_COMPONENTBUILDER_FIELD_INT="INT" +COM_COMPONENTBUILDER_FIELD_IN_THE="field in the" COM_COMPONENTBUILDER_FIELD_JAVASCRIPT_VIEWS_FOOTER_DESCRIPTION="Add JavaScript for the list view that is loaded in the footer inside script tags. Do not add the script tags." COM_COMPONENTBUILDER_FIELD_JAVASCRIPT_VIEWS_FOOTER_LABEL="Javascript (list view footer)" COM_COMPONENTBUILDER_FIELD_JAVASCRIPT_VIEW_FOOTER_DESCRIPTION="Add JavaScript for the edit view that is loaded in the footer inside script tags. Do not add the script tags." @@ -5451,7 +5454,6 @@ COM_COMPONENTBUILDER_FORCE_THAT_THIS_JCB_PACKAGE_IMPORT_SEARCH_FOR_LOCAL_ITEMS_T COM_COMPONENTBUILDER_FOUND="Found" COM_COMPONENTBUILDER_FOUND_TEXT="Found Text" COM_COMPONENTBUILDER_FREEOPEN="Free/Open" -COM_COMPONENTBUILDER_FULL_TEXT="Full Text" COM_COMPONENTBUILDER_FULL_WIDTH_IN_TAB="Full Width in Tab" COM_COMPONENTBUILDER_FUNCTION_NAME_ALREADY_TAKEN_PLEASE_TRY_AGAIN="Function name already taken, please try again." COM_COMPONENTBUILDER_GENERAL_OVERVIEW_OF_HOW_THINGS_WORK_BSB="General overview of how things work: %s" @@ -5619,6 +5621,7 @@ COM_COMPONENTBUILDER_HTWOWE_COULD_NOT_OPEN_THE_PACKAGEHTWOTHIS_COULD_BE_DUE_TO_T COM_COMPONENTBUILDER_IAUTHORI_BSB="Author: %s" COM_COMPONENTBUILDER_ICOMPANYI_BSB="Company: %s" COM_COMPONENTBUILDER_ICON="Icon" +COM_COMPONENTBUILDER_ID="id" COM_COMPONENTBUILDER_ID_MISMATCH_WAS_DETECTED_WITH_THE_SSSS_GUI_CODE_FIELD_SO_THE_PLACEHOLDER_WAS_NOT_SET="ID mismatch was detected with the %s.%s.%s.%s GUI code field. So the placeholder was not set." COM_COMPONENTBUILDER_IEMAILI_BSB="Email: %s" COM_COMPONENTBUILDER_IMPORT_BY_GUID_ONLY="Import by GUID only!" @@ -5685,6 +5688,7 @@ COM_COMPONENTBUILDER_ISOLATE="Isolate" COM_COMPONENTBUILDER_IS_BEING_COMPILED="is being compiled" COM_COMPONENTBUILDER_IS_NOT_ONLY_FOUR_LISTRADIOCHECKBOXES="Is Not (only 4 list/radio/checkboxes)" COM_COMPONENTBUILDER_IS_ONLY_FOUR_LISTRADIOCHECKBOXES="Is (only 4 list/radio/checkboxes)" +COM_COMPONENTBUILDER_ITEM_CODE="Item Code" COM_COMPONENTBUILDER_IWEBSITEI_BSB="Website: %s" COM_COMPONENTBUILDER_JCB_COMMUNITY="JCB Community" COM_COMPONENTBUILDER_JCB_COMMUNITY_PACKAGES="JCB Community Packages" @@ -7748,7 +7752,7 @@ COM_COMPONENTBUILDER_LIBRARY_VERSION_DESC="A count of the number of times this L COM_COMPONENTBUILDER_LIBRARY_VERSION_LABEL="Version" COM_COMPONENTBUILDER_LICENSE="License" COM_COMPONENTBUILDER_LICENSE_S="License: %s" -COM_COMPONENTBUILDER_LINE="Line" +COM_COMPONENTBUILDER_LINE="line" COM_COMPONENTBUILDER_LINK="Link" COM_COMPONENTBUILDER_LINK_LOCAL_DYNAMIC="Link & Local (dynamic)" COM_COMPONENTBUILDER_LINK_TO_THE_CONTRIBUTOR="Link to the contributor" @@ -7803,7 +7807,7 @@ COM_COMPONENTBUILDER_NO_CRONJOB_PATH_FOUND_SINCE_INCORRECT_TYPE_REQUESTED="No cr COM_COMPONENTBUILDER_NO_DESCRIPTION_FOUND="No description found." COM_COMPONENTBUILDER_NO_FILES_LINKED="No Files Linked" COM_COMPONENTBUILDER_NO_FOUND="No Found" -COM_COMPONENTBUILDER_NO_INSTANCES_WHERE_FOUND_S="No instances where found %s" +COM_COMPONENTBUILDER_NO_INSTANCES_WHERE_FOUND_IN_S="No instances where found in %s" COM_COMPONENTBUILDER_NO_ITEM_FOUND="No Item Found" COM_COMPONENTBUILDER_NO_KEYS_WERE_FOUND_TO_ADD_AN_EXPORT_KEY_SIMPLY_OPEN_THE_COMPONENT_GO_TO_THE_TAB_CALLED_SETTINGS_BOTTOM_RIGHT_THERE_IS_A_FIELD_CALLED_EXPORT_KEY="No keys were found. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key." COM_COMPONENTBUILDER_NO_LANGUAGES_FOUND="No Languages Found" @@ -8159,6 +8163,7 @@ COM_COMPONENTBUILDER_REMOVE="Remove" COM_COMPONENTBUILDER_REMOVING_ALL_ZIP_PACKAGES_FROM_THE_TEMPORARY_FOLDER_OF_THE_JOOMLA_INSTALL="Removing all zip packages from the temporary folder of the Joomla install" COM_COMPONENTBUILDER_RENAME="Rename" COM_COMPONENTBUILDER_REPLACE="Replace" +COM_COMPONENTBUILDER_REPLACED_WITH="replaced with" COM_COMPONENTBUILDER_REPORT_AN_ISSUE_BSB="Report an issue: %s" COM_COMPONENTBUILDER_REQUIRES_THE_VALUE_ENTERED_BE_ONE_OF_THE_OPTIONS_IN_AN_ELEMENT_OF_TYPEQUOTLISTQUOT_THAT_IS_THAT_THE_ELEMENT_IS_A_SELECT_LIST="Requires the value entered be one of the options in an element of type="list": that is, that the element is a select list." COM_COMPONENTBUILDER_REQUIRES_THE_VALUE_TO_BE_A_TELEPHONE_NUMBER_COMPLYING_WITH_THE_STANDARDS_OF_NANPA_ITUT_TRECEONE_HUNDRED_AND_SIXTY_FOUR_OR_IETF_RFCFOUR_THOUSAND_NINE_HUNDRED_AND_THIRTY_THREE="Requires the value to be a Telephone number complying with the standards of nanpa, ITU-T T-REC-E.164 or ietf rfc4933." @@ -8167,19 +8172,25 @@ COM_COMPONENTBUILDER_REVERT_ALL_AHEAD_SNIPPETS="Revert All Ahead Snippets" COM_COMPONENTBUILDER_RIGHT_IN_TAB="Right in Tab" COM_COMPONENTBUILDER_RIGHT_OF_TABS="Right of Tabs" COM_COMPONENTBUILDER_RUN_EXPANSION="Run Expansion" +COM_COMPONENTBUILDER_SAVE_ALL_CHANGES_MADE_TO_THE_SELECTED_ITEM="Save all changes made to the selected item." +COM_COMPONENTBUILDER_SAVE_ITEM="Save Item" COM_COMPONENTBUILDER_SAVE_SUCCESS="Great! Item successfully saved." COM_COMPONENTBUILDER_SAVE_WARNING="The value already existed so please select another." COM_COMPONENTBUILDER_SBR_YOU_CAN_ADD_A_BGITHUB_ACCESS_TOKENB_TO_COMPONENTBUILDER_GLOBAL_OPTIONS_TO_MAKE_AUTHENTICATED_REQUESTS_TO_GITHUB_AN_ACCESS_TOKEN_WITH_ONLY_PUBLIC_ACCESS_WILL_DO_TO_RETRIEVE_S="%s
You can add a gitHub Access Token to Componentbuilder global options to make authenticated requests to gitHub. An access token with only public access will do to retrieve %s." COM_COMPONENTBUILDER_SEARCH="Search" COM_COMPONENTBUILDER_SEARCHABLE="Searchable" +COM_COMPONENTBUILDER_SEARCHED_FOR="searched for" COM_COMPONENTBUILDER_SEARCH_ACCESS="Search Access" COM_COMPONENTBUILDER_SEARCH_ACCESS_DESC="Allows the users in this group to access search." COM_COMPONENTBUILDER_SEARCH_COMPILER_BUTTON_ACCESS="Search Compiler Button Access" COM_COMPONENTBUILDER_SEARCH_COMPILER_BUTTON_ACCESS_DESC="Allows the users in this group to access the compiler button." +COM_COMPONENTBUILDER_SEARCH_DATABASE_AGAIN="Search Database Again" COM_COMPONENTBUILDER_SEARCH_DESC="JCB Search" +COM_COMPONENTBUILDER_SEARCH_FINISHED_IN="Search finished in" COM_COMPONENTBUILDER_SEARCH_OR_SEARCH_AND_REPLACE="Search, or Search and Replace" COM_COMPONENTBUILDER_SEARCH_SUBMENU="Search Submenu" COM_COMPONENTBUILDER_SEARCH_SUBMENU_DESC="Allows the users in this group to submenu of Search" +COM_COMPONENTBUILDER_SECONDS="seconds" COM_COMPONENTBUILDER_SEE_ALL_IMPORT_INFO="See All Import Info" COM_COMPONENTBUILDER_SELECTION="selection" COM_COMPONENTBUILDER_SELECT_ADMIN_VIEW="Select Admin View" @@ -9217,8 +9228,10 @@ COM_COMPONENTBUILDER_THE_URL_S_SET_TO_RETRIEVE_THE_PACKAGES_DOES_NOT_EXIST="The COM_COMPONENTBUILDER_THE_URL_S_SET_TO_RETRIEVE_THE_PACKAGES_DOES_NOT_RETURN_ANY_DATA="The url (%s) set to retrieve the packages does not return any data!" COM_COMPONENTBUILDER_THE_WIKI_CAN_ONLY_BE_LOADED_WHEN_YOUR_JCB_SYSTEM_HAS_INTERNET_CONNECTION="The wiki can only be loaded when your JCB system has internet connection." COM_COMPONENTBUILDER_THE_WIKI_IS_LOADING="The wiki is loading" -COM_COMPONENTBUILDER_THIS_AREA_IS_STILL_UNDER_DEVELOPMENT_AND_DOES_NOT_WORK="This area is still under development and does not work." +COM_COMPONENTBUILDER_THIS_AREA_IS_STILL_UNDER_DEVELOPMENT_ALTHOUGH_IT_WORKS_IT_SHOULD_BE_USED_WITH_EXTREME_CAUTION_AS_ITS_NOT_STABLE="This area is still under development, although it works, it should be used with extreme caution as its not stable." COM_COMPONENTBUILDER_THIS_BSB_IS_NOT_LINKED_TO_ANY_OTHER_AREAS_OF_JCB_AT_THIS_TIME="This %s is not linked to any other areas of JCB at this time!" +COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_ARE_YOU_SURE_YOU_WANT_TO_CONTINUE="This can not be undone, are you sure you want to continue?" +COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_BYOU_HAVE_BEEN_WARNEDB="This can not be undone, you have been warned!" COM_COMPONENTBUILDER_THIS_MAY_TAKE_A_WHILE_DEPENDING_ON_THE_SIZE_OF_YOUR_PROJECT="This may take a while depending on the size of your project." COM_COMPONENTBUILDER_THIS_PACKAGE_BPASSEDB_THE_CHECKSUM_VALIDATIONBR_BR_SMALLMANUALLY_ALSO_VALIDATE_THAT_THE_CORRECT_CHECKSUM_WAS_USEDSMALLBR_THIS_CHECKSUM_BSB_MUST_BE_THE_SAME_AS_THE_ONE_FOUND_A_S_SA="This package PASSED the checksum validation!

Manually also validate that the correct checksum was used.
This checksum: %s must be the same as the one found @ " COM_COMPONENTBUILDER_THIS_PACKAGE_HAS_NO_KEY="This package has no key." @@ -9294,7 +9307,9 @@ COM_COMPONENTBUILDER_TYPE_VALIDATION_RULE="Validation Rule" COM_COMPONENTBUILDER_UNACTIVE_ONLY_FOUR_TEXT_FIELD="Unactive (only 4 text_field)" COM_COMPONENTBUILDER_UNDERNEATH_TABS="Underneath Tabs" COM_COMPONENTBUILDER_UPDATE="Update" +COM_COMPONENTBUILDER_UPDATE_ALL="Update All" COM_COMPONENTBUILDER_UPDATE_ALL_DIVERGED_SNIPPETS="Update All Diverged Snippets" +COM_COMPONENTBUILDER_UPDATE_ALL_ITEMS_FOUND_WITH_THIS_DATABASE_SEARCH_WITH_THE_REPLACE_VALUE="Update all items found with this database search, with the replace value." COM_COMPONENTBUILDER_UPDATE_ALL_OUT_DATED_SNIPPETS="Update All Out Dated Snippets" COM_COMPONENTBUILDER_UP_TO_DATE="Up to date" COM_COMPONENTBUILDER_USAGE="Usage" @@ -9413,6 +9428,8 @@ COM_COMPONENTBUILDER_WHILE_WE_DOWNLOAD_ALL_TWENTY_SIX_COMPILER_GIF_ANIMATIONS_RA COM_COMPONENTBUILDER_WHOLE_WORD="Whole Word" COM_COMPONENTBUILDER_WIKI="Wiki" COM_COMPONENTBUILDER_YES="Yes" +COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_REPLACE_BALLB_SEARCH_RESULTS="Your are about to replace ALL search results." +COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_ROW="Your are about to update row" COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEY="Your data is encrypted with a AES 128 bit encryption using the above 32 character key." COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEY_WITHOUT_THIS_KEY_IT_WILL_TAKE_THE_CURRENT_TECHNOLOGY_WITH_A_BRUTE_FORCE_ATTACK_METHOD_MORE_THEN_A_HREFHTTPRANDOMIZECOMHOWLONGTOHACKPASS_TARGET_BLANK_TITLEHOW_LONG_TO_HACK_PASSSEVEN_HUNDRED_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZEROA_YEARS_TO_CRACK_THEORETICALLY_UNLESS_THEY_HAVE_THIS_KEY_ABOVE_SO_DO_KEEP_IT_SAFE="Your data is encrypted with a AES 128 bit encryption using the above 32 character key. Without this key it will take the current technology with a brute force attack method more then 700 000 000 000 000 000 000 000 000 000 000 years to crack theoretically. Unless they have this key above, so do keep it safe." COM_COMPONENTBUILDER_YOU_ARE_CURRENTLY_VIEWING_THE_TRASHED_ITEMS="You are currently viewing the trashed items." diff --git a/admin/models/ajax.php b/admin/models/ajax.php index 3f3320249..77c88be23 100644 --- a/admin/models/ajax.php +++ b/admin/models/ajax.php @@ -3610,6 +3610,7 @@ class ComponentbuilderModelAjax extends ListModel * Search for value in a table * * @param string $tableName The main table to search + * @param int $typeSearch The type of search being done * @param string $searchValue The value to search for * @param int $matchCase The switch to control match case * @param int $wholeWord The switch to control whole word @@ -3619,26 +3620,34 @@ class ComponentbuilderModelAjax extends ListModel * @return array|null * @since 3.2.0 **/ - public function doSearch(string $tableName, string $searchValue, + public function doSearch(string $tableName, int $typeSearch, string $searchValue, int $matchCase, int $wholeWord, int $regexSearch, int $componentId): ?array { // check if this is a valid table if (SearchFactory::_('Table')->exist($tableName)) { - // load the configurations - SearchFactory::_('Config')->table_name = $tableName; - SearchFactory::_('Config')->search_value = $searchValue; - SearchFactory::_('Config')->match_case = $matchCase; - SearchFactory::_('Config')->whole_word = $wholeWord; - SearchFactory::_('Config')->regex_search = $regexSearch; - SearchFactory::_('Config')->component_id = $componentId; - - if (($items = SearchFactory::_('Agent')->table($tableName)) !== null) + try { - return ['success' => JText::sprintf('COM_COMPONENTBUILDER_WE_FOUND_SOME_INSTANCES_IN_S', $tableName), 'items' => $items]; - } + // load the configurations + SearchFactory::_('Config')->table_name = $tableName; + SearchFactory::_('Config')->type_search = $typeSearch; + SearchFactory::_('Config')->search_value = $searchValue; + SearchFactory::_('Config')->match_case = $matchCase; + SearchFactory::_('Config')->whole_word = $wholeWord; + SearchFactory::_('Config')->regex_search = $regexSearch; + SearchFactory::_('Config')->component_id = $componentId; - return ['success' => JText::sprintf('COM_COMPONENTBUILDER_NO_INSTANCES_WHERE_FOUND_S', $tableName)]; + if (($items = SearchFactory::_('Agent')->table($tableName)) !== null) + { + return ['success' => JText::sprintf('COM_COMPONENTBUILDER_WE_FOUND_SOME_INSTANCES_IN_S', $tableName), 'items' => $items]; + } + + return ['not_found' => JText::sprintf('COM_COMPONENTBUILDER_NO_INSTANCES_WHERE_FOUND_IN_S', $tableName)]; + } + catch(Exception $error) + { + return ['error' => $error->getMessage()]; + } } return ['error' => JText::_('COM_COMPONENTBUILDER_THERE_HAS_BEEN_AN_ERROR_PLEASE_TRY_AGAIN')]; @@ -3664,18 +3673,27 @@ class ComponentbuilderModelAjax extends ListModel // check if this is a valid table if (SearchFactory::_('Table')->exist($tableName)) { - // load the configurations - SearchFactory::_('Config')->table_name = $tableName; - SearchFactory::_('Config')->search_value = $searchValue; - SearchFactory::_('Config')->replace_value = $replaceValue; - SearchFactory::_('Config')->match_case = $matchCase; - SearchFactory::_('Config')->whole_word = $wholeWord; - SearchFactory::_('Config')->regex_search = $regexSearch; - SearchFactory::_('Config')->component_id = $componentId; + try + { + // load the configurations + SearchFactory::_('Config')->table_name = $tableName; + SearchFactory::_('Config')->search_value = $searchValue; + SearchFactory::_('Config')->replace_value = $replaceValue; + SearchFactory::_('Config')->match_case = $matchCase; + SearchFactory::_('Config')->whole_word = $wholeWord; + SearchFactory::_('Config')->regex_search = $regexSearch; + SearchFactory::_('Config')->component_id = $componentId; - // SearchFactory::_('Agent')->replace(); // TODO show danger message before allowing this!!!!! - - return ['success' => JText::sprintf('COM_COMPONENTBUILDER_ALL_FOUND_INSTANCES_IN_S_WHERE_REPLACED', $tableName)]; + if (($number = SearchFactory::_('Agent')->replace()) !== 0) + { + return ['success' => JText::sprintf('COM_COMPONENTBUILDER_ALL_FOUND_INSTANCES_IN_S_WHERE_REPLACED', $tableName)]; + } + return ['not_found' => JText::sprintf('COM_COMPONENTBUILDER_NO_INSTANCES_WHERE_FOUND_IN_S', $tableName)]; + } + catch(Exception $error) + { + return ['error' => $error->getMessage()]; + } } return ['error' => JText::_('COM_COMPONENTBUILDER_THERE_HAS_BEEN_AN_ERROR_PLEASE_TRY_AGAIN')]; } @@ -3686,28 +3704,41 @@ class ComponentbuilderModelAjax extends ListModel * @param string $fieldName The field key * @param int $rowId The item ID * @param string $tableName The table + * @param string $searchValue The value to search for + * @param string|null $replaceValue The value to replace search value + * @param int $matchCase The switch to control match case + * @param int $wholeWord The switch to control whole word + * @param int $regexSearch The switch to control regex search * * @return array * @since 3.2.0 **/ - public function getSearchValue(string $fieldName, int $rowId, string $tableName): array + public function getSearchValue(string $fieldName, int $rowId, string $tableName, + string $searchValue, ?string $replaceValue = null, int $matchCase, int $wholeWord, int $regexSearch): array { // check if this is a valid table and field if ($rowId > 0 && SearchFactory::_('Table')->exist($tableName, $fieldName)) { - // load the configurations - SearchFactory::_('Config')->table_name = $tableName; - // load dummy data... TODO this should not be needed! - SearchFactory::_('Config')->search_value = ''; - SearchFactory::_('Config')->replace_value = ''; - SearchFactory::_('Config')->match_case = 0; - SearchFactory::_('Config')->whole_word = 0; - SearchFactory::_('Config')->regex_search = 0; - - if (($value = SearchFactory::_('Agent')->getValue($rowId, $fieldName, 0, $tableName)) !== null) + try { - // load the value - return ['value' => $value]; + // load the configurations + SearchFactory::_('Config')->table_name = $tableName; + SearchFactory::_('Config')->type_search = 1; + SearchFactory::_('Config')->search_value = $searchValue; + SearchFactory::_('Config')->replace_value = $replaceValue; + SearchFactory::_('Config')->match_case = $matchCase; + SearchFactory::_('Config')->whole_word = $wholeWord; + SearchFactory::_('Config')->regex_search = $regexSearch; + + if (($value = SearchFactory::_('Agent')->getValue($rowId, $fieldName, 0, $tableName)) !== null) + { + // load the value + return ['value' => $value]; + } + } + catch(Exception $error) + { + return ['error' => $error->getMessage()]; } } return ['error' => JText::_('COM_COMPONENTBUILDER_THERE_HAS_BEEN_AN_ERROR_PLEASE_TRY_AGAIN')]; @@ -3735,18 +3766,26 @@ class ComponentbuilderModelAjax extends ListModel // check if this is a valid table and field if ($rowId > 0 && SearchFactory::_('Table')->exist($tableName, $fieldName)) { - // load the configurations - SearchFactory::_('Config')->table_name = $tableName; - SearchFactory::_('Config')->search_value = $searchValue; - SearchFactory::_('Config')->replace_value = $replaceValue; - SearchFactory::_('Config')->match_case = $matchCase; - SearchFactory::_('Config')->whole_word = $wholeWord; - SearchFactory::_('Config')->regex_search = $regexSearch; - - // load the value - if (($value = SearchFactory::_('Agent')->getValue($rowId, $fieldName, $line, $tableName, true)) !== null) + try { - return ['value' => $value]; + // load the configurations + SearchFactory::_('Config')->table_name = $tableName; + SearchFactory::_('Config')->type_search = 2; + SearchFactory::_('Config')->search_value = $searchValue; + SearchFactory::_('Config')->replace_value = $replaceValue; + SearchFactory::_('Config')->match_case = $matchCase; + SearchFactory::_('Config')->whole_word = $wholeWord; + SearchFactory::_('Config')->regex_search = $regexSearch; + + // load the value + if (($value = SearchFactory::_('Agent')->getValue($rowId, $fieldName, $line, $tableName, true)) !== null) + { + return ['value' => $value]; + } + } + catch(Exception $error) + { + return ['error' => $error->getMessage()]; } } return ['error' => JText::_('COM_COMPONENTBUILDER_THERE_HAS_BEEN_AN_ERROR_PLEASE_TRY_AGAIN')]; diff --git a/admin/models/search.php b/admin/models/search.php index 5479a986c..78c11147c 100644 --- a/admin/models/search.php +++ b/admin/models/search.php @@ -148,6 +148,50 @@ class ComponentbuilderModelSearch extends ItemModel return $this->_item[$pk]; } + /** + * Custom Method + * + * @return mixed item data object on success, false on failure. + * + */ + public function getUrlValues() + { + + if (!isset($this->initSet) || !$this->initSet) + { + $this->user = JFactory::getUser(); + $this->userId = $this->user->get('id'); + $this->guest = $this->user->get('guest'); + $this->groups = $this->user->get('groups'); + $this->authorisedGroups = $this->user->getAuthorisedGroups(); + $this->levels = $this->user->getAuthorisedViewLevels(); + $this->initSet = true; + } + // Get a db connection. + $db = JFactory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + + // Get data + $data = [ + 'type_search' => SearchFactory::_('Config')->get('type_search', 1), + 'search_value' => SearchFactory::_('Config')->get('search_value', ''), + 'replace_value' => SearchFactory::_('Config')->get('replace_value', ''), + 'match_case' => SearchFactory::_('Config')->get('match_case', 0), + 'whole_word' => SearchFactory::_('Config')->get('whole_word', 0), + 'regex_search' => SearchFactory::_('Config')->get('regex_search', 0) + ]; + + if (empty($data)) + { + return false; + } + + // return data object. + return $data; + } + /** * Get the uikit needed components * diff --git a/admin/views/search/tmpl/default.php b/admin/views/search/tmpl/default.php index a85d22228..0b7c35392 100644 --- a/admin/views/search/tmpl/default.php +++ b/admin/views/search/tmpl/default.php @@ -36,8 +36,8 @@ $selectNotice .= '

' . JText::_('COM_COMPONENTBUILDER_ENTER_YOUR_SEARCH_TEXT') item->id)) ? '&id='. (int) $this->item->id : ''; ?> -