📁
SKYSHELL MANAGER
PHP v8.2.31
Create
Create
Path:
root
/
home
/
thevaxnx
/
nativize.com
/
staging
/
wp-includes
/
js
/
tinymce
/
themes
/
Name
Size
Perm
Actions
📁
inlite
-
0755
🗑️
🏷️
🔒
📁
modern
-
0755
🗑️
🏷️
🔒
📄
wp-links-opml.php
6.83 KB
0444
🗑️
🏷️
⬇️
✏️
🔒
Edit: ea4Util.js
/* # cpanel - whostmgr/docroot/templates/easyapache4/services/ea4Util.js # Copyright 2025 WebPros International, LLC # All rights reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited */ /* global define: false */ define( [ "angular", "cjt/util/locale", "lodash", "cjt/io/api", "cjt/io/whm-v1-request", "cjt/io/whm-v1", "cjt/services/APIService", ], function(angular, LOCALE, _) { "use strict"; var app = angular.module("whm.easyapache4.ea4Util", []); app.factory("ea4Util", ["wizardState", function(wizardState) { var util = { eaRegex: /^ea-/i, phpVerRegex: /^ea-php(\d{2})$/i, phpExtRegex: /^ea-php(\d{2}-)/i, apacheVerRegex: /^ea-apache(\d{2})$/i, rubyVerRegex: /^ea-ruby(\d{2})/i, apacheModulesRegex: /^ea-apache(\d{2}-)/i, additionalPkgList: [], defaultMeta: { // Search/Filter settings filterList: {}, filterValue: "", isEmptyList: false, // Pager settings showPager: true, maxPages: 0, totalItems: 0, currentPage: 1, pageSize: 10, pageSizes: [10, 20, 50, 100], start: 0, limit: 10, }, pkgActions: { removeList: [], addList: [], actionNeeded: false, }, vhostWarning: { exist: false, text: "", }, multiRequirements: { exist: false, orList: [], chosenPackage: "", }, autoSelectExt: { list: [], text: "", errorList: [], show: false, showError: false, showCommonExtensions: false, }, checkUpdateInfo: { isLoading: true, pkgNumber: 0, btnText: LOCALE.maketext("Checking for updates …"), btnTitle: LOCALE.maketext("Checking for updates …"), btnCss: "btn-ea4-looking-updates disabled", }, }; util.cachedPrefixes = null; util.cachePrefixes = function(prefixes) { util.cachedPrefixes = prefixes; }; util.getCachedPrefixes = function() { return util.cachedPrefixes || []; }; // Cached EA4 metainfo used for version support checks util.cachedMetaInfo = null; util.cacheMetaInfo = function(metaInfo) { util.cachedMetaInfo = metaInfo; }; util.getCachedMetaInfo = function() { return util.cachedMetaInfo || {}; }; util.getOutdatedLabel = function() { return LOCALE.maketext("Outdated"); }; /** * Check if a non-alt PHP package is outdated based on oldest_supported_version from metainfo. * Applies to ea-phpNN and other non-alt prefixes. * @param {String} pkgName - Package name (e.g., 'ea-php81', 'custom-php80') * @return {Boolean} - True if the PHP version is outdated */ util.isOutdatedPhpVersion = function(pkgName) { if (PAGE && PAGE.suppress_php_eol_status) { return false; } var metaInfo = util.getCachedMetaInfo(); var oldestSupported = metaInfo.oldest_supported_version; if (!oldestSupported || !pkgName) { return false; } var phpVersionMatch = pkgName.match(/^([^-]+)-php(\d{2})(?:-|$)/i); if (!phpVersionMatch) { return false; } var prefix = phpVersionMatch[1].toLowerCase(); if (prefix === "alt") { return false; } var versionDigits = phpVersionMatch[2]; var packageMajor = parseInt(versionDigits.charAt(0), 10); var packageMinor = parseInt(versionDigits.charAt(1), 10); var oldestParts = oldestSupported.split("."); var oldestMajor = parseInt(oldestParts[0], 10); var oldestMinor = parseInt(oldestParts[1] || "0", 10); if (packageMajor < oldestMajor) { return true; } if (packageMajor === oldestMajor && packageMinor < oldestMinor) { return true; } return false; }; /** * Append outdated label to PHP package display names. * Uses round brackets unless parentheses are already present. * @param {String} displayName - The current display name * @param {String} pkgName - The package name to check * @param {String} outdatedLabel - Localized "Outdated" text * @return {String} - Display name with outdated label if applicable */ util.appendOutdatedLabel = function(displayName, pkgName, outdatedLabel) { if (!util.isOutdatedPhpVersion(pkgName)) { return displayName; } if (!outdatedLabel) { outdatedLabel = util.getOutdatedLabel(); } if (displayName.indexOf(outdatedLabel) !== -1) { return displayName; } return displayName + " (" + outdatedLabel + ")"; }; util.gatherAllRequirementsOfPkgs = function(pkgsToConsider, packageListDetails) { var allRequires = []; _.each(pkgsToConsider, function(pkg) { if (!_.includes(allRequires, pkg)) { var pkgInfo = packageListDetails[pkg]; if (typeof pkgInfo !== "undefined") { var result = util.recurseForRequires(pkgInfo, pkg, allRequires, packageListDetails); if (result !== undefined) { allRequires = result; } } allRequires.push(pkg); } }); return allRequires; }; util.recurseForRequires = function(pkgInfo, origPkgName, allPkgList, packageListDetails) { var pkgName = pkgInfo.package; var additionalPrefixes = util.getCachedPrefixes(); var allPrefixes = ["ea", "alt"].concat(additionalPrefixes); var matchesAnyPrefix = _.some(allPrefixes, function(prefix) { return pkgName.startsWith(prefix + "-"); }); if (!matchesAnyPrefix) { return; } if (_.includes(allPkgList, pkgName)) { return; } if (typeof origPkgName !== "undefined" && pkgName !== origPkgName) { allPkgList.push(pkgName); } var recurseArray = []; if (pkgInfo.pkg_dep.requires.length > 0) { recurseArray = _.clone(pkgInfo.pkg_dep.requires); recurseArray = _.filter(recurseArray, function(pkg) { if (typeof pkg !== "string" || _.isArray(pkg)) { return false; } var reqMatchesPrefix = _.some(allPrefixes, function(prefix) { return pkg.startsWith(prefix + "-"); }); return reqMatchesPrefix; }); recurseArray = _.difference(recurseArray, allPkgList); } _.forEach(recurseArray, function(reqPkg) { var reqPkgInfo = packageListDetails[reqPkg]; if (typeof reqPkgInfo !== "undefined") { util.recurseForRequires(reqPkgInfo, origPkgName, allPkgList, packageListDetails); } }); return allPkgList; }; /** * @method getFormattedPackageList * Takes an Array of packages names and returns a new sorted list * with formatted names. By default takes out the "ea-" part of * the package name. Also takes a second optional regex param to change the default behavior. * @example getFormattedPackageList("ea-openssl"); // returns "openssl" * @param {Array} pkgList - Array contains a list of packages names. * @param {RegExp} regex - Optional * @return {Array} - New formatted and sorted list. */ util.getFormattedPackageList = function(pkgList, regex) { var formattedList = []; var additionalPrefixes = util.getCachedPrefixes() || []; var allPrefixes = ["ea"].concat(additionalPrefixes); _.each(pkgList, function(pkg) { var formattedName; // For review list, preserve non-EA prefixes var pkgPrefix = "ea"; var match = _.find(allPrefixes, function(prefix) { return pkg.startsWith(prefix + "-"); }); if (match) { pkgPrefix = match; } if (pkgPrefix === "ea") { // For EA packages, strip the prefix as usual formattedName = util._getReadableName(pkg, regex); } else { // For non-EA packages, keep the full name to preserve context formattedName = pkg; } formattedList.push(formattedName); }); return formattedList; }; util.getFormattedPackageName = function(pkg, regex) { return util._getReadableName(pkg, regex); }; util._getReadableName = function(pkg, replaceRegex) { var strippedName = pkg; if (typeof replaceRegex !== "undefined" && replaceRegex !== "") { strippedName = pkg.replace(replaceRegex, ""); } else { if (util.apacheModulesRegex.test(pkg)) { strippedName = pkg.replace(util.apacheModulesRegex, ""); } else { // Strip ALL prefixes for consistent naming and sorting var additionalPrefixes = util.getCachedPrefixes() || []; var allPrefixes = ["ea"].concat(additionalPrefixes); var prefixPattern = "^(" + allPrefixes.join("|") + ")-"; var prefixRegex = new RegExp(prefixPattern); if (prefixRegex.test(pkg)) { strippedName = pkg.replace(prefixRegex, ""); } else { strippedName = pkg; } } } if (strippedName === "php") { strippedName = "php (DSO)"; } return strippedName; }; /** * @method getProfilePackagesByCategories * Takes an Array of packages names and groups them together in different categories. * The method will return an Object where the keys are the new categories. * @param {Array} pkgList - list of packages names. * @return {Object} - each keys equals a new category. */ util.getProfilePackagesByCategories = function(pkgList) { var pkgCategories = util._pkgByCategory(pkgList); return pkgCategories; }; util._pkgByCategory = function(pkgList) { var categories = {}, apacheList = [], phpExtList = [], others = [], phpVersions = [], apacheVersion = ""; var apachePrefix = "ea"; var additionalPrefixes = util.getCachedPrefixes(); var allPrefixes = ["ea"].concat(additionalPrefixes); _.each(pkgList, function(pkg) { if (util.apacheVerRegex.test(pkg)) { apacheVersion = pkg; var match = pkg.match(new RegExp("^(" + allPrefixes.join("|") + ")-apache")); if (match) { apachePrefix = match[1]; } } else if (util.apacheModulesRegex.test(pkg)) { apacheList = _.concat(apacheList, pkg); } else if (util.phpVerRegex.test(pkg)) { phpVersions = _.concat(phpVersions, pkg); } else if (util.phpExtRegex.test(pkg)) { phpExtList = _.concat(phpExtList, pkg); } else { others = _.concat(others, pkg); } }); if (apacheList.length > 0) { apacheVersion = util._getReadableName(apacheVersion, util.eaRegex); var categoryKey = apachePrefix + "_" + apacheVersion; categories[categoryKey] = { "name": util.versionToString(apacheVersion), "prefix": apachePrefix !== "ea" ? apachePrefix : null, "packages": util.getFormattedPackageListForProfile(apacheList, util.apacheModulesRegex), }; } if (phpVersions.length > 0) { _.each(phpVersions.sort(), function(version) { var verRegex = new RegExp("^" + _.escapeRegExp(version) + "-"); var extensions = _.filter(phpExtList, function(pkg) { return verRegex.test(pkg); }); phpExtList = _.difference(phpExtList, extensions); var phpversion = util._getReadableName(version, util.eaRegex); var phpPrefix = "ea"; var match = version.match(new RegExp("^(" + allPrefixes.join("|") + ")-php")); if (match) { phpPrefix = match[1]; } var categoryKey = phpPrefix + "_" + phpversion; var phpVersionName = util.versionToString(phpversion).replace("Php", "PHP"); var phpVersionOutdated = util.isOutdatedPhpVersion(version); categories[categoryKey] = { "name": phpVersionName, "prefix": phpPrefix !== "ea" ? phpPrefix : null, "isOutdated": phpVersionOutdated, "packages": util.getFormattedPackageListForProfile(extensions, util.phpExtRegex), }; }); } // Handle Others. if (others.length > 0) { categories["others"] = { "name": LOCALE.maketext("Additional Packages"), "prefix": null, "packages": util.getFormattedPackageListForProfile(others, /^ea-/), }; } return categories; }; /** * @method getFormattedPackageListForProfile * Like getFormattedPackageList but always strips prefixes for profile view * since it has labels to show namespace context * @param {Array} pkgList - Array contains a list of packages names. * @param {RegExp} regex - Optional * @return {Array} - New formatted and sorted list with ALL prefixes stripped. */ util.getFormattedPackageListForProfile = function(pkgList, regex) { var formattedList = []; _.each(pkgList, function(pkg) { // For profile view, always strip prefixes since we have labels var formattedName = util._getReadableName(pkg, regex); formattedList.push(formattedName); }); return formattedList; }; /** * @method versionToString * Returns a version in a user friendly format. * @example versionToString("apache24") // returns "Apache 2.4" * @param {String} * @return {String} */ util.versionToString = function(version) { return version.replace(/^([a-z]+)(\d)(\d)$/, function(match, p1, p2, p3) { return _.capitalize(p1) + " " + p2 + "." + p3; }); }; /** * @method getPackageLabel * Returns appropriate package label for a given package state. * @example getPackageLabel(true, "updatable"); // returns "Update" * @param {Boolean} selected * @param {String} state * @return {String} */ util.getPackageLabel = function(selected, state) { var str = ""; if (selected) { if (state === "updatable") { str = "Update"; } else if (state !== "installed" && state !== "updatable") { str = "Install"; } else if (state === "installed") { str = "Unaffected"; } } else if (state === "installed" || state === "updatable") { str = "Uninstall"; } return str; }; /** * @method getPackageClass * Returns the proper css callout class for a given package state. * @param {Boolean} selected * @param {String} state * @return {String} */ util.getPackageClass = function(selected, state) { var classString; if (selected) { classString = "callout"; if (state === "updatable") { classString += " callout-info"; } else { classString += " callout-success"; } } else { if (state === "installed" || state === "updatable") { classString = "callout callout-warning"; } else { classString = "no-callout"; } } return classString; }; /** * @method getDefaultMetaData * Returns a deep copy of the Default Meta Data needed * to initialize the Wizard component * @return {Object} */ util.getDefaultMetaData = function() { return _.clone(util.defaultMeta); }; /** * @method getDefaultPageSizes * Returns an Array with the Default page size values * @return {Array} */ util.getDefaultPageSizes = function() { return util.defaultMeta.pageSizes; }; /** * @method getUpdatedMetaData * Returns updated meta data. While updating the metadata, * the package list may be filtered depending on the search criteria. * @param {Object} list - List of current packages * @param {Object} meta - Current meta data * @return {Object} updated meta data */ util.getUpdatedMetaData = function(list, meta) { if (typeof list !== "undefined" && _.keys(list).length <= 0) { meta.isEmptyList = true; meta.totalItems = 0; return meta; } // Filter settings. var searchStr = meta.filterValue; if (searchStr) { var searchString = new RegExp(".*" + searchStr + ".*", "i"); list = _.pickBy(list, function(value, key) { return (searchString.test(value.package) || searchString.test(value.short_description)); }); } // Pager settings. var pkgKeys = _.keys(list); var pgSizes = util.getDefaultPageSizes(); pgSizes = _.filter(pgSizes, function(size) { return (size <= pkgKeys.length); }); meta.pageSizes = pgSizes; var totalItems = pkgKeys.length; // filter list based on page size and pagination if (totalItems > _.min(pgSizes)) { var startIdx = (meta.currentPage - 1) * meta.pageSize; var endIdx = startIdx + meta.pageSize; endIdx = endIdx > totalItems ? totalItems : endIdx; list = _.pick(list, _.slice(pkgKeys, startIdx, endIdx)); // list statistics meta.start = startIdx + 1; meta.limit = endIdx; meta.showPager = true; } else { meta.showPager = false; if (pkgKeys.length === 0) { meta.start = 0; } else { // list statistics meta.start = 1; } meta.limit = pkgKeys.length; } meta.totalItems = totalItems; meta.filterList = list; meta.isEmptyList = _.keys(meta.filterList).length <= 0; return meta; }; /** * @method getPageShowingText * Returns a formated string message * @param {Object} meta - Current meta data * @return {String} */ util.getPageShowingText = function(meta) { var newString = ""; if (meta && typeof meta.start !== "undefined" && typeof meta.limit !== "undefined" && typeof meta.totalItems !== "undefined" ) { newString = LOCALE.maketext("[output,strong,Showing] [_1] - [_2] of [_3] items", meta.start, meta.limit, meta.totalItems); } return newString; }; /** * @method getExtensionsForPHPVersion * Filters the package list and returns a new list * with only the packages associated to the PHP version provided * @param {String} version - PHP version (eg. ea-php71). * @param {Array} pkgList - Array of package names string * @return {Array} */ util.getExtensionsForPHPVersion = function(version, pkgList) { var testString = new RegExp(version + ".*", "i"); var list = _.filter(pkgList, function(name) { return testString.test(name); }); return list; }; /** * @method decideShowHideRecommendations * Based on the current state of package selection (i.e. on select or unselect), * this method filters the recommendations and decides if the recommendation is to be shown or hidden. * @param {Array} recommendations - Array of recommendation Objects * @param {Array} pkgListToCheck - Package list to check if they match the recommendation criteria. * @param {Boolean} onSelect * @return {Array} - Array of filtered recommendation Objects */ util.decideShowHideRecommendations = function(recommendations, pkgListToCheck, onSelect, pkg) { // Currently this recommendation system works strictly for DSO recommendation only. It can be modified to suit other // recommendations as they come. _.each(recommendations, function(reco) { if (_.isUndefined(reco)) { return; } if (typeof onSelect !== "undefined") { // The display of a recommendation depends on when it should be // shown (i.e. when installing a package or uninstalling a package) if (onSelect) { reco.show = (reco.on === "add"); } else { reco.show = (reco.on === "remove"); } } else { reco.show = false; } if (reco.show) { var pkgDisplayName = pkg; // Show readable PHP version name if the pkg is PHP version. if (util.phpVerRegex.test(pkg)) { pkgDisplayName = util._getReadableName(pkg, util.eaRegex); pkgDisplayName = util.versionToString(pkgDisplayName).replace("Php", "PHP"); } var localizedName = LOCALE.makevar(reco.name); // The value of this variable is pulled in for translation via an ea4_recommendations TPDS reco.displayName = LOCALE.maketext("Recommendations for “[_1]”: [_2]", pkgDisplayName, localizedName); reco.desc = LOCALE.makevar(reco.desc); // The value of this variable is pulled in for translation via an ea4_recommendations TPDS reco.showFootnote = false; // 'showReco' flag is strictly used for the DSO recommendation. var showReco = true; _.each(reco.options, function(option) { if (!_.isNil(option.recommended)) { option.title = (option.recommended) ? LOCALE.maketext("Recommended") : LOCALE.maketext("Not Recommended"); } option.text = LOCALE.makevar(option.text); // The value of this variable is pulled in for translation via an ea4_recommendations TPDS option.show = true; if (!_.isEmpty(option.items)) { showReco = option.show = _.isEmpty(_.intersection(option.items, pkgListToCheck)); // If none of the options that include package recos need not be shown // then we do not need to show the footnote. if (!reco.showFootnote) { reco.showFootnote = option.show; } } else { // In DSO recommendation, we are hiding the second option // as well when the first option option.show = showReco; } }); reco.show = !_.every(reco.options, ["show", false]); } }); return recommendations; }; /** * @method getExtensionsOfSelectedPHPVersions * @param {Object} pkgInfoList * @param {Object} currPkgInfoList * @param {Array} selectedPkgs - Array of packages names * @return {Object} */ util.getExtensionsOfSelectedPHPVersions = function(pkgInfoList, currPkgInfoList, selectedPkgs) { var extToConsider = []; var noPHPSelected = false; var allPhpVersions = _.filter(_.keys(pkgInfoList), function(pkg) { return util.phpVerRegex.test(pkg); }).sort(); var versionsToConsider = _.filter(selectedPkgs, function(pkg) { return (util.phpVerRegex.test(pkg)); }).sort(); // Determine if all versions are selected or not. If selected, // we do not need to extract a subset, we can just show all extensions. if (!_.isEqual(allPhpVersions, versionsToConsider)) { if (versionsToConsider.length > 0) { // Extract only the extension packages of the versions to consider. var workingExt = _.keys(currPkgInfoList); _.each(versionsToConsider, function(ver) { var testString = new RegExp(ver + ".*", "i"); var verExt = _.remove(workingExt, function(ext) { return testString.test(ext); }); extToConsider = _.concat(extToConsider, verExt); }); } else { noPHPSelected = true; } } else { versionsToConsider = allPhpVersions; extToConsider = _.keys(currPkgInfoList); } return { versions: versionsToConsider, extensions: extToConsider, noPHPSelected: noPHPSelected }; }; /** * Following validations are done for filename: * - It is invalid if the input is just . or .. * - It is invalid if the filename contains / or NUL byte. * - It is valid for all other cases. * * @method validateFilename */ util.validateFilename = function(filename) { var valData = { valid: true, valMsg: "" }; if (/^\.{1,2}$/.test(filename)) { valData.valid = false; valData.valMsg = LOCALE.maketext("Filename [output,strong,cannot] be “[output,strong,_1]”.", filename); } else if (/\/|\0/.test(filename)) { valData.valid = false; valData.valMsg = LOCALE.maketext("Filename [output,strong,cannot] include the following characters: [list_and,_1]", ["/", "NUL"]); } return valData; }; util.setupVhostWarning = function(pkgInfo, vhostsCount) { // Show them as a warning. pkgInfo.vhostWarning.exist = true; var localizedText = LOCALE.maketext( "[quant,_1,virtual host currently uses,virtual hosts currently use] this version of PHP. If you remove this PHP version, your virtual hosts may not work properly.", vhostsCount); // This hack is to apply the right class to the number. This // is to overcome the limitation of locale system to take multiple output types for a string. localizedText = localizedText.replace(/^(\d+)/, "<span class='vhost-emphasis'>$1</span>"); pkgInfo.vhostWarning.text = localizedText; return pkgInfo; }; util.resetVhostWarning = function(pkgInfo) { pkgInfo.vhostWarning = angular.copy(util.vhostWarning); }; /** * Creates tags based on the packages list provided. * * NOTE: [ Needs Improvement ] * Until there is a better way to identify the important packages in a * "Currently Installed Packages", we are going to use regex to extract * Apache, and all PHP versions installed and add them as tags. * * @method createTagsForActiveProfile * @param {Array} packages A list of packages. */ util.createTagsForActiveProfile = function(packages) { var tags = []; var skipRuby = false; var foundPhpVersions = new Set(); // Create static regexes for tag creation that won't be affected by prefix updates var additionalPrefixes = util.getCachedPrefixes() || []; var allPrefixes = ["ea", "alt"].concat(additionalPrefixes); var phpTagRegex = new RegExp("^(" + allPrefixes.join("|") + ")-php(\\d{2})$", "i"); var apacheTagRegex = new RegExp("^(" + allPrefixes.join("|") + ")-apache(\\d{2})$", "i"); var rubyTagRegex = new RegExp("^(" + allPrefixes.join("|") + ")-ruby(\\d{2})", "i"); _.each(packages, function(pkg) { var newTag; var apacheMatch = pkg.match(apacheTagRegex); if (apacheMatch) { var apacheVersion = apacheMatch[2]; newTag = "Apache " + apacheVersion.replace(/(\d)(\d)$/, "$1.$2"); tags = _.concat(tags, newTag); } else { var phpMatch = pkg.match(phpTagRegex); if (phpMatch) { var phpPrefix = phpMatch[1]; var phpVersion = phpMatch[2]; var formattedVersion = "PHP " + phpVersion.replace(/(\d)(\d)$/, "$1.$2"); phpPrefix = "ea"; if (pkg.startsWith("alt-")) { phpPrefix = "alt"; } else if (!pkg.startsWith("ea-") && !pkg.startsWith("alt-")) { phpPrefix = phpMatch[1]; } var tagKey = phpPrefix.toLowerCase() + "-" + formattedVersion; if (!foundPhpVersions.has(tagKey)) { foundPhpVersions.add(tagKey); if (phpPrefix.toLowerCase() === "alt") { if (!(PAGE && PAGE.suppress_php_eol_status)) { var securedTag = LOCALE.maketext("Secured"); tags = _.concat(tags, formattedVersion + " (alt)(" + securedTag + ")"); } else { tags = _.concat(tags, formattedVersion + " (alt)"); } } else if (phpPrefix.toLowerCase() !== "ea") { var prefixedTag = formattedVersion + " (" + phpPrefix + ")"; prefixedTag = util.appendOutdatedLabel(prefixedTag, pkg, util.getOutdatedLabel()); tags = _.concat(tags, prefixedTag); } else { var tagToAdd = util.appendOutdatedLabel(formattedVersion, pkg, util.getOutdatedLabel()); tags = _.concat(tags, tagToAdd); } } } } var rubyMatch = pkg.match(rubyTagRegex); if (rubyMatch && !skipRuby) { var rubyVersion = rubyMatch[2]; newTag = "Ruby " + rubyVersion.replace(/(\d)(\d)$/, "$1.$2"); tags = _.concat(tags, newTag); skipRuby = true; } }); return tags; }; /** * @method checkMPMRequirement * Checks if the user has any MPM packages (at least one needs to be installed). * Updates MPM callout feedback. * @param {Object} pkgData * @param {Object} resolvedData * @param {Array} selectedPkgs * @param {Boolean} whenSelected * @return {Object} */ util.checkMPMRequirement = function(pkgData, resolvedData, selectedPkgs, whenSelected) { var mpmRegex = /mod[-_]mpm/; var mpmInRemoveList = _.filter(_.uniq(resolvedData.removeList), function(pkg) { return mpmRegex.test(pkg); }); if (!whenSelected && mpmRegex.test(pkgData.package)) { mpmInRemoveList = _.union(mpmInRemoveList, [pkgData.package]); } var subList = _.difference(selectedPkgs, mpmInRemoveList); var mpmIndexInRemove = _.findIndex(subList, function(pkg) { return mpmRegex.test(pkg); }); var mpmIndexInAdd = _.findIndex(resolvedData.addList, function(pkg) { return mpmRegex.test(pkg); }); if (mpmIndexInRemove === -1 && mpmIndexInAdd === -1) { // Show MPM callout; pkgData.mpmMissing = true; pkgData.mpmMissingMsg = LOCALE.maketext("Your selection removed [list_and,_1].", mpmInRemoveList) + " " + LOCALE.maketext("An [asis,MPM] package must exist on your system. Click “Continue” to select a new [asis,MPM] package.") + " " + LOCALE.maketext("Click “Cancel” to cancel this operation."); pkgData.actions.actionNeeded = false; } return pkgData; }; util.getCommonlyInstalledExtensions = function(allExtensions, installedPhpVersions) { // Filter only installed extensions. var installedExt = _.map(_.filter(allExtensions, ["selectedPackage", true]), "package"); var extGroupByVersions = []; _.each(installedPhpVersions, function(version, index) { // Group the extensions by PHP versions and normalize them to // a common name to make it easy to extract the // common extensions across all installed versions. // Example: // Trying to process the following array: // [ // "ea-php54-libc-client", "ea-php54-build", "ea-php54-pear", // "ea-php54-php-bcmath", "ea-php55-libc-client", "ea-php55-build", "ea-php55-pear", // "ea-php70-libc-client", "ea-php70-build", "ea-php70-pear", // "ea-php70-php-calendar", "ea-php70-php-curl" // ] // To: // [ // [ "libc-client", "build", "pear", "php-bcmath" ], // [ "libc-client", "build", "pear" ], // [ "libc-client", "build", "pear", "php-calendar", "php-curl" ] // ] extGroupByVersions[index] = _.chain(installedExt) .filter(function(ext) { return _.startsWith(ext, version); }) .map(function(ext) { return _.replace(ext, util.phpExtRegex, ""); }) .value(); }); // Extract the common extensions. // Note: EA packages use "php-bcmath" format while ALT packages use "bcmath" format. // We need to normalize for comparison but preserve the original names. var commonExtensions = []; if (extGroupByVersions.length === 1) { commonExtensions = extGroupByVersions[0]; } else { // Helper function to normalize extension name for comparison // Strips "php-" prefix if present to allow matching between EA and ALT packages var normalizeForComparison = function(ext) { return ext.indexOf("php-") === 0 ? ext.substring(4) : ext; }; // Build a map of normalized names to original names for each group var normalizedGroups = _.map(extGroupByVersions, function(group) { var map = {}; _.each(group, function(ext) { var normalizedName = normalizeForComparison(ext); // Prefer the original name (with php- prefix if it exists) if (!map[normalizedName] || ext.indexOf("php-") === 0) { map[normalizedName] = ext; } }); return map; }); // Find common normalized extension names var commonNormalized = _.keys(normalizedGroups[0]); for (var i = 1; i < normalizedGroups.length; i++) { commonNormalized = _.intersection(commonNormalized, _.keys(normalizedGroups[i])); } // Map back to original names, preferring the php- prefixed version for EA compatibility commonExtensions = _.map(commonNormalized, function(normalizedName) { // Look through all groups and prefer the php- prefixed version for (var j = 0; j < normalizedGroups.length; j++) { var original = normalizedGroups[j][normalizedName]; if (original && original.indexOf("php-") === 0) { return original; } } // If no php- prefixed version found, return any version return normalizedGroups[0][normalizedName]; }); } // Only single PHP version can have DSO package installed at any instance. So // if a DSO package come up in the commonExtensions, pull it out to eliminate // having conflict issues while auto selecting common extensions. // Note: Generally a DSO package is 'ea-php##-php'. Since 'ea-php##-' is stripped above, we are comparing it with just php. var excludeList = ["php", "scldevel" ]; _.pullAll(commonExtensions, excludeList); return commonExtensions; }; /** * Looks for ea-ruby##-** packages and return true if they do exist. * @param {Object} pkgList Package information list, * @return {Boolean} True if at least one ruby package exists. False otherwise. */ util.doRubyPkgsExist = function(pkgList) { return _.some(pkgList, function(pkg) { return util.rubyVerRegex.test(pkg.package); }); }; util.updateRegexForPrefixes = function(additionalPrefixes) { var allPrefixes = ["ea"].concat(additionalPrefixes || []); var prefixPattern = "(" + allPrefixes.join("|") + ")"; util.eaRegex = new RegExp("^(" + allPrefixes.join("|") + ")-", "i"); util.phpVerRegex = new RegExp("^" + prefixPattern + "-php(\\d{2})$", "i"); util.phpExtRegex = new RegExp("^" + prefixPattern + "-php(\\d{2}-)", "i"); util.apacheVerRegex = new RegExp("^" + prefixPattern + "-apache(\\d{2})$", "i"); util.apacheModulesRegex = new RegExp("^" + prefixPattern + "-apache(\\d{2}-)", "i"); util.rubyVerRegex = new RegExp("^" + prefixPattern + "-ruby(\\d{2})", "i"); }; /** * Looks for additional packages and return true if they do exist. * @param {Array} additionalPkgsList Array of additional package objects. * @param {Object} pkgList Package information list, * @return {Boolean} True if at least one additional package exists. False otherwise. */ util.doAdditionalPkgsExist = function(additionalPkgsList, pkgList) { return _.some(additionalPkgsList, function(addlPkg) { return _.includes(_.keys(pkgList), addlPkg); }); }; /** * Show Footer container of the wizard. */ util.showFooter = function() { wizardState.showFooter = true; }; /** * Hide Footer container of the wizard. */ util.hideFooter = function() { wizardState.showFooter = false; }; return util; }]); } );
Save