Viewing File: /usr/local/cpanel/base/frontend/jupiter/multiphp_manager/views/config.js
/*
* multiphp_manager/views/config.js Copyright(c) 2020 cPanel, L.L.C.
* All rights reserved.
* copyright@cpanel.net http://cpanel.net
* This code is subject to the cPanel license. Unauthorized copying is prohibited
*/
/* global define: false, PAGE: true */
define(
[
"angular",
"cjt/util/locale",
"lodash",
"uiBootstrap",
"cjt/services/alertService",
"cjt/directives/alert",
"cjt/directives/alertList",
"cjt/directives/callout",
"app/services/configService",
"app/views/impactedDomainsPopup"
],
function(angular, LOCALE, _) {
"use strict";
// Retrieve the current application
var app = angular.module("App");
var controller = app.controller(
"config",
["$scope", "configService", "$uibModal", "$timeout", "alertService",
function($scope, configService, $uibModal, $timeout, alertService) {
// Setup data structures for the view
$scope.loadingVhostList = false;
$scope.phpVersionsEmpty = true;
$scope.selectedVersion = {};
$scope.phpVhostList = [];
// Setup data structures for restricted versions/alert
$scope.restrictedPhp = {
domainsSelected: [],
showAlert: false,
alertInfo: "",
showAllDomains: false,
showMore: true
};
$scope.vhostSelected = false;
var selectedVhostList = [];
$scope.totalSelectedDomains = 0;
$scope.checkdropdownOpen = false;
// meta information
$scope.meta = {
// Sort settings
sortReverse: false,
sortBy: "vhost",
sortDirection: "asc",
// Search/Filter options
filterBy: "*",
filterCompare: "contains",
filterValue: "",
// Pager settings
maxPages: 0,
totalItems: $scope.phpVhostList.length,
currentPage: 1,
pageSize: 10,
pageSizes: [10, 20, 50, 100, 500, 1000],
start: 0,
limit: 10
};
var impactedDomains = {
loading: false,
warn: false,
show: false,
showMore: false,
text: ""
};
var eolWarningMsgLastPart = LOCALE.maketext("We recommend that you update to a supported version of [asis,PHP]. For more information, read our [output,url,_1,PHP,target,_2] documentation.", "https://go.cpanel.net/eaphp", "_blank");
var phpVersionRegex = /^ea-php\d{2,}$/;
$scope.php = {
systemPhp: {
isEol: false
},
showEolMsg: false,
eolWarningMsg: ""
};
var getSelectedRestrictedDomains = function() {
var totalRestricted = [];
// check if it is a PHP restricted versions
$scope.phpVhostList.forEach(function(item) {
if (item.rowSelected && item.isRestricted) {
totalRestricted.push(item.vhost);
}
});
return totalRestricted;
};
var updatePhpAlert = function() {
// update restricted versions selected
$scope.restrictedPhp.domainsSelected = getSelectedRestrictedDomains();
$scope.restrictedPhp.showMore = 6 < $scope.restrictedPhp.domainsSelected.length;
var restrictedDomains = $scope.restrictedPhp.domainsSelected;
if (restrictedDomains.length > 0) {
$scope.restrictedPhp.showAlert = true;
// reduce is used to extract the display version list from $scope.phpVersions
// to enumerate them in the LOCALE make text list_and method
var phpVersions = $scope.phpVersions.reduce(function(acc, item) {
if (item.version !== "inherit") {
acc.push(item.displayPhpVersion);
}
return acc;
}, []);
$scope.restrictedPhp.alertInfo = LOCALE.maketext("The system administrator only allows this account to use the [asis,PHP] [numerate,_2,version,versions] [list_and,_1].", phpVersions.map(_.escape), phpVersions.length) + " " + LOCALE.maketext("If you change the [asis,PHP] version for the following [numerate,_1,domain,domains], you cannot use this interface to change the [numerate,_1,domain,domains] back to use [numerate,_1,its,their] original version of [asis,PHP].", restrictedDomains.length);
} else {
$scope.restrictedPhp.showAlert = false;
}
};
$scope.selectAllVhosts = function() {
if ($scope.allRowsSelected) {
$scope.phpVhostList.forEach(function(item) {
item.rowSelected = true;
if ( selectedVhostList.indexOf(item.vhost) !== -1 ) {
return;
}
selectedVhostList.push(item.vhost);
});
} else {
var unselectedDomains = $scope.phpVhostList.map(function(item) {
item.rowSelected = false;
return item.vhost;
});
selectedVhostList = _.difference(selectedVhostList, unselectedDomains);
$scope.restrictedPhp.showAlert = false;
}
$scope.totalSelectedDomains = selectedVhostList.length;
$scope.vhostSelected = $scope.totalSelectedDomains > 0;
$scope.restrictedPhp.domainsSelected = getSelectedRestrictedDomains();
// update restricted versions if warning is showing
if ($scope.restrictedPhp.showAlert) {
updatePhpAlert();
}
};
var processImpactedDomains = function(vhostInfo, selected) {
// Get impacted domains for this vhost selection and show them to
// to warn the user about the impact that the change has.
if (selected) {
vhostInfo.impactedDomains.loading = true;
configService.fetchImpactedDomains("domain", vhostInfo.vhost)
.then(function(result) {
// Original vhost we are getting this data for, is also
// returned as part of the result. Let's remove that so we can
// just show the other impacted domains.
var domains = _.without(result.data.domains, vhostInfo.vhost);
if (result.status && domains.length > 0) {
vhostInfo.impactedDomains.show = vhostInfo.impactedDomains.warn = vhostInfo.rowSelected;
vhostInfo.impactedDomains.showMore = domains.length > 10;
vhostInfo.impactedDomains.text = LOCALE.maketext("A change to the “[output,strong,_1]” domain‘s PHP version affects the following domains:", _.escape(vhostInfo.vhost));
vhostInfo.impactedDomains.domains = _.sortBy(domains);
}
},
function(error) {
alertService.add({
type: "danger",
message: error,
closeable: true,
replace: false,
group: "multiphpManager"
});
}).finally(function() {
vhostInfo.impactedDomains.loading = false;
});
} else {
vhostInfo.impactedDomains.show = vhostInfo.impactedDomains.warn = selected;
}
};
$scope.toggleRestrictedDomains = function() {
$scope.restrictedPhp.showAllDomains = !$scope.restrictedPhp.showAllDomains;
};
$scope.selectVhost = function(vhostInfo) {
if (typeof vhostInfo !== "undefined") {
processImpactedDomains(vhostInfo, vhostInfo.rowSelected);
if (vhostInfo.rowSelected) {
selectedVhostList.push(vhostInfo.vhost);
$scope.allRowsSelected = $scope.phpVhostList.every(function(item) {
return item.rowSelected;
});
} else {
selectedVhostList = selectedVhostList.filter(function(item) {
return item !== vhostInfo.vhost;
});
// Unselect Select All checkbox.
$scope.allRowsSelected = false;
}
}
$scope.totalSelectedDomains = selectedVhostList.length;
$scope.vhostSelected = $scope.totalSelectedDomains > 0;
$scope.restrictedPhp.domainsSelected = getSelectedRestrictedDomains();
// update restricted versions if warning is showing
if ($scope.restrictedPhp.showAlert) {
updatePhpAlert();
}
};
$scope.rowClass = function(vhostInfo) {
if (vhostInfo.impactedDomains.warn) {
return "warning";
}
if (vhostInfo.impactedDomains.loading) {
return "processing";
}
};
$scope.showAllImpactedDomains = function(vhostInfo) {
// var viewingProfile = angular.copy(thisProfile);
$uibModal.open({
templateUrl: "impactedDomainsPopup.ptt",
controller: "impactedDomainsPopup",
resolve: {
data: function() {
return vhostInfo;
}
}
});
};
$scope.clearAllSelections = function(event) {
event.preventDefault();
event.stopPropagation();
selectedVhostList = [];
$scope.phpVhostList.forEach(function(item) {
item.rowSelected = false;
});
$scope.checkdropdownOpen = false;
$scope.allRowsSelected = false;
$scope.totalSelectedDomains = 0;
$scope.vhostSelected = false;
$scope.restrictedPhp.showAlert = false;
};
$scope.hidePhpAlert = function() {
$scope.restrictedPhp.showAlert = false;
};
var setPhpRecommendedVersion = function() {
configService.getCustomRecommendations().then(function(result) {
if (result && result.data.length > 0 ) {
var recVersions = result.data;
var matchedVers = [];
recVersions.forEach(function(recVer) {
$scope.phpVersions.forEach(function(v) {
if (v.version.includes(recVer)) {
// Add recommended label to display version for dropdown
matchedVers.push(configService.friendlyPhpFormat(v.version));
v.displayPhpVersion = v.displayPhpVersion + " - " + LOCALE.maketext("Recommended");
$scope.showRecommendedVersion = true;
}
});
});
// Add sentence about recommended version for display in UI
if ( matchedVers.length > 0 ) {
$scope.recommendedVersionMessage = LOCALE.maketext("Your hosting provider recommends [list_or,_1].", matchedVers);
}
}
});
};
var setDomainPhpDropdown = function(versionList) {
// versionList is sent to the function when the
// dropdown is bound the first time.
if (typeof versionList !== "undefined") {
$scope.phpVersions = versionList;
// Cannot show "inherit" in the dropdown if system default itself doesn't exist.
if (typeof $scope.systemPhp !== "undefined" && $scope.systemPhp !== "") {
// A new entry 'inherit' will be added to PHP version list. It allows domains
// to reset back to 'inherit' value.
$scope.phpVersions.push({ version: "inherit", displayPhpVersion: "inherit" });
}
}
if ($scope.phpVersions && $scope.phpVersions.length > 0) {
setPhpRecommendedVersion();
$scope.selectedVersion = $scope.phpVersions[0];
$scope.phpVersionsEmpty = false;
} else {
$scope.phpVersionsEmpty = true;
}
};
var resetForm = function() {
setDomainPhpDropdown();
selectedVhostList = [];
$scope.phpVhostList.forEach(function(item) {
item.rowSelected = false;
});
// Unselect Select All checkbox.
$scope.allRowsSelected = false;
$scope.totalSelectedDomains = 0;
$scope.vhostSelected = false;
};
// Apply the new PHP version setting of a selected user
$scope.performApplyDomainPhp = function() {
alertService.clear();
// hide restricted php warning
if ($scope.restrictedPhp.showAlert) {
$scope.restrictedPhp.showAlert = false;
}
return configService.applyDomainSetting($scope.selectedVersion.version, selectedVhostList)
.then(
function(data) {
if (typeof data !== "undefined") {
alertService.add({
type: "success",
message: LOCALE.maketext("Successfully applied [asis,PHP] version “[_1]” to the selected [numerate,_2,domain,domains].", $scope.selectedVersion.displayPhpVersion, selectedVhostList.length),
closeable: true,
replace: false,
autoClose: 10000,
group: "multiphpManager"
});
$scope.selectPage();
}
}, function(response) {
if (typeof (response.raw) !== "undefined") {
var errors = response.raw.errors;
// ::TODO:: Should scroll to the error alert when
// multiple errors occur.
if (errors.length > 0) {
var successfulDomains = [];
if (response.data && response.data.vhosts) {
successfulDomains = response.data.vhosts;
}
errors.forEach(function(error) {
alertService.add({
type: "danger",
message: error,
closeable: true,
replace: false,
group: "multiphpManager"
});
});
if (successfulDomains.length > 0) {
alertService.add({
type: "success",
message: LOCALE.maketext("Successfully applied [asis,PHP] version “[_1]” to [numerate,_2,a domain,some domains].", $scope.selectedVersion.displayPhpVersion, successfulDomains.length),
closeable: true,
replace: false,
autoClose: 10000,
group: "multiphpManager"
});
}
}
} else {
alertService.add({
type: "danger",
message: response.error,
closeable: true,
replace: false,
group: "multiphpManager"
});
}
}).finally(function() {
resetForm();
});
};
$scope.applyDomainPhp = function() {
if ($scope.restrictedPhp.domainsSelected.length > 0) {
return updatePhpAlert();
} else {
return $scope.performApplyDomainPhp();
}
};
var applyListToTable = function(resultList) {
var vhostList = resultList.items;
// update the total items after search
$scope.meta.totalItems = resultList.totalItems;
var filteredList = vhostList;
// filter list based on page size and pagination
if ($scope.meta.totalItems > _.min($scope.meta.pageSizes)) {
var start = ($scope.meta.currentPage - 1) * $scope.meta.pageSize;
$scope.showPager = true;
// table statistics
$scope.meta.start = start + 1;
$scope.meta.limit = start + filteredList.length;
} else {
// hide pager and pagination
$scope.showPager = false;
if (filteredList.length === 0) {
$scope.meta.start = 0;
} else {
// table statistics
$scope.meta.start = 1;
}
$scope.meta.limit = filteredList.length;
}
var countNonSelected = 0;
// Select the rows if they were previously selected on this page.
filteredList.forEach(function(item) {
if (selectedVhostList.indexOf(item.vhost) !== -1) {
item.rowSelected = true;
} else {
item.rowSelected = false;
countNonSelected++;
}
item.impactedDomains = angular.copy(impactedDomains);
// Initialize the 'inherited' bool flag for every time to false.
item.inherited = false;
var version_source = item.phpversion_source;
if ( typeof version_source !== "undefined" ) {
var type = "", value = "";
if ( typeof version_source.domain !== "undefined" ) {
type = "domain";
value = version_source.domain;
} else if (typeof version_source.system_default !== "undefined") {
type = "system_default";
value = LOCALE.maketext("System Default");
}
if ((type === "domain" && value !== item.vhost) ||
type === "system_default") {
item.inherited = true;
item.inheritedInfo = LOCALE.maketext("This domain inherits its [asis,PHP] version “[output,em,_1]” from: [output,strong,_2]", _.escape(item.displayPhpVersion), _.escape(value));
}
}
// Initialize 'restricted' values
item.isRestricted = false;
item.showInheritInfo = false;
var installedVersions = PAGE.versionListData.data.versions;
// checks if the PHP version is not installed on the system
if (!_.some(installedVersions, ["version", item.version])) {
item.isRestricted = true;
}
});
$scope.restrictedPhp.showMore = 6 < $scope.restrictedPhp.domainsSelected.length;
$scope.phpVhostList = filteredList;
// Clear the 'Select All' checkbox if at least one row is not selected.
$scope.allRowsSelected = (filteredList.length > 0) && (countNonSelected === 0);
};
/**
* Fetch the list of vhosts for the user account with their default PHP versions.
* @return {Promise} Promise that when fulfilled will result in the list being loaded with the account's vhost list.
*/
var fetchVhostList = function() {
$scope.loadingVhostList = true;
return configService
.fetchList($scope.meta)
.then(function(results) {
applyListToTable(results);
}, function(error) {
// failure
alertService.add({
type: "danger",
message: error,
closeable: true,
replace: false,
group: "multiphpManager"
});
})
.then(function() {
$scope.loadingVhostList = false;
});
};
/**
* Select a specific page
* @param {Number} page Page number
*/
$scope.selectPage = function(page) {
// set the page if requested.
if (page && angular.isNumber(page)) {
$scope.meta.currentPage = page;
}
return fetchVhostList();
};
/**
* Filter the End of life PHP recommendations
* from the EA4 recommendation pool.
* @method filterEolPhpRecos
* @param {Object} data
* @returns {Array} Array of PHP End of life recommndations.
*/
var filterEolPhpRecos = function(data) {
var eolPhps = [];
var keys = _.sortBy(_.filter(_.keys(data), function(key) {
return (phpVersionRegex.test(key));
}));
_.each(keys, function(key) {
_.each(data[key], function(reco) {
if (_.includes(reco.filter, "eol")) {
eolPhps.push(key);
}
});
});
return eolPhps;
};
/**
* Sets the view parameters that show the PHP
* EOL warning.
* @method setPhpEolData
* @param {Array} versionList
*/
var setPhpEolData = function(versionList) {
return configService.getEA4Recommendations()
.then(function(result) {
if (result && typeof result.data !== "undefined") {
var eolPhps = filterEolPhpRecos(result.data);
if (eolPhps.length > 0) {
// Show if system PHP is EOL.
$scope.php.systemPhp.isEol = _.includes(eolPhps, PAGE.systemPHPData.data.version);
// Check if there are any EOL PHPs installed.
var installedEolPhps = _.intersection(eolPhps, versionList);
// Show the deprecation message only if EOL PHPs are installed on the system.
if (installedEolPhps.length > 0) {
var displayEolPhps = _.map(installedEolPhps, function(php) {
return configService.friendlyPhpFormat(php);
});
var eolWarningMsg = LOCALE.maketext("[output,strong,Warning]: [asis,PHP] [numerate,_2,version,versions] [list_and,_1] [numerate,_2,is,are] [output,strong,deprecated].", displayEolPhps.map(_.escape), installedEolPhps.length) + " " + eolWarningMsgLastPart;
$scope.php.showEolMsg = true;
$scope.php.eolWarningMsg = eolWarningMsg;
}
}
} else {
alertService.add({
type: "warning",
message: LOCALE.maketext("The system could not retrieve data for deprecated versions of PHP."),
closeable: true,
id: "recommendationsError",
group: "multiphpManager"
});
}
})
.catch(function(error) {
alertService.add({
type: "warning",
message: error,
closeable: true,
id: "recommendationsError",
group: "multiphpManager"
});
});
};
$scope.$on("$viewContentLoaded", function() {
alertService.clear();
setPhpEolData(PAGE.versionListData.data.versions);
// add php user friendly version
if (PAGE.versionListData.data) {
PAGE.versionListData.data.versions = PAGE.versionListData.data.versions.map(function(version) {
return {
version: version,
displayPhpVersion: configService.transformPhpFormat(version)
};
});
}
var errorMsg;
// Load the domain table
if (PAGE.vhostListData.status) {
$scope.loadingVhostList = false;
var results = configService.convertResponseToList(PAGE.vhostListData);
applyListToTable(results);
} else {
errorMsg = PAGE.vhostListData.errors[0];
alertService.add({
type: "danger",
message: PAGE.vhostListData.errors[0],
closeable: true,
replace: false,
group: "multiphpManager"
});
}
// Load system PHP version.
if (PAGE.systemPHPData.status) {
$scope.systemPhp = {
version: PAGE.systemPHPData.data.version,
displayPhpVersion: configService.transformPhpFormat(PAGE.systemPHPData.data.version)
};
} else {
if (errorMsg !== PAGE.systemPHPData.errors[0]) {
alertService.add({
type: "danger",
message: PAGE.systemPHPData.errors[0],
closeable: true,
replace: false,
group: "multiphpManager"
});
}
}
// Load the installed PHP versions.
if (PAGE.versionListData.status) {
setDomainPhpDropdown(PAGE.versionListData.data.versions );
} else {
setDomainPhpDropdown();
if (errorMsg !== PAGE.versionListData.errors[0]) {
alertService.add({
type: "danger",
message: PAGE.versionListData.errors[0],
closeable: true,
replace: false,
group: "multiphpManager"
});
}
}
});
}
]);
return controller;
}
);
Back to Directory
File Manager