/*
 * This file is part of the TYPO3 CMS project.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */
import"bootstrap";import $ from"jquery";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{AbstractInteractableModule}from"@typo3/install/module/abstract-interactable-module.js";import Modal from"@typo3/backend/modal.js";import Notification from"@typo3/backend/notification.js";import AjaxQueue from"@typo3/install/ajax/ajax-queue.js";import Router from"@typo3/install/router.js";class ExtensionScanner extends AbstractInteractableModule{constructor(){super(...arguments),this.listOfAffectedRestFileHashes=[],this.selectorExtensionContainer=".t3js-extensionScanner-extension",this.selectorNumberOfFiles=".t3js-extensionScanner-number-of-files",this.selectorScanSingleTrigger=".t3js-extensionScanner-scan-single",this.selectorExtensionScanButton=".t3js-extensionScanner-scan-all"}initialize(e){this.currentModal=e,this.getData(),e.on("show.bs.collapse",this.selectorExtensionContainer,(e=>{const n=$(e.currentTarget);if(void 0===n.data("scanned")){const e=n.data("extension");this.scanSingleExtension(e),n.data("scanned",!0)}})).on("typo3-modal-hide",(()=>{AjaxQueue.flush()})).on("click",this.selectorScanSingleTrigger,(e=>{e.preventDefault();const n=$(e.currentTarget).closest(this.selectorExtensionContainer).data("extension");this.scanSingleExtension(n)})).on("click",this.selectorExtensionScanButton,(n=>{n.preventDefault(),this.setModalButtonsState(!1);const t=e.find(this.selectorExtensionContainer);this.scanAll(t)}))}getData(){const e=this.getModalBody();new AjaxRequest(Router.getUrl("extensionScannerGetData")).get().then((async n=>{const t=await n.resolve();!0===t.success?(e.empty().append(t.html),Modal.setButtons(t.buttons)):Notification.error("Something went wrong","The request was not processed successfully. Please check the browser's console and TYPO3's log.")}),(n=>{Router.handleAjaxError(n,e)}))}getExtensionSelector(e){return this.selectorExtensionContainer+"-"+e}scanAll(e){this.findInModal(this.selectorExtensionContainer).removeClass("panel-danger panel-warning panel-success").find(".panel-progress-bar").css("width",0).attr("aria-valuenow",0).find("span").text("0%"),this.setProgressForAll(),e.each(((e,n)=>{const t=$(n),s=t.data("extension");this.scanSingleExtension(s),t.data("scanned",!0)}))}setStatusMessageForScan(e,n,t){this.findInModal(this.getExtensionSelector(e)).find(this.selectorNumberOfFiles).text("Checked "+n+" of "+t+" files")}setProgressForScan(e,n,t){const s=n/t*100;this.findInModal(this.getExtensionSelector(e)).find(".panel-progress-bar").css("width",s+"%").attr("aria-valuenow",s).find("span").text(s+"%")}setProgressForAll(){const e=this.findInModal(this.selectorExtensionContainer).length,n=this.findInModal(this.selectorExtensionContainer+".t3js-extensionscan-finished.panel-success").length+this.findInModal(this.selectorExtensionContainer+".t3js-extensionscan-finished.panel-warning").length+this.findInModal(this.selectorExtensionContainer+".t3js-extensionscan-finished.panel-danger").length,t=n/e*100,s=this.getModalBody();this.findInModal(".t3js-extensionScanner-progress-all-extension .progress-bar").css("width",t+"%").attr("aria-valuenow",t).find("span").text(n+" of "+e+" scanned"),n===e&&(this.findInModal(this.selectorExtensionScanButton).removeClass("disabled").prop("disabled",!1),Notification.success("Scan finished","All extensions have been scanned."),new AjaxRequest(Router.getUrl()).post({install:{action:"extensionScannerMarkFullyScannedRestFiles",token:this.getModuleContent().data("extension-scanner-mark-fully-scanned-rest-files-token"),hashes:this.uniqueArray(this.listOfAffectedRestFileHashes)}}).then((async e=>{const n=await e.resolve();!0===n.success&&Notification.success("Marked not affected files","Marked "+n.markedAsNotAffected+" ReST files as not affected.")}),(e=>{Router.handleAjaxError(e,s)})))}uniqueArray(e){return e.filter(((e,n,t)=>t.indexOf(e)===n))}scanSingleExtension(e){const n=this.getModuleContent().data("extension-scanner-files-token"),t=this.getModalBody(),s=this.findInModal(this.getExtensionSelector(e));let a=!1;s.addClass("panel-default"),s.removeClass("panel-danger panel-warning panel-success t3js-extensionscan-finished"),s.data("hasRun","true"),s.find(".t3js-extensionScanner-scan-single").text("Scanning...").attr("disabled","disabled"),s.find(".t3js-extensionScanner-extension-body-loc").empty().text("0"),s.find(".t3js-extensionScanner-extension-body-ignored-files").empty().text("0"),s.find(".t3js-extensionScanner-extension-body-ignored-lines").empty().text("0"),this.setProgressForAll(),new AjaxRequest(Router.getUrl()).post({install:{action:"extensionScannerFiles",token:n,extension:e}}).then((async n=>{const i=await n.resolve();if(!0===i.success&&Array.isArray(i.files)){const n=i.files.length;if(n<=0)return void Notification.warning("No files found","The extension "+e+" contains no scannable files");this.setStatusMessageForScan(e,0,n),s.find(".t3js-extensionScanner-extension-body").text(""),s.addClass("panel-has-progress");let o=0;i.files.forEach((i=>{AjaxQueue.add({method:"POST",data:{install:{action:"extensionScannerScanFile",token:this.getModuleContent().data("extension-scanner-scan-file-token"),extension:e,file:i}},url:Router.getUrl(),onfulfilled:async r=>{const l=await r.resolve();if(o++,this.setStatusMessageForScan(e,o,n),this.setProgressForScan(e,o,n),l.success&&$.isArray(l.matches)&&l.matches.forEach((e=>{a=!0;const n=t.find("#t3js-extensionScanner-file-hit-template").find(".panel").clone();n.find(".t3js-extensionScanner-hit-file-panel-head").attr("href","#collapse"+e.uniqueId),n.find(".t3js-extensionScanner-hit-file-panel-body").attr("id","collapse"+e.uniqueId),n.find(".t3js-extensionScanner-hit-filename").text(i),n.find(".t3js-extensionScanner-hit-message").text(e.message),"strong"===e.indicator?n.find(".t3js-extensionScanner-hit-file-panel-head .badges").append('<span class="badge badge-danger" title="Reliable match, false positive unlikely">strong</span>'):n.find(".t3js-extensionScanner-hit-file-panel-head .badges").append('<span class="badge badge-warning" title="Probable match, but can be a false positive">weak</span>'),!0===e.silenced&&n.find(".t3js-extensionScanner-hit-file-panel-head .badges").append('<span class="badge badge-info" title="Match has been annotated by extension author as false positive match">silenced</span>'),n.find(".t3js-extensionScanner-hit-file-lineContent").empty().text(e.lineContent),n.find(".t3js-extensionScanner-hit-file-line").empty().text(e.line+": "),$.isArray(e.restFiles)&&e.restFiles.forEach((e=>{const s=t.find("#t3js-extensionScanner-file-hit-rest-template").find(".panel").clone();s.find(".t3js-extensionScanner-hit-rest-panel-head").attr("href","#collapse"+e.uniqueId),s.find(".t3js-extensionScanner-hit-rest-panel-head .badge").empty().text(e.version),s.find(".t3js-extensionScanner-hit-rest-panel-body").attr("id","collapse"+e.uniqueId),s.find(".t3js-extensionScanner-hit-rest-headline").text(e.headline),s.find(".t3js-extensionScanner-hit-rest-body").text(e.content),s.addClass("panel-"+e.class),n.find(".t3js-extensionScanner-hit-file-rest-container").append(s),this.listOfAffectedRestFileHashes.push(e.file_hash)}));const o=n.find(".panel-breaking",".t3js-extensionScanner-hit-file-rest-container").length>0?"panel-danger":"panel-warning";n.addClass(o),n.removeClass("panel-default"),s.find(".t3js-extensionScanner-extension-body").removeClass("hide").append(n),s.removeClass("panel-default"),"panel-danger"===o&&(s.removeClass("panel-warning"),s.addClass(o)),"panel-warning"!==o||s.hasClass("panel-danger")||s.addClass(o)})),l.success){const e=parseInt(s.find(".t3js-extensionScanner-extension-body-loc").text(),10);if(s.find(".t3js-extensionScanner-extension-body-loc").empty().text(e+l.effectiveCodeLines),l.isFileIgnored){const e=parseInt(s.find(".t3js-extensionScanner-extension-body-ignored-files").text(),10);s.find(".t3js-extensionScanner-extension-body-ignored-files").empty().text(e+1)}const n=parseInt(s.find(".t3js-extensionScanner-extension-body-ignored-lines").text(),10);s.find(".t3js-extensionScanner-extension-body-ignored-lines").empty().text(n+l.ignoredLines)}o===n&&(a||(s.removeClass("panel-default"),s.addClass("panel-success")),s.addClass("t3js-extensionscan-finished"),s.removeClass("panel-has-progress"),this.setProgressForAll(),s.find(".t3js-extensionScanner-scan-single").text("Rescan").attr("disabled",null))},onrejected:t=>{o+=1,this.setStatusMessageForScan(e,o,n),this.setProgressForScan(e,o,n),s.removeClass("panel-has-progress"),this.setProgressForAll(),console.error(t)}})}))}else Notification.error("Oops, an error occurred","Please look at the browser console output for details"),console.error(i)}),(e=>{Router.handleAjaxError(e,t)}))}}export default new ExtensionScanner;