HEX
Server: LiteSpeed
System: Linux server315.web-hosting.com 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: globfdxw (6114)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: /home/globfdxw/www/wp-content/plugins/wpforms-pdf/assets/js/modules/access-restrictions.js
/* global wpforms_builder, wpf, WPForms */

/**
 * WPForms PDF: Access Restrictions module.
 *
 * @since 1.0.0
 *
 * @param {Object} document Document object.
 * @param {Object} window   Window object.
 * @param {jQuery} $        jQuery object.
 *
 * @return {Object} Public functions and properties.
 */
export default function( document, window, $ ) { // eslint-disable-line no-unused-vars, max-lines-per-function
	/**
	 * Elements holder.
	 *
	 * @since 1.0.0
	 *
	 * @type {Object}
	 */
	let el = {};

	/**
	 * Public functions and properties.
	 *
	 * @since 1.0.0
	 */
	const app = {

		/**
		 * Start the engine.
		 *
		 * @since 1.0.0
		 */
		init() {
			app.ready();
		},

		/**
		 * DOM is fully loaded.
		 *
		 * @since 1.0.0
		 */
		ready() {
			app.setup();
			app.events();
		},

		/**
		 * Setup. Prepare some variables.
		 *
		 * @since 1.0.0
		 */
		setup() {
			// Cache DOM elements.
			el = {
				$builder: $( '#wpforms-builder' ),
			};
		},

		/**
		 * Add handlers on events.
		 *
		 * @since 1.0.0
		 */
		events() {
			el.$builder
				.on( 'change', '.wpforms-pdf-access-restrictions input[type=checkbox]', app.accessRestrictionsOptionHandler )
				.on( 'change', '.wpforms-pdf-password-restrictions input[type=checkbox]', app.passwordRestrictionsOptionHandler )
				.on( 'change', '.wpforms-pdf-user-restrictions select', app.userRestrictionsOptionHandler )
				.on( 'keyup focus', '.wpforms-pdf-password-input', app.cleanPasswordButtonHandler )
				.on( 'keyup', '.wpforms-pdf-password-input', app.checkPasswordMatch )
				.on( 'keyup', '.wpforms-pdf-password-confirm-input', app.checkPasswordMatch )
				.on( 'change', '.wpforms-pdf-password-input', app.sanitizePasswordValue )
				.on( 'click', '.wpforms-pdf-password-clean', app.cleanPasswordInput )
				.on( 'wpformsBeforeSave', app.checkPasswordMatchBeforeSave )
				.on( 'wpformsBuilderReady', app.initUserRestrictionsSelects );
		},

		/**
		 * Initialize user restrictions selects with ChoicesJS.
		 *
		 * @since 1.0.0
		 */
		initUserRestrictionsSelects() {
			$( '.wpforms-pdf-user-roles-select select' ).each( function() {
				app.initChoicesJS( $( this )[ 0 ], {}, wpforms_builder.pdf.access_restrictions.all_user_roles_selected );
			} );

			$( '.wpforms-pdf-user-names-select select' ).each( function() {
				app.initUserNamesSelect( $( this )[ 0 ] );
			} );
		},

		/**
		 * Initialize usernames select with AJAX search.
		 *
		 * @since 1.0.0
		 *
		 * @param {HTMLElement} select The select element to initialize.
		 */
		initUserNamesSelect( select ) {
			const ajaxArgs = {
				action: 'wpforms_ajax_search_user_names',
				nonce: wpforms_builder.nonce,
			};

			// From select, strip all options that have no value attribute set.
			const options = $( select ).find( 'option' );
			options.each( function() {
				if ( ! $( this ).attr( 'value' ) ) {
					$( this ).remove();
				}
			} );

			app.initChoicesJS( select, ajaxArgs );
		},

		/**
		 * Initialize ChoicesJS for the given select element.
		 *
		 * @since 1.0.0
		 *
		 * @param {HTMLElement} select        The select element to initialize ChoicesJS on.
		 * @param {Object}      ajaxArgs      Optional. Arguments for AJAX requests.
		 * @param {string}      noChoicesText Optional. Text to display when there are no choices.
		 */
		initChoicesJS( select, ajaxArgs = {}, noChoicesText = '' ) { // eslint-disable-line complexity
			if (
				! select ||
				typeof WPForms.Admin.Builder.WPFormsChoicesJS === 'undefined' ||
				! select.nodeName ||
				select.nodeName.toLowerCase() !== 'select'
			) {
				return;
			}

			if ( ! document.body.contains( select ) ) {
				return;
			}

			const choicesJS = WPForms.Admin.Builder.WPFormsChoicesJS.setup(
				select,
				{
					removeItemButton: true,
					noChoicesText,
					callbackOnInit() {
						if ( typeof wpf !== 'undefined' && typeof wpf.showMoreButtonForChoices === 'function' ) {
							wpf.showMoreButtonForChoices( this.containerOuter.element );
						}
					},
				},
				ajaxArgs
			);

			app.setChoicesJSInitialValue( choicesJS, select );
			app.addChoicesJSEventListeners( choicesJS );
		},

		/**
		 * Set initial value for ChoicesJS select.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object}      choicesJS The ChoicesJS instance.
		 * @param {HTMLElement} select    The select element.
		 */
		setChoicesJSInitialValue( choicesJS, select ) {
			const fieldId = $( select ).data( 'field-id' ),
				fieldName = $( select ).data( 'field-name' );

			const values = app.getHiddenValues( fieldId, fieldName );

			// For user roles, always ensure administrator is selected
			if (
				fieldName === 'user_roles_restrictions' &&
				( ! values || ! values.length || ! values.includes( 'administrator' ) )
			) {
				choicesJS.setChoiceByValue( [ 'administrator' ] );
			} else {
				choicesJS.setChoiceByValue( values );
			}
		},

		/**
		 * Add event listeners for ChoicesJS select.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} choicesJS The ChoicesJS instance.
		 */
		addChoicesJSEventListeners( choicesJS ) {
			const updateHiddenField = () => {
				const fieldId = $( choicesJS.passedElement.element ).data( 'field-id' );
				const fieldName = $( choicesJS.passedElement.element ).data( 'field-name' );
				const values = choicesJS.getValue( true ); // Get array of selected values
				const $hiddenField = $( `#settings-pdfs-${ fieldId }-${ fieldName }-options` );

				if ( $hiddenField.length ) {
					$hiddenField.val( JSON.stringify( values ) );
				}
			};

			choicesJS.passedElement.element.addEventListener( 'removeItem', function( event ) {
				// Set the selected value to 'administrator' if it is removed.
				if ( event.detail.value === 'administrator' ) {
					choicesJS.setChoiceByValue( 'administrator' );
				}

				if ( event.target.classList.contains( 'wpforms-pdf-user-names-select' ) ) {
					choicesJS.clearChoices();
				}

				// Update hidden field
				setTimeout( updateHiddenField, 10 );
			} );

			choicesJS.passedElement.element.addEventListener( 'addItem', function( event ) {
				if ( event.target.classList.contains( 'wpforms-pdf-user-names-select' ) ) {
					choicesJS.hideDropdown();
					choicesJS.clearChoices();
				}

				// Update hidden field
				setTimeout( updateHiddenField, 10 );
			} );
		},

		/**
		 * Get selected values from a hidden JSON field.
		 *
		 * @since 1.0.0
		 *
		 * @param {number} fieldId   The ID of the field.
		 * @param {string} fieldName The name of the field.
		 *
		 * @return {Array} The selected values.
		 */
		getHiddenValues( fieldId, fieldName ) {
			const $hiddenField = $( `#settings-pdfs-${ fieldId }-${ fieldName }-options` );
			const value = $hiddenField.val();

			if ( ! $hiddenField.length || ! value ) {
				return [];
			}

			let selected;

			try {
				selected = JSON.parse( value );
			} catch ( e ) {
				selected = {};
			}

			// Convert to an array of values and ensure they are strings.
			selected = Object.values( selected );

			return selected.map( function( item ) {
				return item.toString();
			} );
		},

		/**
		 * Handle access restrictions option change.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		accessRestrictionsOptionHandler( event ) {
			const $toggle = $( event.target ),
				$pdfBlock = $toggle.closest( '.wpforms-builder-settings-block' ),
				$restrictionSettings = $pdfBlock.find( '.wpforms-pdf-restriction-settings' ),
				isChecked = $toggle.is( ':checked' );

			if ( isChecked ) {
				$restrictionSettings.show();
			} else {
				$restrictionSettings.hide();
				$pdfBlock.find( '.wpforms-pdf-password-restrictions input[type=checkbox]' ).prop( 'checked', false ).trigger( 'change' );
				$pdfBlock.find( '.wpforms-pdf-user-restrictions select' ).val( 'none' ).trigger( 'change' );
			}
		},

		/**
		 * Handle password restrictions option change.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		passwordRestrictionsOptionHandler( event ) {
			const $toggle = $( event.target ),
				$pdfBlock = $toggle.closest( '.wpforms-builder-settings-block' ),
				$passwordFields = $pdfBlock.find( '.wpforms-pdf-password-fields-wrap' ),
				isChecked = $toggle.is( ':checked' );

			if ( isChecked ) {
				$passwordFields.show();
			} else {
				$passwordFields.hide();
				$pdfBlock.find( '.wpforms-pdf-password-field input' ).val( '' );
				$pdfBlock.find( '.wpforms-pdf-password-error' ).hide();
			}
		},

		/**
		 * Handle user restrictions option change.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		userRestrictionsOptionHandler( event ) {
			const $select = $( event.target ),
				$pdfBlock = $select.closest( '.wpforms-builder-settings-block' ),
				$userRolesWrap = $pdfBlock.find( '.wpforms-pdf-user-roles-restrictions-wrap' ),
				$userNamesWrap = $pdfBlock.find( '.wpforms-pdf-user-names-restrictions-wrap' ),
				value = $select.val();

			if ( value === 'none' ) {
				$userRolesWrap.hide();
				$userNamesWrap.hide();

				return;
			}

			$userRolesWrap.show();
			$userNamesWrap.show();

			// Initialize ChoicesJS for the select fields in this block if not already initialized
			const $userRolesSelect = $pdfBlock.find( '.wpforms-pdf-user-roles-select select' );
			const $userNamesSelect = $pdfBlock.find( '.wpforms-pdf-user-names-select select' );

			if ( $userRolesSelect.length && ! $userRolesSelect.hasClass( 'choices__input' ) ) {
				app.initChoicesJS( $userRolesSelect[ 0 ], {}, wpforms_builder.pdf.access_restrictions.no_user_roles_selected );
			}

			if ( $userNamesSelect.length && ! $userNamesSelect.hasClass( 'choices__input' ) ) {
				app.initUserNamesSelect( $userNamesSelect[ 0 ] );
			}
		},

		/**
		 * Handle clean password button visibility.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		cleanPasswordButtonHandler( event ) {
			const $input = $( event.target ),
				$passwordField = $input.closest( '.wpforms-pdf-password-field' ),
				$button = $passwordField.find( '.wpforms-pdf-password-clean' );

			if ( $input.val() ) {
				$button.show();
			} else {
				$button.hide();
			}
		},

		/**
		 * Clean password input.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		cleanPasswordInput( event ) {
			const $button = $( event.target ).closest( '.wpforms-pdf-password-clean' ),
				$passwordField = $button.closest( '.wpforms-pdf-password-fields-wrap' ).find( '.wpforms-pdf-password-field' );

			$passwordField.each( function() {
				const $input = $( this ).find( 'input' );

				$input.val( '' ).trigger( 'focus' );
			} );

			$button.hide();
		},

		/**
		 * Check if passwords match.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		checkPasswordMatch( event ) {
			const $confirmInput = $( event.target ),
				$pdfBlock = $confirmInput.closest( '.wpforms-builder-settings-block' ),
				$passwordInput = $confirmInput.hasClass( 'wpforms-pdf-password-input' ) ? $pdfBlock.find( '.wpforms-pdf-password-confirm-input' ) : $pdfBlock.find( '.wpforms-pdf-password-input' ),
				$error = $pdfBlock.find( '.wpforms-pdf-password-error' );

			if ( $confirmInput.val() !== $passwordInput.val() ) {
				$error.show();
				return;
			}

			$error.hide();
		},

		/**
		 * Sanitize password value.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		sanitizePasswordValue( event ) {
			const $input = $( event.target ),
				value = $input.val(),
				sanitized = value.replace( /\s+/g, '' );

			if ( value !== sanitized ) {
				$input.val( sanitized );
			}
		},

		/**
		 * Check if passwords match before save.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event The event object.
		 */
		checkPasswordMatchBeforeSave( event ) { // eslint-disable-line complexity
			const $form = $( event.target ),
				$pdfBlocks = $form.find( '.wpforms-builder-settings-block.wpforms-pdf' );

			let hasErrors = false,
				isPasswordEmpty = false,
				$errors,
				$passwordInput;

			$pdfBlocks.each( function() {
				const $pdfBlock = $( this );

				// Return early if password toggle is off.
				if ( ! $pdfBlock.find( '.wpforms-pdf-password-restrictions input[type=checkbox]' ).is( ':checked' ) ) {
					return;
				}

				$passwordInput = $pdfBlock.find( '.wpforms-pdf-password-input' );
				const $confirmInput = $pdfBlock.find( '.wpforms-pdf-password-confirm-input' );

				// If password or confirm password is empty, show error.
				if (
					( $passwordInput.val() && ! $confirmInput.val() ) ||
					( ! $passwordInput.val() && $confirmInput.val() )
				) {
					$pdfBlocks.find( '.wpforms-pdf-password-error' ).show();
				}

				$errors = $pdfBlocks.find( '.wpforms-pdf-password-error:visible' );

				hasErrors = hasErrors || $errors.length > 0;

				isPasswordEmpty = isPasswordEmpty || ! $passwordInput.val();
			} );

			if ( hasErrors ) {
				event.preventDefault();

				$.alert( {
					icon: 'fa fa-exclamation-triangle',
					type: 'red',
					title: wpforms_builder.pdf.access_restrictions.password_match_error_title,
					content: wpforms_builder.pdf.access_restrictions.password_match_error_text,
					buttons: {
						confirm: {
							text: wpforms_builder.close,
							btnClass: 'btn-confirm',
							action: () => {
								setTimeout( function() {
									$errors.first().closest( '.wpforms-pdf-password-confirm' ).find( 'input' ).trigger( 'focus' );
								}, 400 );
							},
						},
					},
				} );
			}

			if ( isPasswordEmpty ) {
				event.preventDefault();

				$.alert( {
					icon: 'fa fa-exclamation-triangle',
					type: 'red',
					title: wpforms_builder.pdf.access_restrictions.password_empty_error_title,
					content: wpforms_builder.pdf.access_restrictions.password_empty_error_text,
					buttons: {
						confirm: {
							text: wpforms_builder.close,
							btnClass: 'btn-confirm',
						},
					},
				} );
			}
		},
	};

	// Provide access to public functions/properties.
	return app;
}