FM

/home/u523506497/domains/mymelon.in/public_html/wp-includes UP

<?php
/**
 * WP_View_Config_Data class
 *
 * @package WordPress
 * @since 7.1.0
 */

/**
 * Holds an entity's view configuration while it is being built.
 *
 * An instance of this class is what `get_entity_view_config_{$kind}_{$name}`
 * filter callbacks receive: a callback changes the configuration by calling
 * methods on the instance and returning it. The configuration has four
 * top-level keys — `default_view`, `default_layouts`, `view_list`, and
 * `form` — and there are three ways to contribute. They form a gradient of how
 * deep the replacement reaches:
 *
 * - The `merge()` method merges partial changes (patches) into what is already
 *   there: `default_view`, `default_layouts`, and the `form` settings by key,
 *   and the `view_list` entries by view `slug` identity. This is what plugins
 *   should use: patches compose with core's configuration and with other
 *   plugins'.
 * - `replace()` applies a patch the same way `merge()` does, with one
 *   difference: a list in the patch replaces the current list wholesale
 *   instead of merging into it by member identity. It shouldn't be the
 *   default choice — a callback that replaces a list stops inheriting core's
 *   future additions to it — but it's useful when a contributor needs to pin
 *   a list to an exact set of members.
 * - `set()` goes one step further: it replaces each top-level key the patch
 *   names wholesale, dropping whatever that key held instead of merging into
 *   it. It's for a callback that owns a key outright and wants to pin it to an
 *   exact shape without the inherited default leaking through a key-by-key
 *   merge.
 *
 * All three touch only the top-level keys the patch names — an omitted key
 * keeps whatever it had, and a top-level `null` value drops the key it names,
 * which resets it to its default. They differ only in how deep the replacement
 * reaches once a key is named: `merge()` and `replace()` merge the value in
 * key by key (an associative array merges member by member, a nested `null`
 * deletes just that leaf, a scalar replaces just that value), while `set()`
 * swaps the whole value. A nested `null` deletes just the leaf it names in
 * every case. A patch value whose shape does not match the current value —
 * an associative array where a list lives, or the reverse — is rejected with
 * a notice rather than merged, and an empty array under `merge()` is a
 * no-op. Each patch also declares the configuration schema
 * version it was written against (currently 1), so a future WordPress release
 * that changes the configuration shape can migrate existing patches forward
 * instead of breaking them.
 *
 * Where those three write values, `remove()` deletes them: it takes a spec of
 * names — a list to delete entries at a level, or a nested map to reach deeper —
 * and prunes just what it names, mirroring the configuration's shape all the way
 * down to individual list members.
 *
 * @since 7.1.0
 */
class WP_View_Config_Data {

	/**
	 * The latest supported configuration schema version.
	 *
	 * @since 7.1.0
	 * @var int
	 */
	const LATEST_VERSION = 1;

	/**
	 * The documented top-level configuration keys.
	 *
	 * @since 7.1.0
	 * @var string[]
	 */
	const CONFIG_KEYS = array( 'default_view', 'default_layouts', 'view_list', 'form' );

	/**
	 * The configuration being contributed to.
	 *
	 * @since 7.1.0
	 * @var array
	 */
	private $config;

	/**
	 * The default configuration.
	 *
	 * @since 7.1.0
	 * @var array
	 */
	private $defaults;

	/**
	 * Constructor.
	 *
	 * @since 7.1.0
	 *
	 * @param array $config The base configuration to contribute to.
	 */
	public function __construct( array $config ) {
		$this->config   = $config;
		$this->defaults = $config;
	}

	/**
	 * Returns the current configuration array.
	 *
	 * Deliberately private: filter callbacks receive the container, not the
	 * materialized configuration, so they cannot read the built result and
	 * become coupled to a specific configuration shape or schema version. Only
	 * the class itself reconciles the container back into an array.
	 *
	 * @since 7.1.0
	 *
	 * @return array The configuration.
	 */
	private function get_data() {
		return $this->config;
	}

