HEX
Server: Apache/2.4.66 (Debian)
System: Linux 6dfabc3b2241 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64
User: (1000)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: /var/www/html/wp-content/plugins/wpgraphql-acf/src/assets/admin/js/main.js
$j = jQuery.noConflict();

$j(document).ready(function () {
	// Update the "graphql_field_name" when
	// the "name" field is updated.
	new acf.Model({
		actions: {
			change_field_name: 'updateGraphqlFieldName',
			render_field_settings: 'updateGraphqlFieldName',
		},
		updateGraphqlFieldName($el) {
			const field = acf.getInstance($el);
			const $name = field.$setting('name');
			const $nameField = acf.getInstance($name);

			// when a field is emptied, we'll do nothing
			if ('' === $nameField || undefined === $nameField) {
				field.prop('graphql_field_name', '');
				return;
			}

			if (undefined === $nameField?.getValue()) {
				field.prop('graphql_field_name', '');
				return;
			}

			const name = $nameField?.getValue() ?? null;

			if ('' === name) {
				field.prop('graphql_field_name', '');
				return;
			}

			const $graphqlFieldName = field?.$setting('graphql_field_name');
			const graphqlFieldName =
				acf?.getInstance($graphqlFieldName)?.getValue() ?? '';

			if (graphqlFieldName === '') {
				const sanitizedGraphqlFieldName = acf.strCamelCase(
					acf.strSanitize(name)
				);
				field.prop('graphql_field_name', sanitizedGraphqlFieldName);
			}
		},
	});

	const GraphqlLocationManager = new acf.Model({
		id: 'graphqlLocationManager',
		wait: 'ready',
		events: {
			render_field_settings: 'onChangeRemoveRule',
			'click .add-location-rule': 'onClickAddRule',
			'click .add-location-group': 'onClickAddGroup',
			'click .remove-location-rule': 'onClickRemoveRule',
			'change .refresh-location-rule': 'onChangeRemoveRule',
			'change .rule-groups .operator select': 'onChangeRemoveRule',
			'change .rule-groups .value select': 'onChangeRemoveRule',
		},
		requestPending: false,
		initialize() {
			// ACF with settings tabs
			let el = $j('#acf-field-group-options');

			// ACF with settings tabs
			if (!el.length) {
				// ACF before settings tabs existed
				el = $j('#acf-field-group-locations');
			}

			this.$el = el;
			this.getGraphqlTypes();
		},

		onClickAddRule(_e, _$el) {
			this.getGraphqlTypes();
		},

		onClickRemoveRule(_e, _$el) {
			this.getGraphqlTypes();
		},

		onChangeRemoveRule(_e, _$el) {
			setTimeout(function () {
				GraphqlLocationManager.getGraphqlTypes();
			}, 500);
		},

		onClickAddGroup(_e, _$el) {
			this.getGraphqlTypes();
		},

		isRequestPending() {
			return this.requestPending;
		},

		startRequest() {
			this.requestPending = true;
		},

		finishRequest() {
			this.requestPending = false;
		},

		getGraphqlTypes() {
			getGraphqlTypesFromLocationRules();
		},
	});

	/**
	 * Set the visibility of the GraphQL Fields based on the `show_in_graphql`
	 * field state.
	 */
	function setGraphqlFieldVisibility() {
		const showInGraphQLCheckbox = $j('#acf_field_group-show_in_graphql');
		const graphqlFields = $j('#wpgraphql-acf-meta-box .acf-field');

		graphqlFields.each(function (_i, _el) {
			if ($j(this).attr('data-name') !== 'show_in_graphql') {
				if (!showInGraphQLCheckbox.is(':checked')) {
					$j(this).hide();
				} else {
					$j(this).show();
				}
			}
		});

		showInGraphQLCheckbox.on('change', function () {
			setGraphqlFieldVisibility();
			getGraphqlTypesFromLocationRules();
		});
	}

	function toggleFieldRequirement() {
		$j('#acf_field_group-show_in_graphql').on('change', function () {
			const graphqlFieldNameWrap = $j(
					'.acf-field[data-name="graphql_field_name"]'
				),
				graphqlLabel = graphqlFieldNameWrap.find('label'),
				graphqlInput = $j('#acf_field_group-graphql_field_name');

			if ($j(this).is(':checked')) {
				// Add span.acf-required if necessary.
				if (graphqlFieldNameWrap.find('.acf-required').length === 0) {
					graphqlLabel.append('<span class="acf-required">*</span>');
				}

				// Toggle required attributes and visual features.
				graphqlFieldNameWrap.addClass('is-required');
				graphqlLabel.find('.acf-required').show();
				graphqlInput.attr('required', true);
			} else {
				graphqlFieldNameWrap.removeClass('is-required');
				graphqlLabel.find('.acf-required').hide();
				graphqlInput.attr('required', false);
			}
		});
	}

	/**
	 * Listen to state changes for checkboxes for Interfaces and the checkboxes for
	 * Possible Types of the interfaces
	 */
	function initInterfaceCheckboxes() {
		// Find all the checkboxes for Interface types
		$j('span[data-interface]').each(function (i, el) {
			// Get the interface name
			const interfaceName = $j(el).data('interface');

			// Get the checkbox for the interface
			const interfaceCheckbox = $j(
				'input[value="' + interfaceName + '"]'
			);

			// Find all checkboxes that implement the interface
			const possibleTypesCheckboxes = $j(
				'span[data-implements="' + interfaceName + '"]'
			).siblings('input[type="checkbox"]');

			// Prepend some space before to nest the Types beneath the Interface
			possibleTypesCheckboxes.before('&nbsp;&nbsp;');

			// Listen for changes on the Interface checkbox
			interfaceCheckbox.change(function () {
				possibleTypesCheckboxes.prop(
					'checked',
					$j(this).is(':checked')
				);
			});
		});
	}

	/**
	 * JavaScript version of the PHP lcfirst
	 *
	 * @param  str
	 * @return {string}
	 */
	function lcfirst(str) {
		str += '';
		const f = str.charAt(0).toLowerCase();
		return f + str.substr(1);
	}

	/**
	 * JavaScript version of the PHP ucwords
	 *
	 * @param  str
	 * @return {string}
	 */
	function ucwords(str) {
		return str.toLowerCase().replace(/\b[a-z]/g, function (letter) {
			return letter.toUpperCase();
		});
	}

	/**
	 * Based on the WPGraphQL format_field_name function
	 *
	 * See: https://github.com/wp-graphql/wp-graphql/blob/cc0b383259383898c3a1bebe65adf1140290b37e/src/Utils/Utils.php#L85-L100
	 * @param fieldName
	 */
	function formatFieldName(fieldName) {
		fieldName.replace('[^a-zA-Z0-9 -]', '-');
		fieldName = lcfirst(fieldName);
		fieldName = lcfirst(fieldName.split('-').join(' '));
		fieldName = ucwords(fieldName);
		fieldName = lcfirst(fieldName.split(' ').join(''));
		return fieldName;
	}

	/**
	 * Set the GraphQL Field Name value based on the Field Group Title
	 * if the graphql_field_name has not already been set.
	 */
	function setGraphqlFieldName() {
		const graphqlFieldNameField = $j('#acf_field_group-graphql_field_name');

		let fieldGroupTitle;
		// support for v6+
		if ($j('#title.acf-headerbar-title-field').exists()) {
			fieldGroupTitle = $j('#title.acf-headerbar-title-field');

			// versions of ACF < v6
		} else {
			fieldGroupTitle = $j('#titlediv #title');
		}

		if ('' === graphqlFieldNameField.val()) {
			graphqlFieldNameField.val(formatFieldName(fieldGroupTitle.val()));
		}
		fieldGroupTitle.on('change', function () {
			setGraphqlFieldName();
		});
	}

	/**
	 * Determine whether users should be able to interact with the checkboxes
	 * to manually set the GraphQL Types for the ACF Field Group
	 */
	function graphqlMapTypesFromLocations() {
		const checkboxes = $j(
			'.acf-field[data-name="graphql_types"] .acf-checkbox-list input[type="checkbox"]'
		);
		const manualMapTypes = $j(
			'#acf_field_group-map_graphql_types_from_location_rules'
		);

		if (manualMapTypes.not(':checked')) {
			getGraphqlTypesFromLocationRules();
		}

		checkboxes.each(function (_i, _el) {
			if (manualMapTypes.is(':checked')) {
				$j(this).removeAttr('disabled');
			} else {
				$j(this).attr('disabled', true);
			}
		});
		manualMapTypes.on('change', function () {
			graphqlMapTypesFromLocations();
		});
	}

	// Function to collect all nested fields under 'acf_field_group[location]'
	function collectFieldGroupData() {
		const selectors = [
			'[name^="acf_field_group[location]"]',
			'[name^="acf_field_group[graphql_field_name]"]',
			'[name^="post_title"]',
			'[name^="acf_field_group[active]"]',
		];

		// Select the fields that start with either of the specific name patterns
		const fields = $j(selectors.join(','));

		// Serialize only these fields
		const serializedData = fields.serialize();

		return serializedData;
	}

	function getGraphqlTypesFromLocationRules() {
		const showInGraphQLCheckbox = $j('#acf_field_group-show_in_graphql');
		const form = $j('#post');
		const checkboxes = $j(
			'.acf-field[data-name="graphql_types"] .acf-checkbox-list input[type="checkbox"]'
		);
		const manualMapTypes = $j(
			'#acf_field_group-map_graphql_types_from_location_rules'
		);

		// If Manual Type selection is checked,
		// Don't attempt to get GraphQL Types from the location rules
		if (manualMapTypes.is(':checked')) {
			return;
		}

		if (!showInGraphQLCheckbox.is(':checked')) {
			return;
		}

		if ('pending' !== form.attr('data-request-pending')) {
			// Start the request
			form.attr('data-request-pending', 'pending');

			// Make the request
			$j.post(
				ajaxurl,
				{
					action: 'get_acf_field_group_graphql_types',
					data: collectFieldGroupData(),
					nonce: wp_graphql_acf.nonce,
				},
				function (res) {
					const types =
						res && res.graphql_types ? res.graphql_types : [];

					checkboxes.each(function (_i, _el) {
						const checkbox = $j(this);
						const value = $j(this).val();
						checkbox.prop('checked', false);
						if (types && types.length) {
							if (-1 !== $j.inArray(value, types)) {
								checkbox.prop('checked', true);
							}
						}
						checkbox.trigger('change');
					});

					// Signal that the request is finished
					form.removeAttr('data-request-pending');
				}
			);
		}
	}

	// Initialize the functionality to track the state of the Interface checkboxes.
	initInterfaceCheckboxes();
	toggleFieldRequirement();
	setGraphqlFieldVisibility();
	setGraphqlFieldName();
	graphqlMapTypesFromLocations();
});