📁
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: pkgform.js
// Copyright 2026 WebPros International, LLC // All rights reserved. // copyright@cpanel.net http://cpanel.net // This code is subject to the cPanel license. Unauthorized copying is prohibited. (function() { "use strict"; var DOM = YAHOO.util.Dom, EVENT = YAHOO.util.Event, DRY_DOCK_ID = "extensionDryDock"; // Package type visibility configuration (set from template) let packageTypesVisibility = {}; // Package type to feature label mapping (set from template) let packageTypeFeatureLabels = {}; // Default package type constant const DEFAULT_PACKAGE_TYPE = "standard"; /** * Toggles the disabled state of all form inputs within an element. * Stores original disabled state to restore later. * * @method setInputsDisabled * @param {HTMLElement} container - The container element * @param {boolean} shouldDisable - Whether to disable the inputs */ const setInputsDisabled = (container, shouldDisable) => { const inputs = container.querySelectorAll("input, select, textarea"); for (const input of inputs) { if (shouldDisable) { if (!input.hasAttribute("data-original-disabled")) { input.setAttribute("data-original-disabled", input.disabled); } input.disabled = true; } else { const originalDisabled = input.getAttribute("data-original-disabled"); if (originalDisabled !== null) { input.disabled = originalDisabled === "true"; input.removeAttribute("data-original-disabled"); } } } }; /** * Sets element visibility and toggles input disabled state. * * @method setElementVisibility * @param {HTMLElement} el - The element to update * @param {boolean} isVisible - Whether the element should be visible */ const setElementVisibility = (el, isVisible) => { el.style.display = isVisible ? "" : "none"; setInputsDisabled(el, !isVisible); }; /** * Updates form visibility based on selected package type. * Handles fields, sections, extensions, and extension preselection. * * @method updateFormVisibility * @param {string} typeId - The selected package type ID */ const updateFormVisibility = (typeId) => { const config = packageTypesVisibility[typeId]; if (!config) { return; } // Update sections and fields (pre-computed boolean visibility) document.querySelectorAll("[data-section]").forEach(el => { setElementVisibility(el, config.sections[el.getAttribute("data-section")]); }); document.querySelectorAll("[data-field]:not([data-field='options'])").forEach(el => { setElementVisibility(el, config.fields[el.getAttribute("data-field")]); }); // Update extensions (allow/block logic: allow takes precedence, default visible) const ext = config.extensions || {}; document.querySelectorAll("[data-extension]").forEach(el => { const id = el.getAttribute("data-extension"); const isVisible = ext.allow ? ext.allow.includes(id) : ext.block ? !ext.block.includes(id) : true; setElementVisibility(el, isVisible); }); // Handle extension checkboxes (visibility, preselect, hide) const checkboxes = DOM.getElementsByClassName("packageOptionSelector", "input", "packageExtensions"); for (const checkbox of checkboxes) { const pkgName = DOM.getAttribute(checkbox, "data-packageOptions"); const wrapper = checkbox.parentNode; const isVisible = ext.allow ? ext.allow.includes(pkgName) : ext.block ? !ext.block.includes(pkgName) : true; // Not visible per allow/block? Hide wrapper completely if (!isVisible) { wrapper.style.display = "none"; continue; } // Visible but in hide list? Hide wrapper, auto-enable form if (ext.hide && ext.hide.includes(pkgName)) { wrapper.style.display = "none"; if (!checkbox.checked) { checkbox.checked = true; const subform = DOM.get(pkgName); if (subform) { showExtensionForm(subform, checkbox); } } continue; } // Normal case: show wrapper, handle preselect wrapper.style.display = ""; if (ext.preselect && ext.preselect.includes(pkgName) && !checkbox.checked) { checkbox.checked = true; const subform = DOM.get(pkgName); if (subform) { showExtensionForm(subform, checkbox); } } } // Update 'last' class on visible property editors document.querySelectorAll(".propertyGroup").forEach(group => { const current = group.querySelector(".propertyEditor.last"); if (current) { DOM.removeClass(current, "last"); } const lastVisible = Array.from(group.querySelectorAll(".propertyEditor")) .filter(ed => ed.style.display !== "none") .pop(); if (lastVisible) { DOM.addClass(lastVisible, "last"); } }); }; // Default feature list name - read from template, fallback to "default" const getDefaultFeatureList = () => { const featureListSelect = document.querySelector('select[name="featurelist"]'); return (featureListSelect && featureListSelect.dataset.default) || "default"; }; /* * Enables or disables the Save button based on the feature list dropdown. * * Save is disabled while the dropdown has no valid value: either no feature * lists are available for the selected package type, or the package's * original list was deleted and the admin has not yet picked a replacement * (the empty placeholder is selected). Selecting a valid list re-enables * Save so the package can be repaired from this page. * * @method updateSubmitButtonState */ const updateSubmitButtonState = () => { const featureListSelect = document.querySelector('select[name="featurelist"]'); const submitBtn = document.getElementById("submit"); if (!submitBtn) { return; } const hasValidFeatureList = !!(featureListSelect && featureListSelect.value); submitBtn.disabled = !hasValidFeatureList; // Keep the accessible relationship in sync with the disabled state. // A disabled Save button is otherwise announced only as "dimmed" with // no reason or recovery action, so point aria-describedby at whichever // warning message explains why (and how to fix it). Clear it when Save // is enabled so no stale description lingers. if (hasValidFeatureList) { submitBtn.removeAttribute("aria-describedby"); } else { const messageId = getActiveFeatureListWarningMessageId(); if (messageId) { submitBtn.setAttribute("aria-describedby", messageId); } else { submitBtn.removeAttribute("aria-describedby"); } } }; /* * Returns the id of the visible feature list warning message - the deleted * list mismatch warning or the no-available-lists warning - so the disabled * Save button can describe itself with the relevant explanation. Returns * null when neither warning is shown. * * @method getActiveFeatureListWarningMessageId */ const getActiveFeatureListWarningMessageId = () => { const isVisible = (el) => !!el && el.style.display !== "none"; if (isVisible(document.getElementById("featureListMismatchWarning"))) { return "featureListMismatchWarningMessage"; } if (isVisible(document.getElementById("featureListWarning"))) { return "featureListWarningMessage"; } return null; }; /* * Points the "View" feature list link at the selected list, or hides it * when nothing valid is selected - an empty dropdown or the placeholder * shown in the no-list / deleted-list states - since there is nothing to * view in those cases. * * @method updateFeatureListViewLink */ const updateFeatureListViewLink = () => { const featureListSelect = document.querySelector('select[name="featurelist"]'); const editLink = document.getElementById("editFeatureListLink"); if (!editLink) { return; } const selected = featureListSelect && featureListSelect.value; if (selected) { editLink.style.display = ""; editLink.setAttribute("href", "../scripts2/featuremanager/editFeatureList?name=" + encodeURIComponent(selected)); } else { editLink.style.display = "none"; } }; /* * Reconciles the Save button and the "View" link when the feature list * selection changes. * * @method handleFeatureListChange */ const handleFeatureListChange = () => { updateSubmitButtonState(); updateFeatureListViewLink(); }; /* * Normalizes the feature list dropdown to the repaired state after a * successful save. * * The deleted-list flow seeds an empty "Select a feature list …" * placeholder so the admin must deliberately pick a replacement. Once the * save succeeds the package references a real list, so that placeholder is * stale: re-selecting it - or resetting the form - would disable Save again * with no visible warning to explain why, reintroducing the very * disabled-with-no-reason state this page is meant to fix. Drop the * placeholder, keep the saved list selected, and promote it to the reset * default so the form stays usable for further edits. * * Exposed on window so the AJAX save handler in the template can call it * without the page reloading. * * @method normalizeFeatureListAfterSave */ const normalizeFeatureListAfterSave = () => { const featureListSelect = document.querySelector('select[name="featurelist"]'); if (!featureListSelect) { return; } // Drop the empty placeholder; the saved package references a real list. for (const option of Array.from(featureListSelect.options)) { if (option.value === "") { option.remove(); } } // Anchor Reset to the saved selection rather than the removed // placeholder (or an arbitrary first option) by making it the default. for (const option of featureListSelect.options) { option.defaultSelected = option.selected; } // Reconcile Save and the View link now that only valid lists remain. handleFeatureListChange(); }; window.normalizeFeatureListAfterSave = normalizeFeatureListAfterSave; /* * Filters the feature list dropdown based on the selected package type. * Shows only the feature lists defined for the package type in PACKAGE_FEATURE_LISTS. * If a package type has no defined feature lists, show a warning and clears the dropdown. * Falls back to the default package type's feature lists if packageType is empty or falsy. * * @method filterFeatureListsByPackageType * @param {String} packageType The selected package type (e.g., 'standard', 'nova') */ const filterFeatureListsByPackageType = (packageType) => { const featureListSelect = document.querySelector('select[name="featurelist"]'); const warningDiv = document.getElementById("featureListWarning"); const mismatchDiv = document.getElementById("featureListMismatchWarning"); const submitBtn = document.getElementById("submit"); if (!featureListSelect) { return; } // Get the mapping from global variable set in template const packageFeatureLists = window.PACKAGE_FEATURE_LISTS || {}; // We assume packageFeatureLists to be always defined with at least the standard package type. // Fall back to default package type 'standard' if packageType is empty or falsy. const effectivePackageType = packageType || DEFAULT_PACKAGE_TYPE; const allowedFeatureLists = packageFeatureLists[effectivePackageType] || []; // Show/hide warning based on whether feature lists are available if (warningDiv) { if (allowedFeatureLists.length || mismatchDiv) { warningDiv.style.display = "none"; } else { warningDiv.style.display = "block"; // Update warning message with feature label const msgSpan = document.getElementById("featureListWarningMessage"); if (msgSpan) { const label = packageTypeFeatureLabels[effectivePackageType] || ""; // SECURITY NOTE: This is XSS-safe by design. Do NOT add HTML escaping/sanitization here. // - textContent assignment prevents script injection (Web API protection) // - the LOCALE [_1] placeholder performs simple String() conversion (no HTML interpretation) // - Source: label from Cpanel::Features::load_addon_feature_descs() escaped by Template Toolkit .json().html() // Additional sanitization would provide no security benefit and could harm display of feature names. msgSpan.textContent = LOCALE.maketext("This package type requires a feature list with the “[_1]” feature enabled. Create one before you save this package.", label); if (submitBtn) { submitBtn.disabled = true; } } } } // If no feature lists are available for this package type, replace the // dropdown contents with a placeholder directing the admin to create // one, and hide the "View" link since there is nothing to view. The // accompanying warning provides the create action. if (allowedFeatureLists.length === 0) { featureListSelect.innerHTML = ""; const placeholder = document.createElement("option"); placeholder.value = ""; placeholder.textContent = LOCALE.maketext("Create a feature list …"); placeholder.selected = true; featureListSelect.appendChild(placeholder); updateFeatureListViewLink(); updateSubmitButtonState(); return; } // When the package's original feature list was deleted, force the // admin to make a deliberate choice instead of silently auto-selecting // a replacement: select a non-value placeholder so the mismatch warning // stays meaningful and Save stays disabled until a valid list is picked. const mismatchActive = !!mismatchDiv && mismatchDiv.style.display !== "none"; // Store the currently selected value to try to restore it after filtering. // This is useful if package types share feature lists (overlap), allowing // the user's selection to persist when switching between types. const currentValue = featureListSelect.value; // Check if the current value exists in the new allowed list const currentValueInNewList = allowedFeatureLists.includes(currentValue); // Determine which value to select: // 1. In the mismatch state, select nothing - the placeholder is selected. // 2. Keep current selection if it exists in the new list // 3. Otherwise, prefer the default feature list if it exists in the new list // 4. Otherwise, the first option will be auto-selected const defaultFeatureList = getDefaultFeatureList(); const preferredValue = mismatchActive ? null : currentValueInNewList ? currentValue : (allowedFeatureLists.includes(defaultFeatureList) ? defaultFeatureList : null); // Clear existing options featureListSelect.innerHTML = ""; if (mismatchActive) { const placeholder = document.createElement("option"); placeholder.value = ""; placeholder.textContent = LOCALE.maketext("Select a feature list …"); placeholder.selected = true; featureListSelect.appendChild(placeholder); } // Add filtered options for (const featurelist of allowedFeatureLists) { const option = document.createElement("option"); option.value = featurelist; option.textContent = featurelist; if (preferredValue && featurelist === preferredValue) { option.selected = true; } featureListSelect.appendChild(option); } // Update the "View" link to match the selection: shown and pointed at // the chosen list, or hidden while the placeholder is selected. updateFeatureListViewLink(); // Reconcile the Save button now that the dropdown reflects the // selected package type's valid feature lists. updateSubmitButtonState(); }; /* * Handles package type radio button change. * Updates the visual selection state of package type cards * and updates form field/section visibility. * * @method handlePackageTypeChange * @param {Event} evt The change event */ const handlePackageTypeChange = (evt) => { const radio = EVENT.getTarget(evt); if (!radio || !radio.parentNode) { return; } const cards = DOM.getElementsByClassName("pkgTypeCard", "label", "packageTypeSelector"); if (!cards || !cards.length) { return; } for (const card of cards) { DOM.removeClass(card, "pkgTypeCardSelected"); } const selectedCard = radio.parentNode; if (selectedCard && DOM.hasClass(selectedCard, "pkgTypeCard")) { DOM.addClass(selectedCard, "pkgTypeCardSelected"); } // Update form visibility based on selected package type updateFormVisibility(radio.value); // Filter feature lists based on the newly selected package type filterFeatureListsByPackageType(radio.value); }; /* * Adds change handlers to package type radio buttons. * Called from onDOMReady * * @method addPackageTypeHandlers */ const addPackageTypeHandlers = () => { const radios = DOM.getElementsByClassName("pkgTypeRadio", "input", "packageTypeSelector"); // React to manual feature list selection so the admin can repair a // package whose original feature list was deleted: (re-)enable Save once // a valid list is chosen. The mismatch warning intentionally persists // until the change is saved and the page reloads. const featureListSelect = document.querySelector('select[name="featurelist"]'); if (featureListSelect) { EVENT.addListener(featureListSelect, "change", handleFeatureListChange); } // A native form reset restores the select's options without firing a // "change" event, so the Save button and "View" link would otherwise be // left in a stale state (e.g. Save enabled and View pointing at a list // the placeholder no longer reflects). Reconcile after the browser has // applied the reset, which happens asynchronously, hence setTimeout(0). const mainform = document.forms.mainform; if (mainform) { EVENT.addListener(mainform, "reset", () => { setTimeout(handleFeatureListChange, 0); }); } // Add change listeners to radio buttons (if present) if (radios && radios.length) { for (const radio of radios) { EVENT.addListener(radio, "change", handlePackageTypeChange); } } // Apply initial filtering based on the currently selected package type const selectedRadio = document.querySelector('input[name="package_type"]:checked'); if (selectedRadio) { filterFeatureListsByPackageType(selectedRadio.value); } else { // On edit page, no radio buttons exist - check for hidden input const hiddenInput = document.querySelector("input[name='package_type'][type='hidden']"); if (hiddenInput) { filterFeatureListsByPackageType(hiddenInput.value); } } }; /* * Moves a given package extension editor fieldset from * the form to the form "drydock." * * @method drydockExtensionForm * @param {HTMLElement} subform The form to move */ var drydockExtensionForm = function(subform) { var dryDock = DOM.get(DRY_DOCK_ID); var removedSubform = subform.parentNode.removeChild(subform); if (removedSubform) { dryDock.appendChild(removedSubform); DOM.replaceClass(removedSubform, "visible", "hidden"); } }; /* * Moves a given package extension editor fieldset from * the form "drydock" to the form. * * @method showExtensionForm * @param {HTMLElement} subform The form to move * @param {HTMLElement} control The control (usually a checkbox) that shows/hides the package extension fields */ function showExtensionForm(subform, control) { var dryDock = DOM.get(DRY_DOCK_ID); var subformToShow = dryDock.removeChild(subform); if (subformToShow) { var packageExtensionsContainer = DOM.get("packageExtensions"); packageExtensionsContainer.insertBefore(subformToShow, control.parentNode.nextSibling); DOM.replaceClass(subformToShow, "hidden", "visible"); } } /* * Toggles the visibility of a given package extension form. * * @method showHidePackageOptions * @param {MouseEvent} mouseEvt Mouse event data * @param {Object} controlData Click handler data structure */ var showHidePackageOptions = function(mouseEvt, controlData) { var subform = DOM.get(controlData.packageName); var relatedControl = DOM.get(controlData.controlId); if (relatedControl.checked) { showExtensionForm(subform, relatedControl); } else { drydockExtensionForm(subform); } }; /* * Adds click handlers to package extension toggle control (usually a checkbox). * Click handlers add remove related fieldset items from page form. * Called from onDOMReady * * @method addClickHandlers */ var addClickHandlers = function() { var pkgOptionsControls = DOM.getElementsByClassName("packageOptionSelector", "input", "packageExtensions"); var pkgOptionsControlCount = pkgOptionsControls.length; for (var i = 0; i < pkgOptionsControlCount; i++) { var control = pkgOptionsControls[i]; control.checked = false; // turn off checkbox on reload EVENT.addListener(control, "click", showHidePackageOptions, { packageName: DOM.getAttribute(control, "data-packageOptions"), controlId: control.id, } ); } }; /* * Adds "last" class to last property editor within a property group. * Makes sure last property editor doesn't have a bottom border * (primarily for IE8 compatibility). * Called from onDOMReady * * @method addLastStyleToPropertyGroups */ var addLastStyleToPropertyGroups = function() { var isLastPropertyEditor = function(el) { return DOM.hasClass(el, "propertyEditor"); }; var fixLastPropertyEditors = function(containerId) { var packageExtensions = DOM.getElementsByClassName("propertyGroup", "div", containerId); var propertyGroupCount = packageExtensions.length; for (var j = 0; j < propertyGroupCount; j++) { var lastInGroup = DOM.getLastChildBy(packageExtensions[j], isLastPropertyEditor); if (lastInGroup) { DOM.addClass(lastInGroup, "last"); } } }; // check extension dry dock first fixLastPropertyEditors("extensionDryDock"); // now do package extensions fixLastPropertyEditors("packageExtensions"); }; /** * Initializes package type visibility and feature labels from data attributes. * Called from onDOMReady. * * @method initPackageTypesFromDataAttr */ const initPackageTypesFromDataAttr = () => { const selector = DOM.get("packageTypeSelector"); if (selector) { const configData = DOM.getAttribute(selector, "data-visibility-config"); if (configData) { try { packageTypesVisibility = JSON.parse(configData); } catch (error) { // Invalid JSON console.error(error); } } } // Load feature labels mapping from warning div const warningDiv = DOM.get("featureListWarning"); if (warningDiv) { const labelsData = DOM.getAttribute(warningDiv, "data-feature-labels"); if (labelsData) { try { packageTypeFeatureLabels = JSON.parse(labelsData); } catch (error) { // NOTE: Parse failures can be safely ignored. If packageTypeFeatureLabels remains empty, // the feature list warning message will simply display without a feature label (empty string). // This is acceptable degraded UX and does not break functionality. console.error(error); } } } // Apply initial visibility for currently selected package type applyInitialVisibility(); }; /** * Applies visibility for the initially selected package type. * Called after loading the visibility config. * * @method applyInitialVisibility */ function applyInitialVisibility() { const checkedRadio = document.querySelector(".pkgTypeRadio:checked"); if (checkedRadio) { updateFormVisibility(checkedRadio.value); } else { // Default to 'standard' if no radio is checked (e.g., hidden input) const hiddenInput = document.querySelector("input[name='package_type'][type='hidden']"); if (hiddenInput) { updateFormVisibility(hiddenInput.value); } } } EVENT.onDOMReady(initPackageTypesFromDataAttr); EVENT.onDOMReady(addClickHandlers); EVENT.onDOMReady(addLastStyleToPropertyGroups); EVENT.onDOMReady(addPackageTypeHandlers); }());
Save