[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> meta.php (source)

   1  <?php
   2  /**
   3   * Core Metadata API
   4   *
   5   * Functions for retrieving and manipulating metadata of various WordPress object types. Metadata
   6   * for an object is a represented by a simple key-value pair. Objects may contain multiple
   7   * metadata entries that share the same key and differ only in their value.
   8   *
   9   * @package WordPress
  10   * @subpackage Meta
  11   */
  12  
  13  /**
  14   * Adds metadata for the specified object.
  15   *
  16   * @since 2.9.0
  17   *
  18   * @global wpdb $wpdb WordPress database abstraction object.
  19   *
  20   * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
  21   *                           or any other object type with an associated meta table.
  22   * @param int    $object_id  ID of the object metadata is for.
  23   * @param string $meta_key   Metadata key.
  24   * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
  25   * @param bool   $unique     Optional. Whether the specified metadata key should be unique for the object.
  26   *                           If true, and the object already has a value for the specified metadata key,
  27   *                           no change will be made. Default false.
  28   * @return int|false The meta ID on success, false on failure.
  29   */
  30  function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = false ) {
  31      global $wpdb;
  32  
  33      if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
  34          return false;
  35      }
  36  
  37      $object_id = absint( $object_id );
  38      if ( ! $object_id ) {
  39          return false;
  40      }
  41  
  42      $table = _get_meta_table( $meta_type );
  43      if ( ! $table ) {
  44          return false;
  45      }
  46  
  47      $meta_subtype = get_object_subtype( $meta_type, $object_id );
  48  
  49      $column = sanitize_key( $meta_type . '_id' );
  50  
  51      // expected_slashed ($meta_key)
  52      $meta_key   = wp_unslash( $meta_key );
  53      $meta_value = wp_unslash( $meta_value );
  54      $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
  55  
  56      /**
  57       * Filters whether to add metadata of a specific type.
  58       *
  59       * The dynamic portion of the hook, `$meta_type`, refers to the meta
  60       * object type (comment, post, term, or user). Returning a non-null value
  61       * will effectively short-circuit the function.
  62       *
  63       * @since 3.1.0
  64       *
  65       * @param null|bool $check      Whether to allow adding metadata for the given type.
  66       * @param int       $object_id  ID of the object metadata is for.
  67       * @param string    $meta_key   Metadata key.
  68       * @param mixed     $meta_value Metadata value. Must be serializable if non-scalar.
  69       * @param bool      $unique     Whether the specified meta key should be unique for the object.
  70       */
  71      $check = apply_filters( "add_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $unique );
  72      if ( null !== $check ) {
  73          return $check;
  74      }
  75  
  76      if ( $unique && $wpdb->get_var(
  77          $wpdb->prepare(
  78              "SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d",
  79              $meta_key,
  80              $object_id
  81          )
  82      ) ) {
  83          return false;
  84      }
  85  
  86      $_meta_value = $meta_value;
  87      $meta_value  = maybe_serialize( $meta_value );
  88  
  89      /**
  90       * Fires immediately before meta of a specific type is added.
  91       *
  92       * The dynamic portion of the hook, `$meta_type`, refers to the meta
  93       * object type (comment, post, term, or user).
  94       *
  95       * @since 3.1.0
  96       *
  97       * @param int    $object_id   ID of the object metadata is for.
  98       * @param string $meta_key    Metadata key.
  99       * @param mixed  $_meta_value Metadata value. Serialized if non-scalar.
 100       */
 101      do_action( "add_{$meta_type}_meta", $object_id, $meta_key, $_meta_value );
 102  
 103      $result = $wpdb->insert(
 104          $table,
 105          array(
 106              $column      => $object_id,
 107              'meta_key'   => $meta_key,
 108              'meta_value' => $meta_value,
 109          )
 110      );
 111  
 112      if ( ! $result ) {
 113          return false;
 114      }
 115  
 116      $mid = (int) $wpdb->insert_id;
 117  
 118      wp_cache_delete( $object_id, $meta_type . '_meta' );
 119  
 120      /**
 121       * Fires immediately after meta of a specific type is added.
 122       *
 123       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 124       * object type (comment, post, term, or user).
 125       *
 126       * @since 2.9.0
 127       *
 128       * @param int    $mid         The meta ID after successful update.
 129       * @param int    $object_id   ID of the object metadata is for.
 130       * @param string $meta_key    Metadata key.
 131       * @param mixed  $_meta_value Metadata value. Serialized if non-scalar.
 132       */
 133      do_action( "added_{$meta_type}_meta", $mid, $object_id, $meta_key, $_meta_value );
 134  
 135      return $mid;
 136  }
 137  
 138  /**
 139   * Updates metadata for the specified object. If no value already exists for the specified object
 140   * ID and metadata key, the metadata will be added.
 141   *
 142   * @since 2.9.0
 143   *
 144   * @global wpdb $wpdb WordPress database abstraction object.
 145   *
 146   * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 147   *                           or any other object type with an associated meta table.
 148   * @param int    $object_id  ID of the object metadata is for.
 149   * @param string $meta_key   Metadata key.
 150   * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
 151   * @param mixed  $prev_value Optional. If specified, only update existing metadata entries
 152   *                           with this value. Otherwise, update all entries.
 153   * @return int|bool The new meta field ID if a field with the given key didn't exist and was
 154   *                  therefore added, true on successful update, false on failure.
 155   */
 156  function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_value = '' ) {
 157      global $wpdb;
 158  
 159      if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
 160          return false;
 161      }
 162  
 163      $object_id = absint( $object_id );
 164      if ( ! $object_id ) {
 165          return false;
 166      }
 167  
 168      $table = _get_meta_table( $meta_type );
 169      if ( ! $table ) {
 170          return false;
 171      }
 172  
 173      $meta_subtype = get_object_subtype( $meta_type, $object_id );
 174  
 175      $column    = sanitize_key( $meta_type . '_id' );
 176      $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 177  
 178      // expected_slashed ($meta_key)
 179      $raw_meta_key = $meta_key;
 180      $meta_key     = wp_unslash( $meta_key );
 181      $passed_value = $meta_value;
 182      $meta_value   = wp_unslash( $meta_value );
 183      $meta_value   = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
 184  
 185      /**
 186       * Filters whether to update metadata of a specific type.
 187       *
 188       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 189       * object type (comment, post, term, or user). Returning a non-null value
 190       * will effectively short-circuit the function.
 191       *
 192       * @since 3.1.0
 193       *
 194       * @param null|bool $check      Whether to allow updating metadata for the given type.
 195       * @param int       $object_id  ID of the object metadata is for.
 196       * @param string    $meta_key   Metadata key.
 197       * @param mixed     $meta_value Metadata value. Must be serializable if non-scalar.
 198       * @param mixed     $prev_value Optional. If specified, only update existing metadata entries
 199       *                              with this value. Otherwise, update all entries.
 200       */
 201      $check = apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
 202      if ( null !== $check ) {
 203          return (bool) $check;
 204      }
 205  
 206      // Compare existing value to new value if no prev value given and the key exists only once.
 207      if ( empty( $prev_value ) ) {
 208          $old_value = get_metadata( $meta_type, $object_id, $meta_key );
 209          if ( count( $old_value ) == 1 ) {
 210              if ( $old_value[0] === $meta_value ) {
 211                  return false;
 212              }
 213          }
 214      }
 215  
 216      $meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id ) );
 217      if ( empty( $meta_ids ) ) {
 218          return add_metadata( $meta_type, $object_id, $raw_meta_key, $passed_value );
 219      }
 220  
 221      $_meta_value = $meta_value;
 222      $meta_value  = maybe_serialize( $meta_value );
 223  
 224      $data  = compact( 'meta_value' );
 225      $where = array(
 226          $column    => $object_id,
 227          'meta_key' => $meta_key,
 228      );
 229  
 230      if ( ! empty( $prev_value ) ) {
 231          $prev_value          = maybe_serialize( $prev_value );
 232          $where['meta_value'] = $prev_value;
 233      }
 234  
 235      foreach ( $meta_ids as $meta_id ) {
 236          /**
 237           * Fires immediately before updating metadata of a specific type.
 238           *
 239           * The dynamic portion of the hook, `$meta_type`, refers to the meta
 240           * object type (comment, post, term, or user).
 241           *
 242           * @since 2.9.0
 243           *
 244           * @param int    $meta_id     ID of the metadata entry to update.
 245           * @param int    $object_id   ID of the object metadata is for.
 246           * @param string $meta_key    Metadata key.
 247           * @param mixed  $_meta_value Metadata value. Serialized if non-scalar.
 248           */
 249          do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
 250  
 251          if ( 'post' == $meta_type ) {
 252              /**
 253               * Fires immediately before updating a post's metadata.
 254               *
 255               * @since 2.9.0
 256               *
 257               * @param int    $meta_id    ID of metadata entry to update.
 258               * @param int    $object_id  Post ID.
 259               * @param string $meta_key   Metadata key.
 260               * @param mixed  $meta_value Metadata value. This will be a PHP-serialized string representation of the value
 261               *                           if the value is an array, an object, or itself a PHP-serialized string.
 262               */
 263              do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
 264          }
 265      }
 266  
 267      $result = $wpdb->update( $table, $data, $where );
 268      if ( ! $result ) {
 269          return false;
 270      }
 271  
 272      wp_cache_delete( $object_id, $meta_type . '_meta' );
 273  
 274      foreach ( $meta_ids as $meta_id ) {
 275          /**
 276           * Fires immediately after updating metadata of a specific type.
 277           *
 278           * The dynamic portion of the hook, `$meta_type`, refers to the meta
 279           * object type (comment, post, term, or user).
 280           *
 281           * @since 2.9.0
 282           *
 283           * @param int    $meta_id     ID of updated metadata entry.
 284           * @param int    $object_id   ID of the object metadata is for.
 285           * @param string $meta_key    Metadata key.
 286           * @param mixed  $_meta_value Metadata value. Serialized if non-scalar.
 287           */
 288          do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
 289  
 290          if ( 'post' == $meta_type ) {
 291              /**
 292               * Fires immediately after updating a post's metadata.
 293               *
 294               * @since 2.9.0
 295               *
 296               * @param int    $meta_id    ID of updated metadata entry.
 297               * @param int    $object_id  Post ID.
 298               * @param string $meta_key   Metadata key.
 299               * @param mixed  $meta_value Metadata value. This will be a PHP-serialized string representation of the value
 300               *                           if the value is an array, an object, or itself a PHP-serialized string.
 301               */
 302              do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
 303          }
 304      }
 305  
 306      return true;
 307  }
 308  
 309  /**
 310   * Deletes metadata for the specified object.
 311   *
 312   * @since 2.9.0
 313   *
 314   * @global wpdb $wpdb WordPress database abstraction object.
 315   *
 316   * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 317   *                           or any other object type with an associated meta table.
 318   * @param int    $object_id  ID of the object metadata is for.
 319   * @param string $meta_key   Metadata key.
 320   * @param mixed  $meta_value Optional. Metadata value. Must be serializable if non-scalar.
 321   *                           If specified, only delete metadata entries with this value.
 322   *                           Otherwise, delete all entries with the specified meta_key.
 323   *                           Pass `null`, `false`, or an empty string to skip this check.
 324   *                           (For backward compatibility, it is not possible to pass an empty string
 325   *                           to delete those entries with an empty string for a value.)
 326   * @param bool   $delete_all Optional. If true, delete matching metadata entries for all objects,
 327   *                           ignoring the specified object_id. Otherwise, only delete
 328   *                           matching metadata entries for the specified object_id. Default false.
 329   * @return bool True on successful delete, false on failure.
 330   */
 331  function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = false ) {
 332      global $wpdb;
 333  
 334      if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) && ! $delete_all ) {
 335          return false;
 336      }
 337  
 338      $object_id = absint( $object_id );
 339      if ( ! $object_id && ! $delete_all ) {
 340          return false;
 341      }
 342  
 343      $table = _get_meta_table( $meta_type );
 344      if ( ! $table ) {
 345          return false;
 346      }
 347  
 348      $type_column = sanitize_key( $meta_type . '_id' );
 349      $id_column   = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 350      // expected_slashed ($meta_key)
 351      $meta_key   = wp_unslash( $meta_key );
 352      $meta_value = wp_unslash( $meta_value );
 353  
 354      /**
 355       * Filters whether to delete metadata of a specific type.
 356       *
 357       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 358       * object type (comment, post, term, or user). Returning a non-null value
 359       * will effectively short-circuit the function.
 360       *
 361       * @since 3.1.0
 362       *
 363       * @param null|bool $delete     Whether to allow metadata deletion of the given type.
 364       * @param int       $object_id  ID of the object metadata is for.
 365       * @param string    $meta_key   Metadata key.
 366       * @param mixed     $meta_value Metadata value. Must be serializable if non-scalar.
 367       * @param bool      $delete_all Whether to delete the matching metadata entries
 368       *                              for all objects, ignoring the specified $object_id.
 369       *                              Default false.
 370       */
 371      $check = apply_filters( "delete_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $delete_all );
 372      if ( null !== $check ) {
 373          return (bool) $check;
 374      }
 375  
 376      $_meta_value = $meta_value;
 377      $meta_value  = maybe_serialize( $meta_value );
 378  
 379      $query = $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s", $meta_key );
 380  
 381      if ( ! $delete_all ) {
 382          $query .= $wpdb->prepare( " AND $type_column = %d", $object_id );
 383      }
 384  
 385      if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value ) {
 386          $query .= $wpdb->prepare( ' AND meta_value = %s', $meta_value );
 387      }
 388  
 389      $meta_ids = $wpdb->get_col( $query );
 390      if ( ! count( $meta_ids ) ) {
 391          return false;
 392      }
 393  
 394      if ( $delete_all ) {
 395          if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value ) {
 396              $object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $type_column FROM $table WHERE meta_key = %s AND meta_value = %s", $meta_key, $meta_value ) );
 397          } else {
 398              $object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $type_column FROM $table WHERE meta_key = %s", $meta_key ) );
 399          }
 400      }
 401  
 402      /**
 403       * Fires immediately before deleting metadata of a specific type.
 404       *
 405       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 406       * object type (comment, post, term, or user).
 407       *
 408       * @since 3.1.0
 409       *
 410       * @param string[] $meta_ids    An array of metadata entry IDs to delete.
 411       * @param int      $object_id   ID of the object metadata is for.
 412       * @param string   $meta_key    Metadata key.
 413       * @param mixed    $_meta_value Metadata value. Serialized if non-scalar.
 414       */
 415      do_action( "delete_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value );
 416  
 417      // Old-style action.
 418      if ( 'post' == $meta_type ) {
 419          /**
 420           * Fires immediately before deleting metadata for a post.
 421           *
 422           * @since 2.9.0
 423           *
 424           * @param string[] $meta_ids An array of metadata entry IDs to delete.
 425           */
 426          do_action( 'delete_postmeta', $meta_ids );
 427      }
 428  
 429      $query = "DELETE FROM $table WHERE $id_column IN( " . implode( ',', $meta_ids ) . ' )';
 430  
 431      $count = $wpdb->query( $query );
 432  
 433      if ( ! $count ) {
 434          return false;
 435      }
 436  
 437      if ( $delete_all ) {
 438          foreach ( (array) $object_ids as $o_id ) {
 439              wp_cache_delete( $o_id, $meta_type . '_meta' );
 440          }
 441      } else {
 442          wp_cache_delete( $object_id, $meta_type . '_meta' );
 443      }
 444  
 445      /**
 446       * Fires immediately after deleting metadata of a specific type.
 447       *
 448       * The dynamic portion of the hook name, `$meta_type`, refers to the meta
 449       * object type (comment, post, term, or user).
 450       *
 451       * @since 2.9.0
 452       *
 453       * @param string[] $meta_ids    An array of metadata entry IDs to delete.
 454       * @param int      $object_id   ID of the object metadata is for.
 455       * @param string   $meta_key    Metadata key.
 456       * @param mixed    $_meta_value Metadata value. Serialized if non-scalar.
 457       */
 458      do_action( "deleted_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value );
 459  
 460      // Old-style action.
 461      if ( 'post' == $meta_type ) {
 462          /**
 463           * Fires immediately after deleting metadata for a post.
 464           *
 465           * @since 2.9.0
 466           *
 467           * @param string[] $meta_ids An array of metadata entry IDs to delete.
 468           */
 469          do_action( 'deleted_postmeta', $meta_ids );
 470      }
 471  
 472      return true;
 473  }
 474  
 475  /**
 476   * Retrieves metadata for the specified object.
 477   *
 478   * @since 2.9.0
 479   *
 480   * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 481   *                          or any other object type with an associated meta table.
 482   * @param int    $object_id ID of the object metadata is for.
 483   * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
 484   *                          the specified object. Default empty.
 485   * @param bool   $single    Optional. If true, return only the first value of the specified meta_key.
 486   *                          This parameter has no effect if meta_key is not specified. Default false.
 487   * @return mixed Single metadata value, or array of values
 488   */
 489  function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false ) {
 490      if ( ! $meta_type || ! is_numeric( $object_id ) ) {
 491          return false;
 492      }
 493  
 494      $object_id = absint( $object_id );
 495      if ( ! $object_id ) {
 496          return false;
 497      }
 498  
 499      /**
 500       * Filters whether to retrieve metadata of a specific type.
 501       *
 502       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 503       * object type (comment, post, term, or user). Returning a non-null value
 504       * will effectively short-circuit the function.
 505       *
 506       * @since 3.1.0
 507       *
 508       * @param null|array|string $value     The value get_metadata() should return - a single metadata value,
 509       *                                     or an array of values.
 510       * @param int               $object_id ID of the object metadata is for.
 511       * @param string            $meta_key  Metadata key.
 512       * @param bool              $single    Whether to return only the first value of the specified $meta_key.
 513       */
 514      $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single );
 515      if ( null !== $check ) {
 516          if ( $single && is_array( $check ) ) {
 517              return $check[0];
 518          } else {
 519              return $check;
 520          }
 521      }
 522  
 523      $meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
 524  
 525      if ( ! $meta_cache ) {
 526          $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
 527          if ( isset( $meta_cache[ $object_id ] ) ) {
 528              $meta_cache = $meta_cache[ $object_id ];
 529          } else {
 530              $meta_cache = null;
 531          }
 532      }
 533  
 534      if ( ! $meta_key ) {
 535          return $meta_cache;
 536      }
 537  
 538      if ( isset( $meta_cache[ $meta_key ] ) ) {
 539          if ( $single ) {
 540              return maybe_unserialize( $meta_cache[ $meta_key ][0] );
 541          } else {
 542              return array_map( 'maybe_unserialize', $meta_cache[ $meta_key ] );
 543          }
 544      }
 545  
 546      if ( $single ) {
 547          return '';
 548      } else {
 549          return array();
 550      }
 551  }
 552  
 553  /**
 554   * Determines if a meta key is set for a given object.
 555   *
 556   * @since 3.3.0
 557   *
 558   * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 559   *                          or any other object type with an associated meta table.
 560   * @param int    $object_id ID of the object metadata is for.
 561   * @param string $meta_key  Metadata key.
 562   * @return bool True of the key is set, false if not.
 563   */
 564  function metadata_exists( $meta_type, $object_id, $meta_key ) {
 565      if ( ! $meta_type || ! is_numeric( $object_id ) ) {
 566          return false;
 567      }
 568  
 569      $object_id = absint( $object_id );
 570      if ( ! $object_id ) {
 571          return false;
 572      }
 573  
 574      /** This filter is documented in wp-includes/meta.php */
 575      $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, true );
 576      if ( null !== $check ) {
 577          return (bool) $check;
 578      }
 579  
 580      $meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
 581  
 582      if ( ! $meta_cache ) {
 583          $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
 584          $meta_cache = $meta_cache[ $object_id ];
 585      }
 586  
 587      if ( isset( $meta_cache[ $meta_key ] ) ) {
 588          return true;
 589      }
 590  
 591      return false;
 592  }
 593  
 594  /**
 595   * Retrieves metadata by meta ID.
 596   *
 597   * @since 3.3.0
 598   *
 599   * @global wpdb $wpdb WordPress database abstraction object.
 600   *
 601   * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 602   *                          or any other object type with an associated meta table.
 603   * @param int    $meta_id   ID for a specific meta row.
 604   * @return object|false Meta object or false.
 605   */
 606  function get_metadata_by_mid( $meta_type, $meta_id ) {
 607      global $wpdb;
 608  
 609      if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
 610          return false;
 611      }
 612  
 613      $meta_id = intval( $meta_id );
 614      if ( $meta_id <= 0 ) {
 615          return false;
 616      }
 617  
 618      $table = _get_meta_table( $meta_type );
 619      if ( ! $table ) {
 620          return false;
 621      }
 622  
 623      $id_column = ( 'user' == $meta_type ) ? 'umeta_id' : 'meta_id';
 624  
 625      /**
 626       * Filters whether to retrieve metadata of a specific type by meta ID.
 627       *
 628       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 629       * object type (comment, post, term, or user). Returning a non-null value
 630       * will effectively short-circuit the function.
 631       *
 632       * @since 5.0.0
 633       *
 634       * @param mixed $value    The value get_metadata_by_mid() should return.
 635       * @param int   $meta_id  Meta ID.
 636       */
 637      $check = apply_filters( "get_{$meta_type}_metadata_by_mid", null, $meta_id );
 638      if ( null !== $check ) {
 639          return $check;
 640      }
 641  
 642      $meta = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE $id_column = %d", $meta_id ) );
 643  
 644      if ( empty( $meta ) ) {
 645          return false;
 646      }
 647  
 648      if ( isset( $meta->meta_value ) ) {
 649          $meta->meta_value = maybe_unserialize( $meta->meta_value );
 650      }
 651  
 652      return $meta;
 653  }
 654  
 655  /**
 656   * Updates metadata by meta ID.
 657   *
 658   * @since 3.3.0
 659   *
 660   * @global wpdb $wpdb WordPress database abstraction object.
 661   *
 662   * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 663   *                           or any other object type with an associated meta table.
 664   * @param int    $meta_id    ID for a specific meta row.
 665   * @param string $meta_value Metadata value.
 666   * @param string $meta_key   Optional. You can provide a meta key to update it. Default false.
 667   * @return bool True on successful update, false on failure.
 668   */
 669  function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key = false ) {
 670      global $wpdb;
 671  
 672      // Make sure everything is valid.
 673      if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
 674          return false;
 675      }
 676  
 677      $meta_id = intval( $meta_id );
 678      if ( $meta_id <= 0 ) {
 679          return false;
 680      }
 681  
 682      $table = _get_meta_table( $meta_type );
 683      if ( ! $table ) {
 684          return false;
 685      }
 686  
 687      $column    = sanitize_key( $meta_type . '_id' );
 688      $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 689  
 690      /**
 691       * Filters whether to update metadata of a specific type by meta ID.
 692       *
 693       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 694       * object type (comment, post, term, or user). Returning a non-null value
 695       * will effectively short-circuit the function.
 696       *
 697       * @since 5.0.0
 698       *
 699       * @param null|bool   $check      Whether to allow updating metadata for the given type.
 700       * @param int         $meta_id    Meta ID.
 701       * @param mixed       $meta_value Meta value. Must be serializable if non-scalar.
 702       * @param string|bool $meta_key   Meta key, if provided.
 703       */
 704      $check = apply_filters( "update_{$meta_type}_metadata_by_mid", null, $meta_id, $meta_value, $meta_key );
 705      if ( null !== $check ) {
 706          return (bool) $check;
 707      }
 708  
 709      // Fetch the meta and go on if it's found.
 710      $meta = get_metadata_by_mid( $meta_type, $meta_id );
 711      if ( $meta ) {
 712          $original_key = $meta->meta_key;
 713          $object_id    = $meta->{$column};
 714  
 715          // If a new meta_key (last parameter) was specified, change the meta key,
 716          // otherwise use the original key in the update statement.
 717          if ( false === $meta_key ) {
 718              $meta_key = $original_key;
 719          } elseif ( ! is_string( $meta_key ) ) {
 720              return false;
 721          }
 722  
 723          $meta_subtype = get_object_subtype( $meta_type, $object_id );
 724  
 725          // Sanitize the meta.
 726          $_meta_value = $meta_value;
 727          $meta_value  = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
 728          $meta_value  = maybe_serialize( $meta_value );
 729  
 730          // Format the data query arguments.
 731          $data = array(
 732              'meta_key'   => $meta_key,
 733              'meta_value' => $meta_value,
 734          );
 735  
 736          // Format the where query arguments.
 737          $where               = array();
 738          $where[ $id_column ] = $meta_id;
 739  
 740          /** This action is documented in wp-includes/meta.php */
 741          do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
 742  
 743          if ( 'post' == $meta_type ) {
 744              /** This action is documented in wp-includes/meta.php */
 745              do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
 746          }
 747  
 748          // Run the update query, all fields in $data are %s, $where is a %d.
 749          $result = $wpdb->update( $table, $data, $where, '%s', '%d' );
 750          if ( ! $result ) {
 751              return false;
 752          }
 753  
 754          // Clear the caches.
 755          wp_cache_delete( $object_id, $meta_type . '_meta' );
 756  
 757          /** This action is documented in wp-includes/meta.php */
 758          do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
 759  
 760          if ( 'post' == $meta_type ) {
 761              /** This action is documented in wp-includes/meta.php */
 762              do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
 763          }
 764  
 765          return true;
 766      }
 767  
 768      // And if the meta was not found.
 769      return false;
 770  }
 771  
 772  /**
 773   * Deletes metadata by meta ID.
 774   *
 775   * @since 3.3.0
 776   *
 777   * @global wpdb $wpdb WordPress database abstraction object.
 778   *
 779   * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 780   *                          or any other object type with an associated meta table.
 781   * @param int    $meta_id   ID for a specific meta row.
 782   * @return bool True on successful delete, false on failure.
 783   */
 784  function delete_metadata_by_mid( $meta_type, $meta_id ) {
 785      global $wpdb;
 786  
 787      // Make sure everything is valid.
 788      if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
 789          return false;
 790      }
 791  
 792      $meta_id = intval( $meta_id );
 793      if ( $meta_id <= 0 ) {
 794          return false;
 795      }
 796  
 797      $table = _get_meta_table( $meta_type );
 798      if ( ! $table ) {
 799          return false;
 800      }
 801  
 802      // Object and ID columns.
 803      $column    = sanitize_key( $meta_type . '_id' );
 804      $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 805  
 806      /**
 807       * Filters whether to delete metadata of a specific type by meta ID.
 808       *
 809       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 810       * object type (comment, post, term, or user). Returning a non-null value
 811       * will effectively short-circuit the function.
 812       *
 813       * @since 5.0.0
 814       *
 815       * @param null|bool $delete  Whether to allow metadata deletion of the given type.
 816       * @param int       $meta_id Meta ID.
 817       */
 818      $check = apply_filters( "delete_{$meta_type}_metadata_by_mid", null, $meta_id );
 819      if ( null !== $check ) {
 820          return (bool) $check;
 821      }
 822  
 823      // Fetch the meta and go on if it's found.
 824      $meta = get_metadata_by_mid( $meta_type, $meta_id );
 825      if ( $meta ) {
 826          $object_id = (int) $meta->{$column};
 827  
 828          /** This action is documented in wp-includes/meta.php */
 829          do_action( "delete_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value );
 830  
 831          // Old-style action.
 832          if ( 'post' == $meta_type || 'comment' == $meta_type ) {
 833              /**
 834               * Fires immediately before deleting post or comment metadata of a specific type.
 835               *
 836               * The dynamic portion of the hook, `$meta_type`, refers to the meta
 837               * object type (post or comment).
 838               *
 839               * @since 3.4.0
 840               *
 841               * @param int $meta_id ID of the metadata entry to delete.
 842               */
 843              do_action( "delete_{$meta_type}meta", $meta_id );
 844          }
 845  
 846          // Run the query, will return true if deleted, false otherwise.
 847          $result = (bool) $wpdb->delete( $table, array( $id_column => $meta_id ) );
 848  
 849          // Clear the caches.
 850          wp_cache_delete( $object_id, $meta_type . '_meta' );
 851  
 852          /** This action is documented in wp-includes/meta.php */
 853          do_action( "deleted_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value );
 854  
 855          // Old-style action.
 856          if ( 'post' == $meta_type || 'comment' == $meta_type ) {
 857              /**
 858               * Fires immediately after deleting post or comment metadata of a specific type.
 859               *
 860               * The dynamic portion of the hook, `$meta_type`, refers to the meta
 861               * object type (post or comment).
 862               *
 863               * @since 3.4.0
 864               *
 865               * @param int $meta_ids Deleted metadata entry ID.
 866               */
 867              do_action( "deleted_{$meta_type}meta", $meta_id );
 868          }
 869  
 870          return $result;
 871  
 872      }
 873  
 874      // Meta ID was not found.
 875      return false;
 876  }
 877  
 878  /**
 879   * Updates the metadata cache for the specified objects.
 880   *
 881   * @since 2.9.0
 882   *
 883   * @global wpdb $wpdb WordPress database abstraction object.
 884   *
 885   * @param string       $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
 886   *                                 or any other object type with an associated meta table.
 887   * @param string|int[] $object_ids Array or comma delimited list of object IDs to update cache for.
 888   * @return array|false Metadata cache for the specified objects, or false on failure.
 889   */
 890  function update_meta_cache( $meta_type, $object_ids ) {
 891      global $wpdb;
 892  
 893      if ( ! $meta_type || ! $object_ids ) {
 894          return false;
 895      }
 896  
 897      $table = _get_meta_table( $meta_type );
 898      if ( ! $table ) {
 899          return false;
 900      }
 901  
 902      $column = sanitize_key( $meta_type . '_id' );
 903  
 904      if ( ! is_array( $object_ids ) ) {
 905          $object_ids = preg_replace( '|[^0-9,]|', '', $object_ids );
 906          $object_ids = explode( ',', $object_ids );
 907      }
 908  
 909      $object_ids = array_map( 'intval', $object_ids );
 910  
 911      /**
 912       * Filters whether to update the metadata cache of a specific type.
 913       *
 914       * The dynamic portion of the hook, `$meta_type`, refers to the meta
 915       * object type (comment, post, term, or user). Returning a non-null value
 916       * will effectively short-circuit the function.
 917       *
 918       * @since 5.0.0
 919       *
 920       * @param mixed $check      Whether to allow updating the meta cache of the given type.
 921       * @param int[] $object_ids Array of object IDs to update the meta cache for.
 922       */
 923      $check = apply_filters( "update_{$meta_type}_metadata_cache", null, $object_ids );
 924      if ( null !== $check ) {
 925          return (bool) $check;
 926      }
 927  
 928      $cache_key = $meta_type . '_meta';
 929      $ids       = array();
 930      $cache     = array();
 931      foreach ( $object_ids as $id ) {
 932          $cached_object = wp_cache_get( $id, $cache_key );
 933          if ( false === $cached_object ) {
 934              $ids[] = $id;
 935          } else {
 936              $cache[ $id ] = $cached_object;
 937          }
 938      }
 939  
 940      if ( empty( $ids ) ) {
 941          return $cache;
 942      }
 943  
 944      // Get meta info.
 945      $id_list   = join( ',', $ids );
 946      $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 947      $meta_list = $wpdb->get_results( "SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC", ARRAY_A );
 948  
 949      if ( ! empty( $meta_list ) ) {
 950          foreach ( $meta_list as $metarow ) {
 951              $mpid = intval( $metarow[ $column ] );
 952              $mkey = $metarow['meta_key'];
 953              $mval = $metarow['meta_value'];
 954  
 955              // Force subkeys to be array type.
 956              if ( ! isset( $cache[ $mpid ] ) || ! is_array( $cache[ $mpid ] ) ) {
 957                  $cache[ $mpid ] = array();
 958              }
 959              if ( ! isset( $cache[ $mpid ][ $mkey ] ) || ! is_array( $cache[ $mpid ][ $mkey ] ) ) {
 960                  $cache[ $mpid ][ $mkey ] = array();
 961              }
 962  
 963              // Add a value to the current pid/key.
 964              $cache[ $mpid ][ $mkey ][] = $mval;
 965          }
 966      }
 967  
 968      foreach ( $ids as $id ) {
 969          if ( ! isset( $cache[ $id ] ) ) {
 970              $cache[ $id ] = array();
 971          }
 972          wp_cache_add( $id, $cache[ $id ], $cache_key );
 973      }
 974  
 975      return $cache;
 976  }
 977  
 978  /**
 979   * Retrieves the queue for lazy-loading metadata.
 980   *
 981   * @since 4.5.0
 982   *
 983   * @return WP_Metadata_Lazyloader $lazyloader Metadata lazyloader queue.
 984   */
 985  function wp_metadata_lazyloader() {
 986      static $wp_metadata_lazyloader;
 987  
 988      if ( null === $wp_metadata_lazyloader ) {
 989          $wp_metadata_lazyloader = new WP_Metadata_Lazyloader();
 990      }
 991  
 992      return $wp_metadata_lazyloader;
 993  }
 994  
 995  /**
 996   * Given a meta query, generates SQL clauses to be appended to a main query.
 997   *
 998   * @since 3.2.0
 999   *
1000   * @see WP_Meta_Query
1001   *
1002   * @param array $meta_query         A meta query.
1003   * @param string $type              Type of meta.
1004   * @param string $primary_table     Primary database table name.
1005   * @param string $primary_id_column Primary ID column name.
1006   * @param object $context           Optional. The main query object
1007   * @return array Associative array of `JOIN` and `WHERE` SQL.
1008   */
1009  function get_meta_sql( $meta_query, $type, $primary_table, $primary_id_column, $context = null ) {
1010      $meta_query_obj = new WP_Meta_Query( $meta_query );
1011      return $meta_query_obj->get_sql( $type, $primary_table, $primary_id_column, $context );
1012  }
1013  
1014  /**
1015   * Retrieves the name of the metadata table for the specified object type.
1016   *
1017   * @since 2.9.0
1018   *
1019   * @global wpdb $wpdb WordPress database abstraction object.
1020   *
1021   * @param string $type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1022   *                     or any other object type with an associated meta table.
1023   * @return string|false Metadata table name, or false if no metadata table exists
1024   */
1025  function _get_meta_table( $type ) {
1026      global $wpdb;
1027  
1028      $table_name = $type . 'meta';
1029  
1030      if ( empty( $wpdb->$table_name ) ) {
1031          return false;
1032      }
1033  
1034      return $wpdb->$table_name;
1035  }
1036  
1037  /**
1038   * Determines whether a meta key is considered protected.
1039   *
1040   * @since 3.1.3
1041   *
1042   * @param string $meta_key  Metadata key.
1043   * @param string $meta_type Optional. Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1044   *                          or any other object type with an associated meta table. Default empty.
1045   * @return bool Whether the meta key is considered protected.
1046   */
1047  function is_protected_meta( $meta_key, $meta_type = '' ) {
1048      $protected = ( '_' == $meta_key[0] );
1049  
1050      /**
1051       * Filters whether a meta key is considered protected.
1052       *
1053       * @since 3.2.0
1054       *
1055       * @param bool   $protected Whether the key is considered protected.
1056       * @param string $meta_key  Metadata key.
1057       * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1058       *                          or any other object type with an associated meta table.
1059       */
1060      return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type );
1061  }
1062  
1063  /**
1064   * Sanitizes meta value.
1065   *
1066   * @since 3.1.3
1067   * @since 4.9.8 The `$object_subtype` parameter was added.
1068   *
1069   * @param string $meta_key       Metadata key.
1070   * @param mixed  $meta_value     Metadata value to sanitize.
1071   * @param string $object_type    Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1072   *                               or any other object type with an associated meta table.
1073   * @param string $object_subtype Optional. The subtype of the object type.
1074   * @return mixed Sanitized $meta_value.
1075   */
1076  function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype = '' ) {
1077      if ( ! empty( $object_subtype ) && has_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
1078  
1079          /**
1080           * Filters the sanitization of a specific meta key of a specific meta type and subtype.
1081           *
1082           * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
1083           * and `$object_subtype`, refer to the metadata object type (comment, post, term, or user),
1084           * the meta key value, and the object subtype respectively.
1085           *
1086           * @since 4.9.8
1087           *
1088           * @param mixed  $meta_value     Metadata value to sanitize.
1089           * @param string $meta_key       Metadata key.
1090           * @param string $object_type    Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1091           *                               or any other object type with an associated meta table.
1092           * @param string $object_subtype Object subtype.
1093           */
1094          return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $meta_value, $meta_key, $object_type, $object_subtype );
1095      }
1096  
1097      /**
1098       * Filters the sanitization of a specific meta key of a specific meta type.
1099       *
1100       * The dynamic portions of the hook name, `$meta_type`, and `$meta_key`,
1101       * refer to the metadata object type (comment, post, term, or user) and the meta
1102       * key value, respectively.
1103       *
1104       * @since 3.3.0
1105       *
1106       * @param mixed  $meta_value  Metadata value to sanitize.
1107       * @param string $meta_key    Metadata key.
1108       * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1109       *                            or any other object type with an associated meta table.
1110       */
1111      return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}", $meta_value, $meta_key, $object_type );
1112  }
1113  
1114  /**
1115   * Registers a meta key.
1116   *
1117   * It is recommended to register meta keys for a specific combination of object type and object subtype. If passing
1118   * an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly
1119   * overridden in case a more specific meta key of the same name exists for the same object type and a subtype.
1120   *
1121   * If an object type does not support any subtypes, such as users or comments, you should commonly call this function
1122   * without passing a subtype.
1123   *
1124   * @since 3.3.0
1125   * @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified
1126   *              to support an array of data to attach to registered meta keys}. Previous arguments for
1127   *              `$sanitize_callback` and `$auth_callback` have been folded into this array.
1128   * @since 4.9.8 The `$object_subtype` argument was added to the arguments array.
1129   * @since 5.3.0 Valid meta types expanded to include "array" and "object".
1130   *
1131   * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1132   *                            or any other object type with an associated meta table.
1133   * @param string $meta_key    Meta key to register.
1134   * @param array  $args {
1135   *     Data used to describe the meta key when registered.
1136   *
1137   *     @type string     $object_subtype    A subtype; e.g. if the object type is "post", the post type. If left empty,
1138   *                                         the meta key will be registered on the entire object type. Default empty.
1139   *     @type string     $type              The type of data associated with this meta key.
1140   *                                         Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'.
1141   *     @type string     $description       A description of the data attached to this meta key.
1142   *     @type bool       $single            Whether the meta key has one value per object, or an array of values per object.
1143   *     @type string     $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
1144   *     @type string     $auth_callback     Optional. A function or method to call when performing edit_post_meta,
1145   *                                         add_post_meta, and delete_post_meta capability checks.
1146   *     @type bool|array $show_in_rest      Whether data associated with this meta key can be considered public and
1147   *                                         should be accessible via the REST API. A custom post type must also declare
1148   *                                         support for custom fields for registered meta to be accessible via REST.
1149   *                                         When registering complex meta values this argument may optionally be an
1150   *                                         array with 'schema' or 'prepare_callback' keys instead of a boolean.
1151   * }
1152   * @param string|array $deprecated Deprecated. Use `$args` instead.
1153   * @return bool True if the meta key was successfully registered in the global array, false if not.
1154   *              Registering a meta key with distinct sanitize and auth callbacks will fire those callbacks,
1155   *              but will not add to the global registry.
1156   */
1157  function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
1158      global $wp_meta_keys;
1159  
1160      if ( ! is_array( $wp_meta_keys ) ) {
1161          $wp_meta_keys = array();
1162      }
1163  
1164      $defaults = array(
1165          'object_subtype'    => '',
1166          'type'              => 'string',
1167          'description'       => '',
1168          'single'            => false,
1169          'sanitize_callback' => null,
1170          'auth_callback'     => null,
1171          'show_in_rest'      => false,
1172      );
1173  
1174      // There used to be individual args for sanitize and auth callbacks.
1175      $has_old_sanitize_cb = false;
1176      $has_old_auth_cb     = false;
1177  
1178      if ( is_callable( $args ) ) {
1179          $args = array(
1180              'sanitize_callback' => $args,
1181          );
1182  
1183          $has_old_sanitize_cb = true;
1184      } else {
1185          $args = (array) $args;
1186      }
1187  
1188      if ( is_callable( $deprecated ) ) {
1189          $args['auth_callback'] = $deprecated;
1190          $has_old_auth_cb       = true;
1191      }
1192  
1193      /**
1194       * Filters the registration arguments when registering meta.
1195       *
1196       * @since 4.6.0
1197       *
1198       * @param array  $args        Array of meta registration arguments.
1199       * @param array  $defaults    Array of default arguments.
1200       * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1201       *                            or any other object type with an associated meta table.
1202       * @param string $meta_key    Meta key.
1203       */
1204      $args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
1205      $args = wp_parse_args( $args, $defaults );
1206  
1207      // Require an item schema when registering array meta.
1208      if ( false !== $args['show_in_rest'] && 'array' === $args['type'] ) {
1209          if ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) {
1210              _doing_it_wrong( __FUNCTION__, __( 'When registering an "array" meta type to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".' ), '5.3.0' );
1211  
1212              return false;
1213          }
1214      }
1215  
1216      $object_subtype = ! empty( $args['object_subtype'] ) ? $args['object_subtype'] : '';
1217  
1218      // If `auth_callback` is not provided, fall back to `is_protected_meta()`.
1219      if ( empty( $args['auth_callback'] ) ) {
1220          if ( is_protected_meta( $meta_key, $object_type ) ) {
1221              $args['auth_callback'] = '__return_false';
1222          } else {
1223              $args['auth_callback'] = '__return_true';
1224          }
1225      }
1226  
1227      // Back-compat: old sanitize and auth callbacks are applied to all of an object type.
1228      if ( is_callable( $args['sanitize_callback'] ) ) {
1229          if ( ! empty( $object_subtype ) ) {
1230              add_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'], 10, 4 );
1231          } else {
1232              add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
1233          }
1234      }
1235  
1236      if ( is_callable( $args['auth_callback'] ) ) {
1237          if ( ! empty( $object_subtype ) ) {
1238              add_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'], 10, 6 );
1239          } else {
1240              add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
1241          }
1242      }
1243  
1244      // Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
1245      if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
1246          unset( $args['object_subtype'] );
1247  
1248          $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] = $args;
1249  
1250          return true;
1251      }
1252  
1253      return false;
1254  }
1255  
1256  /**
1257   * Checks if a meta key is registered.
1258   *
1259   * @since 4.6.0
1260   * @since 4.9.8 The `$object_subtype` parameter was added.
1261   *
1262   * @param string $object_type    Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1263   *                               or any other object type with an associated meta table.
1264   * @param string $meta_key       Metadata key.
1265   * @param string $object_subtype Optional. The subtype of the object type.
1266   * @return bool True if the meta key is registered to the object type and, if provided,
1267   *              the object subtype. False if not.
1268   */
1269  function registered_meta_key_exists( $object_type, $meta_key, $object_subtype = '' ) {
1270      $meta_keys = get_registered_meta_keys( $object_type, $object_subtype );
1271  
1272      return isset( $meta_keys[ $meta_key ] );
1273  }
1274  
1275  /**
1276   * Unregisters a meta key from the list of registered keys.
1277   *
1278   * @since 4.6.0
1279   * @since 4.9.8 The `$object_subtype` parameter was added.
1280   *
1281   * @param string $object_type    Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1282   *                               or any other object type with an associated meta table.
1283   * @param string $meta_key       Metadata key.
1284   * @param string $object_subtype Optional. The subtype of the object type.
1285   * @return bool True if successful. False if the meta key was not registered.
1286   */
1287  function unregister_meta_key( $object_type, $meta_key, $object_subtype = '' ) {
1288      global $wp_meta_keys;
1289  
1290      if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
1291          return false;
1292      }
1293  
1294      $args = $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ];
1295  
1296      if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) {
1297          if ( ! empty( $object_subtype ) ) {
1298              remove_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'] );
1299          } else {
1300              remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
1301          }
1302      }
1303  
1304      if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) {
1305          if ( ! empty( $object_subtype ) ) {
1306              remove_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'] );
1307          } else {
1308              remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
1309          }
1310      }
1311  
1312      unset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] );
1313  
1314      // Do some clean up.
1315      if ( empty( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
1316          unset( $wp_meta_keys[ $object_type ][ $object_subtype ] );
1317      }
1318      if ( empty( $wp_meta_keys[ $object_type ] ) ) {
1319          unset( $wp_meta_keys[ $object_type ] );
1320      }
1321  
1322      return true;
1323  }
1324  
1325  /**
1326   * Retrieves a list of registered meta keys for an object type.
1327   *
1328   * @since 4.6.0
1329   * @since 4.9.8 The `$object_subtype` parameter was added.
1330   *
1331   * @param string $object_type    Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1332   *                               or any other object type with an associated meta table.
1333   * @param string $object_subtype Optional. The subtype of the object type.
1334   * @return string[] List of registered meta keys.
1335   */
1336  function get_registered_meta_keys( $object_type, $object_subtype = '' ) {
1337      global $wp_meta_keys;
1338  
1339      if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) || ! isset( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
1340          return array();
1341      }
1342  
1343      return $wp_meta_keys[ $object_type ][ $object_subtype ];
1344  }
1345  
1346  /**
1347   * Retrieves registered metadata for a specified object.
1348   *
1349   * The results include both meta that is registered specifically for the
1350   * object's subtype and meta that is registered for the entire object type.
1351   *
1352   * @since 4.6.0
1353   *
1354   * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1355   *                            or any other object type with an associated meta table.
1356   * @param int    $object_id   ID of the object the metadata is for.
1357   * @param string $meta_key    Optional. Registered metadata key. If not specified, retrieve all registered
1358   *                            metadata for the specified object.
1359   * @return mixed A single value or array of values for a key if specified. An array of all registered keys
1360   *               and values for an object ID if not. False if a given $meta_key is not registered.
1361   */
1362  function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) {
1363      $object_subtype = get_object_subtype( $object_type, $object_id );
1364  
1365      if ( ! empty( $meta_key ) ) {
1366          if ( ! empty( $object_subtype ) && ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
1367              $object_subtype = '';
1368          }
1369  
1370          if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
1371              return false;
1372          }
1373  
1374          $meta_keys     = get_registered_meta_keys( $object_type, $object_subtype );
1375          $meta_key_data = $meta_keys[ $meta_key ];
1376  
1377          $data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] );
1378  
1379          return $data;
1380      }
1381  
1382      $data = get_metadata( $object_type, $object_id );
1383      if ( ! $data ) {
1384          return array();
1385      }
1386  
1387      $meta_keys = get_registered_meta_keys( $object_type );
1388      if ( ! empty( $object_subtype ) ) {
1389          $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( $object_type, $object_subtype ) );
1390      }
1391  
1392      return array_intersect_key( $data, $meta_keys );
1393  }
1394  
1395  /**
1396   * Filters out `register_meta()` args based on a whitelist.
1397   *
1398   * `register_meta()` args may change over time, so requiring the whitelist
1399   * to be explicitly turned off is a warranty seal of sorts.
1400   *
1401   * @access private
1402   * @since 4.6.0
1403   *
1404   * @param array $args         Arguments from `register_meta()`.
1405   * @param array $default_args Default arguments for `register_meta()`.
1406   * @return array Filtered arguments.
1407   */
1408  function _wp_register_meta_args_whitelist( $args, $default_args ) {
1409      return array_intersect_key( $args, $default_args );
1410  }
1411  
1412  /**
1413   * Returns the object subtype for a given object ID of a specific type.
1414   *
1415   * @since 4.9.8
1416   *
1417   * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
1418   *                            or any other object type with an associated meta table.
1419   * @param int    $object_id   ID of the object to retrieve its subtype.
1420   * @return string The object subtype or an empty string if unspecified subtype.
1421   */
1422  function get_object_subtype( $object_type, $object_id ) {
1423      $object_id      = (int) $object_id;
1424      $object_subtype = '';
1425  
1426      switch ( $object_type ) {
1427          case 'post':
1428              $post_type = get_post_type( $object_id );
1429  
1430              if ( ! empty( $post_type ) ) {
1431                  $object_subtype = $post_type;
1432              }
1433              break;
1434  
1435          case 'term':
1436              $term = get_term( $object_id );
1437              if ( ! $term instanceof WP_Term ) {
1438                  break;
1439              }
1440  
1441              $object_subtype = $term->taxonomy;
1442              break;
1443  
1444          case 'comment':
1445              $comment = get_comment( $object_id );
1446              if ( ! $comment ) {
1447                  break;
1448              }
1449  
1450              $object_subtype = 'comment';
1451              break;
1452  
1453          case 'user':
1454              $user = get_user_by( 'id', $object_id );
1455              if ( ! $user ) {
1456                  break;
1457              }
1458  
1459              $object_subtype = 'user';
1460              break;
1461      }
1462  
1463      /**
1464       * Filters the object subtype identifier for a non standard object type.
1465       *
1466       * The dynamic portion of the hook, `$object_type`, refers to the object
1467       * type (post, comment, term, or user).
1468       *
1469       * @since 4.9.8
1470       *
1471       * @param string $object_subtype Empty string to override.
1472       * @param int    $object_id      ID of the object to get the subtype for.
1473       */
1474      return apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
1475  }


Generated: Mon Mar 30 01:00:03 2020 Cross-referenced by PHPXref 0.7.1