	/**
	 * Applies the entity view configuration filter and returns the result.
	 *
	 * Exposes the container through the dynamic
	 * `get_entity_view_config_{$kind}_{$name}` filter (with the dynamic portions
	 * lowercased), so that core and third parties can provide the configuration for a specific entity,
	 * then reconciles the filtered container back into a plain configuration array,
	 * limited to the documented configuration keys.
	 *
	 * @since 7.1.0
	 *
	 * @param string $kind The entity kind (e.g. `postType`).
	 * @param string $name The entity name (e.g. `page`).
	 * @return array The filtered configuration, limited to the documented keys.
	 */
	public function apply_filters( $kind, $name ) {
		/**
		 * Filters the view configuration for a given entity.
		 *
		 * The dynamic portions of the hook name, `$kind` and `$name`, refer to the
		 * entity kind (e.g. `postType`) and the entity name (e.g. `page`),
		 * lowercased — so the `postType`/`page` entity maps to the
		 * `get_entity_view_config_posttype_page` hook.
		 *
		 * Callbacks receive a WP_View_Config_Data object and change the
		 * configuration through its methods. Each write method takes the schema
		 * version the change was authored against as its second argument,
		 * and returns the object for chaining:
		 *
		 * - `merge( $patch, $version )` merges a partial change into the current
		 *   configuration. It touches only the top-level keys the patch names, and
		 *   merges each named value into the current one by shape: a scalar
		 *   replaces, an associative array merges key by key, and a list merges by
		 *   member identity (`id`, `slug`, or `field`). A `null` value drops the
		 *   key it names, resetting it to its default.
		 * - `replace( $patch, $version )` applies a patch exactly like `merge()`,
		 *   but swaps any list it names wholesale instead of merging that list by
		 *   member identity.
		 * - `set( $patch, $version )` also touches only the keys the patch names,
		 *   but swaps each named value in wholesale, dropping whatever the key held
		 *   before — for a callback that owns those keys outright.
		 * - `remove( $spec, $version )` deletes named properties. The spec mirrors
		 *   the configuration shape: a list of names deletes entries at that level,
		 *   and a nested map recurses to prune from within a named value, down to
		 *   individual list members.
		 *
		 * A change that declares an unsupported schema version is rejected and does
		 * not alter anything. As with any filter, each callback's return value is
		 * passed to the next callback as `$data`, so callbacks must return the
		 * container they received: a callback that returns nothing, or any other
		 * value, hands that result to every callback hooked at a later priority
		 * instead of the container. Since the write methods return the container,
		 * a callback can end with `return $data->merge( $patch, $version );`.
		 *
		 * @since 7.1.0
		 *
		 * @param WP_View_Config_Data $data   The view configuration container
		 *                                    for the entity, exposing the
		 *                                    `default_view`, `default_layouts`,
		 *                                    `view_list`, and `form` keys.
		 * @param array               $entity {
		 *     The entity the configuration is built for.
		 *
		 *     @type string $kind The entity kind.
		 *     @type string $name The entity name.
		 * }
		 */
		apply_filters(
			wp_get_entity_view_config_hook_name( $kind, $name ),
			$this,
			array(
				'kind' => $kind,
				'name' => $name,
			)
		);

		// Discard any keys the filter introduced that are not part of the
		// documented configuration shape.
		return array_intersect_key( $this->get_data(), array_flip( self::CONFIG_KEYS ) );
	}

	/**
	 * Replaces whole top-level keys, leaving the rest of the configuration alone.
	 *
	 * Like merge() and replace(), set() applies a patch of top-level keys and
	 * touches only the keys the patch names: a key the patch omits keeps whatever
	 * it had, and a `null` value drops the key it names (which resets it to its
	 * default). The difference is depth — where merge() and replace() merge a
	 * named key's value into the current one key by key, set() swaps the whole
	 * value in wholesale, dropping whatever the key held before. A `null` nested
	 * within that value still drops the property it names, so set() honours
	 * nulls at every depth just as merge() and replace() do.
	 *
	 * Use it when a callback owns a key outright and wants to pin it to an exact
	 * shape, without the inherited default leaking through a key-by-key merge.
	 *
	 * A patch that declares an unsupported schema version is rejected and does
	 * not change anything.
	 *
	 * @since 7.1.0
	 *
	 * @param array $patch   The partial configuration whose named keys to replace.
	 * @param int   $version The schema version the patch was authored against.
	 * @return WP_View_Config_Data The instance, for chaining.
	 */
	public function set( array $patch, int $version ) {
		return $this->apply( $patch, $version, __METHOD__, 'set' );
	}

	/**
	 * Removes named properties from the configuration, leaving the rest alone.
	 *
	 * Where merge(), replace(), and set() take a patch of *values* to write,
	 * remove() takes a spec of *names* to delete, and its shape mirrors the
	 * configuration it prunes:
	 *
	 * - A list of names deletes each named entry from the value at that level: a
	 *   key from an associative array, or the member with a matching identity
	 *   (`id`, `slug`, `field`, or a bare scalar) from a list.
	 * - An associative array maps a name to a nested spec, recursing into that
	 *   entry's value to delete from within it.
	 *
	 * Naming a top-level configuration key is the one exception: like a `null`
	 * value in a patch, it resets that key to its default rather than dropping it
	 * outright, so top-level removal and top-level `null` compose the same way.
	 *
	 * So `array( 'default_view' )` resets the whole `default_view` key to its
	 * default, `array( 'default_view' => array( 'sort' ) )` drops just its `sort`
	 * property, and `array( 'default_view' => array( 'fields' => array( 'f2' ) ) )`
	 * drops the `f2` member from its `fields` list. A name that is not present is
	 * ignored, and a list is renumbered after a member is removed.
	 *
	 * A spec that declares an unsupported schema version is rejected and does not
	 * change anything.
	 *
	 * @since 7.1.0
	 *
	 * @param array $spec    The names to remove, keyed to match the configuration shape.
	 * @param int   $version The schema version the spec was authored against.
	 * @return WP_View_Config_Data The instance, for chaining.
	 */
	public function remove( array $spec, int $version ) {
		if ( $version <= 0 || $version > self::LATEST_VERSION ) {
			_doing_it_wrong(
				__METHOD__,
				esc_html__( 'A view configuration patch must declare a supported schema version.' ),
				'7.1.0'
			);

			return $this;
		}

		// A flat list names top-level keys to reset; a map recurses into each
		// named key to prune from within its value.
		$spec_is_list = array_is_list( $spec );
		foreach ( $spec as $spec_key => $spec_value ) {
			$key = $spec_is_list ? $spec_value : $spec_key;

			if ( ! in_array( $key, self::CONFIG_KEYS, true ) ) {
				_doing_it_wrong(
					__METHOD__,
					sprintf(
						/* translators: %s: the configuration key. */
						esc_html__( '"%s" is not a documented view configuration key.' ),
						esc_html( $key )
					),
					'7.1.0'
				);
				continue;
			}

			if ( $spec_is_list ) {
				// Removing a top-level key resets it to its default, just as a
				// null patch value does.
				$this->config[ $key ] = $this->defaults[ $key ] ?? array();
			} elseif ( array_key_exists( $key, $this->config ) ) {
				$this->config[ $key ] = $this->remove_properties( $this->config[ $key ], $spec_value );
			}
		}

		return $this;
	}

