/** * @copyright (C) 2018 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ if (!Joomla) { throw new Error('Joomla API is not properly initialised'); } const allowList = { button: ['type'], input: ['type', 'name', 'placeholder', 'inputmode'], select: ['name'], option: ['value', 'selected'] }; const webInstallerOptions = { view: 'dashboard', id: 0, ordering: '', version: 'current', list: 0, options: Joomla.getOptions('plg_installer_webinstaller', {}) }; let instance; class WebInstaller { initialise() { webInstallerOptions.loaded = 1; const cancelButton = document.getElementById('uploadform-web-cancel'); cancelButton.addEventListener('click', () => { document.getElementById('uploadform-web').classList.add('hidden'); if (webInstallerOptions.list && document.querySelector('.list-view')) { document.querySelector('.list-view').click(); } }); const installButton = document.getElementById('uploadform-web-install'); installButton.addEventListener('click', () => { if (webInstallerOptions.options.installFrom === 4) { this.submitButtonUrl(); } else { this.submitButtonWeb(); } }); this.loadweb(`${webInstallerOptions.options.base_url}index.php?format=json&option=com_apps&view=dashboard`); this.clickforlinks(); } loadweb(url) { if (!url) { return false; } // eslint-disable-next-line prefer-regex-literals const pattern1 = new RegExp(webInstallerOptions.options.base_url); const pattern2 = /^index\.php/; if (!(pattern1.test(url) || pattern2.test(url))) { window.open(url, '_blank'); return false; } let requestUrl = `${url}&product=${webInstallerOptions.options.product}&release=${webInstallerOptions.options.release}&dev_level=${webInstallerOptions.options.dev_level}&list=${webInstallerOptions.list ? 'list' : 'grid'}&lang=${webInstallerOptions.options.language}`; const orderingSelect = document.getElementById('com-apps-ordering'); const versionSelect = document.getElementById('com-apps-filter-joomla-version'); if (webInstallerOptions.ordering !== '' && orderingSelect && orderingSelect.value) { webInstallerOptions.ordering = orderingSelect.value; requestUrl += `&ordering=${webInstallerOptions.ordering}`; } if (webInstallerOptions.version !== '' && versionSelect && versionSelect.value) { webInstallerOptions.version = versionSelect.value; requestUrl += `&filter_version=${webInstallerOptions.version}`; } WebInstaller.showLoadingLayer(); new Promise((resolve, reject) => { Joomla.request({ url: requestUrl, onSuccess: resp => { let response; try { response = JSON.parse(resp); } catch (error) { throw new Error('Failed to parse JSON'); } if (document.getElementById('web-loader')) { document.getElementById('web-loader').classList.add('hidden'); } const jedContainer = document.getElementById('jed-container'); jedContainer.innerHTML = Joomla.sanitizeHtml(response.data.html, allowList); document.getElementById('com-apps-searchbox').addEventListener('keypress', ({ which }) => { if (which === 13) { this.initiateSearch(); } }); document.getElementById('search-extensions').addEventListener('click', () => { this.initiateSearch(); }); document.getElementById('search-reset').addEventListener('click', () => { const searchBox = document.getElementById('com-apps-searchbox'); searchBox.value = ''; this.initiateSearch(); document.getElementById('search-reset').setAttribute('disabled', 'disabled'); }); if (document.getElementById('com-apps-searchbox').value === '') { document.getElementById('search-reset').setAttribute('disabled', 'disabled'); } document.getElementById('search-reset').innerHTML = Joomla.sanitizeHtml(Joomla.Text._('JSEARCH_FILTER_CLEAR')); // eslint-disable-next-line no-shadow const orderingSelect = document.getElementById('com-apps-ordering'); // eslint-disable-next-line no-shadow const versionSelect = document.getElementById('com-apps-filter-joomla-version'); if (orderingSelect) { orderingSelect.addEventListener('change', () => { const index = orderingSelect.selectedIndex; webInstallerOptions.ordering = orderingSelect.options[index].value; this.installfromwebajaxsubmit(); }); } if (versionSelect) { versionSelect.addEventListener('change', () => { const index = versionSelect.selectedIndex; webInstallerOptions.version = versionSelect.options[index].value; this.installfromwebajaxsubmit(); }); } if (webInstallerOptions.options.installfrom_url !== '') { WebInstaller.installfromweb(webInstallerOptions.options.installfrom_url); } resolve(); }, onError: request => { const errorContainer = document.getElementById('web-loader-error'); const loaderContainer = document.getElementById('web-loader'); if (request.responseText && errorContainer) { errorContainer.innerHTML = Joomla.sanitizeHtml(request.responseText); } if (loaderContainer) { loaderContainer.classList.add('hidden'); errorContainer.classList.remove('hidden'); } Joomla.renderMessages({ danger: [Joomla.Text._('PLG_INSTALLER_WEBINSTALLER_INSTALL_WEB_LOADING_ERROR')] }, '#web-loader-error'); reject(); } }); }).finally(() => { // Promise has been settled. // Run the following whether or not it was a success. const installAtField = document.getElementById('joomlaapsinstallatinput'); if (installAtField) { installAtField.value = webInstallerOptions.options.installat_url; } this.clickforlinks(); WebInstaller.clicker(); if (webInstallerOptions.view !== 'extension') { [].slice.call(document.querySelectorAll('div.load-extension')).forEach(element => { element.addEventListener('click', event => { event.preventDefault(); this.processLinkClick(element.getAttribute('data-url')); }); element.setAttribute('href', '#'); }); } if (webInstallerOptions.view === 'extension') { const installExtensionButton = document.getElementById('install-extension'); const installExtensionFromExternalButton = document.getElementById('install-extension-from-external'); if (installExtensionButton) { installExtensionButton.addEventListener('click', () => { WebInstaller.installfromweb(installExtensionButton.getAttribute('data-downloadurl'), installExtensionButton.getAttribute('data-name')); document.getElementById('uploadform-web-install').scrollIntoView({ behavior: 'smooth', block: 'start' }); }); } if (installExtensionFromExternalButton) { installExtensionFromExternalButton.addEventListener('click', () => { const redirectUrl = installExtensionFromExternalButton.getAttribute('data-downloadurl'); const redirectConfirm = window.confirm(Joomla.Text._('PLG_INSTALLER_WEBINSTALLER_REDIRECT_TO_EXTERNAL_SITE_TO_INSTALL').replace('[SITEURL]', redirectUrl)); if (redirectConfirm !== true) { return; } document.getElementById('adminForm').setAttribute('action', redirectUrl); document.querySelector('input[name=task]').setAttribute('disabled', true); document.querySelector('input[name=install_directory]').setAttribute('disabled', true); document.querySelector('input[name=install_url]').setAttribute('disabled', true); document.querySelector('input[name=installtype]').setAttribute('disabled', true); document.querySelector('input[name=filter_search]').setAttribute('disabled', true); document.getElementById('adminForm').submit(); }); } } if (webInstallerOptions.list && document.querySelector('.list-view')) { document.querySelector('.list-view').click(); } WebInstaller.hideLoadingLayer(); }); return true; } clickforlinks() { [].slice.call(document.querySelectorAll('a.transcode')).forEach(element => { const ajaxurl = element.getAttribute('href'); element.addEventListener('click', event => { event.preventDefault(); this.processLinkClick(ajaxurl); }); element.setAttribute('href', '#'); }); } initiateSearch() { document.getElementById('search-reset').removeAttribute('disabled'); webInstallerOptions.view = 'dashboard'; this.installfromwebajaxsubmit(); } installfromwebajaxsubmit() { let tail = `&view=${webInstallerOptions.view}`; if (webInstallerOptions.id) { tail += `&id=${webInstallerOptions.id}`; } if (document.getElementById('com-apps-searchbox').value) { const value = encodeURI(document.getElementById('com-apps-searchbox').value.toLowerCase().replace(/ +/g, '_').replace(/[^a-z0-9-_]/g, '').trim()); tail += `&filter_search=${value}`; } const orderingSelect = document.getElementById('com-apps-ordering'); const versionSelect = document.getElementById('com-apps-filter-joomla-version'); if (webInstallerOptions.ordering !== '' && orderingSelect && orderingSelect.value) { webInstallerOptions.ordering = orderingSelect.value; } if (webInstallerOptions.ordering) { tail += `&ordering=${webInstallerOptions.ordering}`; } if (webInstallerOptions.version !== '' && versionSelect && versionSelect.value) { webInstallerOptions.version = versionSelect.value; } if (webInstallerOptions.version) { tail += `&filter_version=${webInstallerOptions.version}`; } this.loadweb(`${webInstallerOptions.options.base_url}index.php?format=json&option=com_apps${tail}`); } processLinkClick(url) { const pattern1 = new RegExp(webInstallerOptions.options.base_url); const pattern2 = /^index\.php/; if (pattern1.test(url) || pattern2.test(url)) { webInstallerOptions.view = url.replace(/^.+[&?]view=(\w+).*$/, '$1'); if (webInstallerOptions.view === 'dashboard') { webInstallerOptions.id = 0; } else if (webInstallerOptions.view === 'category') { webInstallerOptions.id = url.replace(/^.+[&?]id=(\d+).*$/, '$1'); } this.loadweb(webInstallerOptions.options.base_url + url); } else { this.loadweb(url); } } static showLoadingLayer() { document.getElementById('web').appendChild(document.createElement('joomla-core-loader')); } static hideLoadingLayer() { const spinnerElement = document.querySelector('#web joomla-core-loader'); spinnerElement.parentNode.removeChild(spinnerElement); } static clicker() { if (document.querySelector('.grid-view')) { document.querySelector('.grid-view').addEventListener('click', () => { webInstallerOptions.list = 0; document.querySelector('.list-container').classList.add('hidden'); document.querySelector('.grid-container').classList.remove('hidden'); document.getElementById('btn-list-view').classList.remove('active'); document.getElementById('btn-grid-view').classList.remove('active'); }); } if (document.querySelector('.list-view')) { document.querySelector('.list-view').addEventListener('click', () => { webInstallerOptions.list = 1; document.querySelector('.grid-container').classList.add('hidden'); document.querySelector('.list-container').classList.remove('hidden'); document.getElementById('btn-grid-view').classList.remove('active'); document.getElementById('btn-list-view').classList.add('active'); }); } } /** * @param {string} installUrl * @param {string} name * @returns {boolean} */ static installfromweb(installUrl, name = null) { if (!installUrl) { Joomla.renderMessages({ warning: [Joomla.Text._('PLG_INSTALLER_WEBINSTALLER_CANNOT_INSTALL_EXTENSION_IN_PLUGIN')] }); return false; } document.getElementById('install_url').value = installUrl; document.getElementById('uploadform-web-url').innerText = installUrl; if (name) { document.getElementById('uploadform-web-name').innerText = name; document.getElementById('uploadform-web-name-label').classList.remove('hidden'); } else { document.getElementById('uploadform-web-name-label').classList.add('hidden'); } document.getElementById('uploadform-web').classList.remove('hidden'); return true; } // eslint-disable-next-line class-methods-use-this submitButtonUrl() { const form = document.getElementById('adminForm'); // do field validation if (form.install_url.value === '' || form.install_url.value === 'http://' || form.install_url.value === 'https://') { Joomla.renderMessages({ warning: [Joomla.Text._('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL')] }); } else { const loading = document.getElementById('loading'); if (loading) { loading.classList.remove('hidden'); } form.installtype.value = 'url'; form.submit(); } } submitButtonWeb() { const form = document.getElementById('adminForm'); // do field validation if (form.install_url.value !== '' || form.install_url.value !== 'http://' || form.install_url.value !== 'https://') { this.submitButtonUrl(); } else if (form.install_url.value === '') { Joomla.renderMessages({ warning: [Joomla.apps.options.btntxt] }); } else { document.querySelector('#appsloading').classList.remove('hidden'); form.installtype.value = 'web'; form.submit(); } } } customElements.whenDefined('joomla-tab').then(() => { const installerTabs = document.getElementById('myTab'); const link = installerTabs.querySelector('button[aria-controls=web]'); // Abort if the IFW tab cannot be found if (!link) { return; } if (webInstallerOptions.options.installfromon) { link.click(); } if (link.hasAttribute('aria-expanded') && link.getAttribute('aria-expanded') === 'true' && !instance) { instance = new WebInstaller(); instance.initialise(); } if (webInstallerOptions.options.installfrom_url !== '') { link.click(); } link.addEventListener('joomla.tab.shown', () => { if (!instance) { instance = new WebInstaller(); instance.initialise(); } }); });