	/**
	 * Replaces list values while merging the rest of a partial configuration.
	 *
	 * Takes the same arguments as merge() and applies the patch the same way,
	 * with one difference: a list in the patch replaces the current list
	 * wholesale instead of merging into it by member identity. Associative
	 * arrays still merge key by key, `null` still drops what it names, and a
	 * scalar still replaces the current value.
	 *
	 * It shouldn't be the default choice — a callback that replaces a list
	 * stops inheriting core's future additions to it — but it's useful when a
	 * contributor needs to pin a list to an exact set of members.
	 *
	 * The shape rule applies here too: a patch value whose shape does not match
	 * the current value — an associative array where a list lives, or a
	 * non-empty list where an associative value lives — is rejected with a
	 * notice and leaves the current value unchanged. An empty array is exempt,
	 * so replacing a list with an empty list still clears it.
	 *
	 * A patch that declares an unsupported schema version is rejected and does
	 * not change anything.
	 *
	 * @since 7.1.0
	 *
	 * @param array $patch   The partial configuration to apply.
	 * @param int   $version The schema version the patch was authored against.
	 * @return WP_View_Config_Data The instance, for chaining.
	 */
	public function replace( array $patch, int $version ) {
		return $this->apply( $patch, $version, __METHOD__, 'replace' );
	}

	/**
	 * Merges a partial configuration into the existing one.
	 *
	 * Applies a patch of top-level keys and touches only the keys the patch
	 * names: a key the patch omits keeps whatever it had, and a `null` value
	 * drops the key it names (which resets it to its default). Each named key's
	 * value is then merged into the current one by value shape:
	 *
	 * - a scalar replaces the current value;
	 * - an associative array merges key by key, with a nested `null` deleting
	 *   just the leaf it names;
	 * - a list merges into the current list by member identity.
	 *
	 * Identity is the member's value cast to a string: a bare scalar is its own
	 * identity, and a map is identified by the value of the first of the
	 * well-known identity keys (`id`, `slug`, `field`) it carries. A member
	 * whose identity matches one already present merges into it in place, keeping
	 * its position; a member with no identity is appended to the end of the list.
	 *
	 * For example, given this patch:
	 *
	 * ```php
	 * array(
	 *   'default_view' => array( 'titleField' => 'newTitleField', 'fields' => array( 'newField' ) ),
	 *   'default_layouts' => array( 'grid' => array( 'layout' => array( 'badgeFields' => array( 'newField' ) ) ) ),
	 *   'view_list' => array( array( 'slug' => 'table', 'title' => 'New title' ) ),
	 * )
	 * ```
	 *
	 * - default_view will be updated so the titleField is 'newTitleField' and the newField is appended to the list of fields.
	 * - default_layouts will be updated so that newField is appended to the badgeFields.
	 * - view_list will be updated so that the view with slug 'table' has its title changed to 'New title'.
	 *
	 * A patch value only merges into a current value of the same shape: an
	 * associative array where a list lives, or a non-empty list where an
	 * associative value lives, is rejected with a notice and leaves the current
	 * value unchanged. An empty array merges nothing and is a no-op — clear a
	 * list with replace() and an empty list, or reset a key to its default with
	 * a top-level `null`.
	 *
	 * A patch that declares an unsupported schema version is rejected and does
	 * not change anything.
	 *
	 * @since 7.1.0
	 *
	 * @param array $patch   The partial configuration to merge.
	 * @param int   $version The schema version the patch was authored against.
	 * @return WP_View_Config_Data The instance, for chaining.
	 */
	public function merge( array $patch, int $version ) {
		return $this->apply( $patch, $version, __METHOD__, 'merge' );
	}

	/**
	 * Applies a patch to the configuration, top-level key by top-level key.
	 *
	 * Shared by merge(), replace(), and set(); the three differ only in how the
	 * value of a named key is applied, which is carried by $mode:
	 *
	 * - `merge`   merges the value into the current one, lists by member identity;
	 * - `replace` merges the value in the same way but swaps lists wholesale;
	 * - `set`     swaps the whole value in wholesale, without merging.
	 *
	 * In every mode a top-level `null` resets the key it names to its default, a
	 * nested `null` drops the property it names, and an omitted key is left
	 * untouched, so all three treat nulls the same way at every depth.
	 *
	 * @since 7.1.0
	 *
	 * @param array  $patch   The partial configuration to apply.
	 * @param int    $version The schema version the patch was authored against.
	 * @param string $method  The public method the patch was passed to, for misuse reporting.
	 * @param string $mode    How to apply each named key's value: `merge`, `replace`, or `set`.
	 * @return WP_View_Config_Data The instance, for chaining.
	 */
	private function apply( array $patch, int $version, $method, $mode ) {
		if ( $version <= 0 || $version > self::LATEST_VERSION ) {
			_doing_it_wrong(
				esc_html( $method ),
				esc_html__( 'A view configuration patch must declare a supported schema version.' ),
				'7.1.0'
			);

			return $this;
		}

		foreach ( $patch as $key => $value ) {
			if ( ! in_array( $key, self::CONFIG_KEYS, true ) ) {
				_doing_it_wrong(
					esc_html( $method ),
					sprintf(
						/* translators: %s: the configuration key. */
						esc_html__( '"%s" is not a documented view configuration key.' ),
						esc_html( $key )
					),
					'7.1.0'
				);
				continue;
			}

			// A null patch value makes the top-level property reset to defaults.
			if ( null === $value ) {
				$this->config[ $key ] = $this->defaults[ $key ] ?? array();
				continue;
			}

			// set() swaps the whole value in; merge()/replace() merge it into the
			// current one, differing only in how they treat lists. In every mode a
			// nested null still drops the property it names.
			$this->config[ $key ] = 'set' === $mode
				? $this->strip_nulls( $value )
				: $this->merge_properties( $this->config[ $key ] ?? array(), $value, 'replace' === $mode );
		}

		return $this;
	}

	/**
	 * Recursively drops every property whose value is `null` from a value.
	 *
	 * set() swaps a named key's value in wholesale rather than merging it into
	 * the current one, so it has no existing leaf for a nested `null` to delete
	 * the way merge() and replace() do. Stripping nulls here gives a nested
	 * `null` the same "drop the property it names" meaning under set() that it
	 * carries everywhere else. The same applies to a list replace() swaps in
	 * wholesale. A list is renumbered after a member is removed so removed
	 * entries do not leave gaps.
	 *
	 * @since 7.1.0
	 *
	 * @param mixed $value The value to strip nulls from.
	 * @return mixed The value with every `null` property removed, recursively.
	 */
	private function strip_nulls( $value ) {
		if ( ! is_array( $value ) ) {
			return $value;
		}

		$result = array();
		foreach ( $value as $key => $item ) {
			// A null value drops the property it names.
			if ( null === $item ) {
				continue;
			}

			$result[ $key ] = $this->strip_nulls( $item );
		}

		// Renumber a list so a removed member does not leave a gap.
		return array_is_list( $value ) ? array_values( $result ) : $result;
	}

	/**
	 * Merges an incoming value into the current one, recursing by value shape.
	 *
	 * This is the core of the merge algorithm and is applied at every nesting
	 * level: a scalar (or `null`) in $incoming replaces $current outright, an
	 * associative array merges key by key (recursing here for each key, with a
	 * `null` value deleting that key), and a list either replaces $current
	 * wholesale ($replace_lists) or merges into it by member identity. The
	 * $replace_lists flag is carried down through associative nesting so that,
	 * under replace(), every list reached along the way is swapped wholesale.
	 *
	 * An array in $incoming only merges into a current value of the same shape.
	 * A non-empty mismatch — an associative array where a list lives, or a
	 * non-empty list where an associative value lives — is reported with
	 * _doing_it_wrong() and leaves the current value unchanged, so a malformed
	 * patch cannot silently destroy configuration. An empty array is
	 * shape-ambiguous and merges nothing, so it is a no-op: clearing a list is
	 * spelled replace() with an empty list, and resetting a key is spelled
	 * `null`.
	 *
	 * @since 7.1.0
	 *
	 * @param mixed $current       The current value.
	 * @param mixed $incoming      The incoming value.
	 * @param bool  $replace_lists Whether a list in $incoming replaces the current list
	 *                             wholesale instead of merging into it by member identity.
	 * @return mixed The merged value.
	 */
	private function merge_properties( $current, $incoming, $replace_lists ) {
		// Scalar properties are merged as-is.
		if ( ! is_array( $incoming ) ) {
			return $incoming;
		}

		// Numerical indexed arrays are expected to be lists (sequential integer keys starting at 0).
		if ( array_is_list( $incoming ) ) {
			// A non-empty list only lands where a list (or nothing) lives, under
			// merge() and replace() alike. An empty array is shape-ambiguous and
			// exempt, so replace() with an empty list can still clear a list.
			if ( array() !== $incoming && is_array( $current ) && ! array_is_list( $current ) && array() !== $current ) {
				_doing_it_wrong(
					__METHOD__,
					esc_html__( 'A view configuration patch value must match the shape of the value it patches: a list merges into a list, and an associative array into an associative array.' ),
					'7.1.0'
				);
				return $current;
			}

			// replace() takes an incoming list as-is; merge() merges it by member identity.
			if ( $replace_lists ) {
				// As-is except for nulls: a list swapped in wholesale has no
				// existing leaf for a null to delete (the same rationale as
				// set()), so a null member is dropped rather than stored.
				return $this->strip_nulls( $incoming );
			}

			// An empty list has no members to merge, and an empty array is
			// shape-ambiguous, so merging one is a no-op rather than a reset.
			if ( array() === $incoming ) {
				return $current;
			}

			return $this->merge_list_by_identity(
				is_array( $current ) && array_is_list( $current ) ? $current : array(),
				$incoming
			);
		}

		// Consider any other array as associative (keys are strings).
		if ( is_array( $current ) && array_is_list( $current ) && array() !== $current ) {
			_doing_it_wrong(
				__METHOD__,
				esc_html__( 'A view configuration patch value must match the shape of the value it patches: a list merges into a list, and an associative array into an associative array.' ),
				'7.1.0'
			);
			return $current;
		}

		$result = is_array( $current ) && ! array_is_list( $current ) ? $current : array();
		foreach ( $incoming as $key => $value ) {
			// A null patch value deletes the property.
			if ( null === $value ) {
				unset( $result[ $key ] );
				continue;
			}

			$result[ $key ] = $this->merge_properties(
				array_key_exists( $key, $result ) ? $result[ $key ] : array(),
				$value,
				$replace_lists
			);
		}

		return $result;
	}

	/**
	 * Removes the properties a spec names from the current value.
	 *
	 * The mirror of merge_properties(), applied at every nesting level: a list in
	 * $spec names entries to delete from $current — associative keys are unset,
	 * and list members are matched by identity (list_item_identity) and dropped —
	 * while an associative $spec recurses into each named entry to prune from
	 * within it. A name absent from $current is ignored, and a list is renumbered
	 * after members are removed so it keeps sequential keys.
	 *
	 * @since 7.1.0
	 *
	 * @param mixed $current The current value.
	 * @param mixed $spec    The names to remove from it.
	 * @return mixed The pruned value.
	 */
	private function remove_properties( $current, $spec ) {
		if ( ! is_array( $current ) || ! is_array( $spec ) ) {
			return $current;
		}

		$current_is_list = array_is_list( $current );

		if ( array_is_list( $spec ) ) {
			// Each entry names something to delete from the current value.
			foreach ( $spec as $name ) {
				if ( $current_is_list ) {
					$current = $this->remove_list_member( $current, $name );
				} else {
					unset( $current[ $name ] );
				}
			}
		} else {
			// Each key names an entry to recurse into and prune from within.
			foreach ( $spec as $name => $subspec ) {
				if ( $current_is_list ) {
					foreach ( $current as $index => $member ) {
						if ( $this->list_item_identity( $member ) === (string) $name ) {
							$current[ $index ] = $this->remove_properties( $member, $subspec );
							break;
						}
					}
				} elseif ( array_key_exists( $name, $current ) ) {
					$current[ $name ] = $this->remove_properties( $current[ $name ], $subspec );
				}
			}
		}

		// Renumber so a list from which a member was removed keeps sequential keys.
		return $current_is_list ? array_values( $current ) : $current;
	}

	/**
	 * Removes the first list member matching an identity, leaving the rest.
	 *
	 * @since 7.1.0
	 *
	 * @param array $members  The current list.
	 * @param mixed $identity The identity of the member to remove.
	 * @return array The list with the matching member removed, if any.
	 */
	private function remove_list_member( array $members, $identity ) {
		foreach ( $members as $index => $member ) {
			if ( $this->list_item_identity( $member ) === (string) $identity ) {
				unset( $members[ $index ] );
				break;
			}
		}

		return $members;
	}

	/**
	 * Merges an incoming list into the current one by member identity.
	 *
	 * A member of the incoming list whose identity matches one already present
	 * merges into it in place, keeping its position; an unmatched member is
	 * appended to the end, except a literal `null`, which carries no identity
	 * and holds nothing to merge and so is dropped. An appended member has no
	 * existing leaf for a nested `null` to delete (the same rationale as set()),
	 * so its nulls are stripped rather than stored. A matched member's contents
	 * merge recursively with the same rules (merge_properties), so the
	 * identity-aware merge applies at
	 * any nesting level: each key named by the patch is substituted while the
	 * others are left intact, and a list nested inside a member merges by
	 * identity just like the list it lives in.
	 *
	 * @since 7.1.0
	 *
	 * @param array $current  The current list.
	 * @param array $incoming The incoming list.
	 * @return array The merged list.
	 */
	private function merge_list_by_identity( array $current, array $incoming ) {
		$result = $current;
		foreach ( $incoming as $item ) {
			// A null member carries no identity and holds nothing to merge,
			// so it is dropped rather than appended as a literal null.
			if ( null === $item ) {
				continue;
			}

			$identity = $this->list_item_identity( $item );

			// Find the index of the existing member with the same identity, if any.
			// If there's none, append the incoming member to the end of the list.
			$index = null;
			if ( null !== $identity ) {
				foreach ( $result as $i => $existing ) {
					if ( $this->list_item_identity( $existing ) === $identity ) {
						$index = $i;
						break;
					}
				}
			}
			if ( null === $index ) {
				// An appended member has no existing leaf for a nested null to
				// delete, so nulls are dropped rather than stored.
				$result[] = $this->strip_nulls( $item );
				continue;
			}

			// Otherwise, merge the incoming member into the existing one in place.
			$result[ $index ] = $this->merge_properties( $result[ $index ], $item, false );
		}

		return $result;
	}

	/**
	 * Resolves the identity used to match a list member against another.
	 *
	 * The identity is simply the member's value cast to a string, regardless of
	 * which key carries it: a bare scalar is its own identity, and a map is
	 * identified by the value of the first of the well-known identity keys
	 * (`id`, `slug`, `field`) it carries. Because the key is not part of
	 * the identity, a bare field like `'f3'` matches any map carrying that
	 * value, whether it appears as `array( 'id' => 'f3' )`,
	 * `array( 'slug' => 'f3' )`, and so on — this lets the same shorthand target
	 * lists keyed by different fields. Casting to string keeps numeric
	 * identities matching whether they arrive as an int or a string. Anything
	 * else (e.g. a nested list) has no identity and never matches, so it is
	 * always appended.
	 *
	 * @since 7.1.0
	 *
	 * @param mixed $item The list member.
	 * @return string|null The identity, or null when the member has none.
	 */
	private function list_item_identity( $item ) {
		if ( is_scalar( $item ) ) {
			return (string) $item;
		}

		if ( is_array( $item ) && ! array_is_list( $item ) ) {
			foreach ( array( 'id', 'slug', 'field' ) as $key ) {
				if ( isset( $item[ $key ] ) && is_scalar( $item[ $key ] ) ) {
					return (string) $item[ $key ];
				}
			}
		}

		return null;
	}
}
ID3-
IXR-
PHPMailer-
Requests-
SimplePie-
Text-
abilities-api-
abilities-api.php32800V
abilities.php11797V
admin-bar.php40067V
ai-client-
ai-client.php2549V
assets-
atomlib.php12181V
author-template.php19844V
block-bindings-
block-bindings.php7632V
block-editor.php28724V
block-i18n.json316V
block-patterns-
block-patterns.php15606V
block-supports-
block-template-utils.php63477V
block-template.php18257V
blocks-
blocks.php124205V
bookmark-template.php12768V
bookmark.php15427V
build-
cache-compat.php11021V
cache.php13486V
canonical.php34786V
capabilities.php43584V
category-template.php56990V
category.php12834V
certificates-
class-IXR.php2609V
class-avif-info.php30008V
class-feed.php539V
class-http.php367V
class-json.php171V
class-oembed.php401V
class-phpass.php6771V
class-phpmailer.php664V
class-pop3.php171V
class-requests.php2237V
class-simplepie.php453V
class-smtp.php457V
class-snoopy.php37715V
class-spl.php171V
class-walker-category-dropdown.php2469V
class-walker-category.php8477V
class-walker-comment.php14221V
class-walker-nav-menu.php12044V
class-walker-page-dropdown.php2710V
class-walker-page.php7612V
class-wp-admin-bar.php18002V
class-wp-ajax-response.php5288V
class-wp-application-passwords.php17099V
class-wp-block-bindings-registry.php8263V
class-wp-block-bindings-source.php2992V
class-wp-block-editor-context.php1350V
class-wp-block-list.php4713V
class-wp-block-metadata-registry.php11846V
class-wp-block-parser-block.php2555V
class-wp-block-parser-frame.php1994V
class-wp-block-parser.php11525V
class-wp-block-pattern-categories-registry.php4383V
class-wp-block-patterns-registry.php10265V
class-wp-block-processor.php69914V
class-wp-block-styles-registry.php6419V
class-wp-block-supports.php7578V
class-wp-block-template.php2111V
class-wp-block-templates-registry.php7080V
class-wp-block-type-registry.php5305V
class-wp-block-type.php17222V
class-wp-block.php28236V
class-wp-classic-to-block-menu-converter.php4026V
class-wp-comment-query.php49040V
class-wp-comment.php17249V
class-wp-connector-registry.php15181V
class-wp-customize-control.php26112V
class-wp-customize-manager.php202908V
class-wp-customize-nav-menus.php58034V
class-wp-customize-panel.php10703V
class-wp-customize-section.php11209V
class-wp-customize-setting.php29956V
class-wp-customize-widgets.php72596V
class-wp-date-query.php35970V
class-wp-dependencies.php17089V
class-wp-dependency.php2653V
class-wp-duotone.php40836V
class-wp-editor.php72228V
class-wp-embed.php15908V
class-wp-error.php7514V
class-wp-exception.php253V
class-wp-fatal-error-handler.php8150V
class-wp-feed-cache-transient.php3304V
class-wp-feed-cache.php969V
class-wp-filter-sentinel.php760V
class-wp-hook.php17584V
class-wp-http-cookie.php7269V
class-wp-http-curl.php13261V
class-wp-http-encoding.php6689V
class-wp-http-ixr-client.php3516V
class-wp-http-proxy.php5980V
class-wp-http-requests-hooks.php2022V
class-wp-http-requests-response.php4243V
class-wp-http-response.php2977V
class-wp-http-streams.php16764V
class-wp-http.php41641V
class-wp-icon-collections-registry.php5805V
class-wp-icons-registry.php9903V
class-wp-image-editor-gd.php20741V
class-wp-image-editor-imagick.php43454V
class-wp-image-editor.php17456V
class-wp-list-util.php7443V
class-wp-locale-switcher.php6776V
class-wp-locale.php16848V
class-wp-matchesmapregex.php1828V
class-wp-meta-query.php30507V
class-wp-metadata-lazyloader.php6833V
class-wp-navigation-fallback.php9193V
class-wp-network-query.php19989V
class-wp-network.php12411V
class-wp-object-cache.php17524V
class-wp-oembed-controller.php6905V
class-wp-oembed.php34372V
class-wp-paused-extensions-storage.php5067V
class-wp-phpmailer.php4348V
class-wp-plugin-dependencies.php25209V
class-wp-post-type-variable.php0V
class-wp-post-type.php30672V
class-wp-post.php8806V
class-wp-query.php164148V
class-wp-recovery-mode-cookie-service.php6877V
class-wp-recovery-mode-email-service.php11162V
class-wp-recovery-mode-key-service.php4914V
class-wp-recovery-mode-link-service.php3523V
class-wp-recovery-mode.php11460V
class-wp-rewrite.php63693V
class-wp-role.php2523V
class-wp-roles.php9326V
class-wp-script-modules.php40743V
class-wp-scripts.php36754V
class-wp-session-tokens.php7319V
class-wp-simplepie-file.php3552V
class-wp-simplepie-sanitize-kses.php1903V
class-wp-site-query.php31482V
class-wp-site.php7836V
class-wp-speculation-rules.php7884V
class-wp-styles.php13316V
class-wp-tax-query.php19577V
class-wp-taxonomy.php18559V
class-wp-term-query.php40751V
class-wp-term.php5263V
class-wp-text-diff-renderer-inline.php979V
class-wp-text-diff-renderer-table.php18925V
class-wp-textdomain-registry.php10481V
class-wp-theme-json-data.php1805V
class-wp-theme-json-resolver.php35692V
class-wp-theme-json-schema.php7367V
class-wp-theme-json.php222059V
class-wp-theme.php65811V
class-wp-token-map.php29032V
class-wp-url-pattern-prefixer.php4802V
class-wp-user-meta-session-tokens.php2954V
class-wp-user-query.php44102V
class-wp-user-request.php2342V
class-wp-user.php23189V
class-wp-view-config-data.php29427V
class-wp-walker.php13292V
class-wp-widget-factory.php4113V
class-wp-widget.php18452V
class-wp-xmlrpc-server.php217288V
class-wp.php26520V
class-wpdb.php121437V
class.wp-dependencies.php373V
class.wp-scripts.php343V
class.wp-styles.php338V
comment-template.php103211V
comment.php150630V
compat-utf8.php19386V
compat.php22479V
connectors.php32922V
cron.php46266V
css-
customize-
date.php400V
default-constants.php11365V
default-filters.php39500V
default-widgets.php2288V
deprecated.php193977V
embed-template.php338V
embed.php39215V
error-protection.php4092V
feed-atom-comments.php5504V
feed-atom.php3114V
feed-rdf.php2668V
feed-rss-core.php146V
feed-rss.php1189V
feed-rss2-comments.php4136V
feed-rss2.php3799V
feed.php25189V
fonts-
fonts.php9789V
formatting.php357678V
functions.php295481V
functions.wp-scripts.php20492V
functions.wp-styles.php8654V
general-template-get.php146V
general-template.php184198V
global-styles-and-settings.php20780V
html-api-
http.php28961V
https-detection.php5857V
https-migration.php4741V
icons.php6334V
images-
interactivity-api-
js-
json-schema.php7802V
kses.php88497V
l10n-
l10n.php71415V
link-template.php160143V
load.php56475V
locale.php162V
media-template.php65759V
media.php236804V
meta.php66739V
ms-blogs.php26324V
ms-default-constants.php4921V
ms-default-filters.php6636V
ms-deprecated.php21787V
ms-files.php2857V
ms-functions.php92530V
ms-load.php20055V
ms-network.php3782V
ms-settings.php4197V
ms-site.php41729V
nav-menu-template.php25983V
nav-menu.php44269V
option.php105246V
php-ai-client-
php-compat-
pluggable-deprecated.php6324V
pluggable.php127919V
plugin.php37123V
pomo-
post-formats.php7070V
post-template.php69129V
post-thumbnail-template.php10879V
post.php305215V
query.php37554V
registration-functions.php200V
registration.php200V
rest-api-
rest-api.php102951V
revision.php31241V
rewrite.php19567V
robots-template.php5185V
rss-functions.php277V
rss.php23203V
script-loader.php163550V
script-modules.php12311V
session.php258V
shortcodes-set.php0V
shortcodes.php24034V
sitemaps-
sitemaps.php3238V
sodium_compat-
speculative-loading.php11880V
spl-autoload-compat.php441V
style-engine-
style-engine.php8045V
taxonomy.php178307V
template-canvas.php544V
template-loader.php4267V
template.php38826V
theme-compat-
theme-i18n.json1892V
theme-previews.php2887V
theme-templates.php4060V
theme.json9480V
theme.php134913V
update.php38269V
user.php180301V
utf8.php6977V
vars.php6600V
version.php1103V
view-config.php19087V
view-transitions.php602V
widgets-
widgets.php70866V
wp-db.php445V
wp-diff.php792V
MyMelon - Digital Marketing and Creative Agency in Delhi, India
Skip to content Skip to footer

MyMelon Home Page

Bored Of Old School Strategies?

Conventional strategies do no justice to complex modern problems. Bringing in kickass blueprints to escalate your exclusive ideas to the growth trajectory.

MyMelon Home Page (1)

Falling In Love With Your Problems

Your problems are our play! You get to decide which ‘solutions’ feel like an astounding fuck yes!

Discover pitch-perfect marketing strategies to deliver complex ideas into simplified solutions. 

Diversity in our problem solving approach makes us who we are!

You Do You

For us every client and their offerings are unique. We offer tailored and hot-off-the-press strategies to produce a unique brand identity. Listening, evolving, and promoting your articles of faith is what makes our work kickass and compelling too!

#
Award
Type
Project
01
Best Project
Art Business
Business Style
2017
02
Best Design
Creative Work
Best Designers
2018
03
Best Concept
New Strategy
Branding Concept
2019
04
Best Picture
Visualization
Small Figures
2020

Our Inspirations

Vivekanand

Arise, awake, and stop not until the goal is achieved

Dr APJ Abdul Kalam

Creativity is seeing the same thing but thinking differently

Christopher Columbus

By prevailing over all obstacles one may unfailingly arrive at his chosen goal.

JRD Tata

Uncommon thinkers reuse what common thinkers refuse.

Lead The Way With Your New Digital Partners

Waiting to get viral? Don’t worry we’ve got your back!

Leading your way through business acumen and business strategies tailored to your needs.

Handholding you since your first lightbulb moment to making a mark in the industry through unique formulas.  Bringing unexpected things to the table is in our DNA.

Producing Tailored Solutions

One solution for multiple solutions is hard to swallow. Creating tailored solutions for your unique problems

Setting Benchmarks

Doesn’t carving a path for others give the best kick ever?

Making A Difference

You can’t wait for a case study. You will be too late!

Blogs

Contact Us

We work hard and then succeed on purpose.

We are constantly looking for a needle in a haystack and connecting to get the deal to happen!

If you've loved our idea and want to take the road less traveled, reach out to us on …….

Before you take the sure-shots of success, let's take some shots of vodka!

    Polscy gracze coraz częściej wybierają kasyno bez weryfikacji przy wypłacie bez ukrytych opłat, aby cieszyć się szybkim dostępem do gier i przejrzystymi warunkami wypłaty wygranych. Tego typu platformy stawiają na uproszczoną rejestrację, nowoczesne metody płatności oraz jasne zasady dotyczące transakcji. Przed rozpoczęciem gry warto zapoznać się z opiniami innych użytkowników, aby ocenić jakość obsługi i niezawodność serwisu.

    Jeśli chcesz znaleźć rzetelne opinie oraz porównać najlepsze platformy, casino Revolut Pay może pomóc Ci podjąć świadomą decyzję. Znajdziesz tam recenzje użytkowników, szczegóły bonusów oraz informacje o wpłatach i wypłatach w kasynach akceptujących Revolut.

    People searching for gerçek canlı casino usually mean live-dealer roulette, blackjack, baccarat, or game-show tables streamed from a studio with a real dealer, rather than an RNG-only game. To assess authenticity, verify the operator’s licence directly with the regulator, check the named game provider and studio, look for clear rules and table limits, inspect withdrawal terms, and confirm that the service is legal in your jurisdiction; a foreign licence does not automatically make an operator legal in Türkiye.

    [canlı casino lisans rehberi](https://guvenilircanlicasinos.com/)[gerçek krupiyeli oyunlar](https://www.livecasinos.com/tr/) [guvenilircanlicasinos](https://guvenilircanlicasinos.com/)

    Many Dutch players now look for beste online casino iDEAL to benefit from secure iDEAL deposits, low minimum stakes, and quick withdrawals. These casinos integrate trusted Dutch payment infrastructure with streamlined cashout systems, ideal for users who value speed, simplicity, and transparent transactions. By consulting authentic player reviews, gamblers can identify sites that consistently deliver rapid payouts and a seamless gaming experience.

    Gli online casinos with bancoposta sono principalmente operatori che accettano la carta Visa o Mastercard collegata al conto BancoPosta per depositi e, in alcuni casi, prelievi. Tra i nomi più citati in Italia figurano 888casino, SNAI, LeoVegas, Planetwin365, Gioco Digitale, Sisal e StarCasinò, con depositi minimi spesso tra 10€ e 20€ e limiti massimi che possono arrivare a diverse migliaia di euro. Per utilizzare la carta, di solito basta selezionare Visa o Mastercard alla cassa, inserire i dati della carta BancoPosta e completare la verifica 3D Secure; i prelievi possono tornare sulla stessa carta o sul conto tramite bonifico, con tempi tipici da 24 ore a 3–5 giorni lavorativi.

    Gracze poszukujący sprawdzonych platform często wybierają kasyno niemcy, które oferuje przejrzyste zasady wypłat i bezpieczne metody płatności. Przed rejestracją warto porównać limity transakcji, czas realizacji przelewów oraz dostępne opcje wpłat, aby uniknąć niepotrzebnych opóźnień. Opinie innych użytkowników mogą pomóc ocenić rzetelność obsługi, jakość gier i ogólny komfort korzystania z platformy.

    Oferty określane jako zagraniczne kasyna bonus bez depozytu mogą obejmować darmowe spiny lub niewielkie środki promocyjne przyznawane po rejestracji i weryfikacji konta. Przed skorzystaniem z promocji należy dokładnie sprawdzić wymagania obrotu, maksymalną wypłatę, czas ważności bonusu oraz ograniczenia dla użytkowników z Polski. Zagraniczna licencja nie legalizuje automatycznie działalności hazardowej w Polsce, dlatego warto zweryfikować operatora w oficjalnych źródłach i grać odpowiedzialnie .