$30 off During Our Annual Pro Sale. View Details »

wp_post_insert(): how, what, why?

Peter Wilson
November 08, 2017

wp_post_insert(): how, what, why?

Peter Wilson

November 08, 2017
Tweet

More Decks by Peter Wilson

Other Decks in Programming

Transcript

  1. wp_insert_post(): How, what and why?
    Peter Wilson • @pwcc • peterwilson.cc

    View Slide

  2. 1 /**
    2 * Insert or update a post.
    3 *
    4 * If the $postarr parameter has 'ID' set to a value, then post will be updated.
    5 *
    6 * You can set the post date manually, by setting the values for 'post_date'
    7 * and 'post_date_gmt' keys. You can close the comments or open the comments by
    8 * setting the value for 'comment_status' key.
    9 *
    10 * @since 1.0.0
    11 * @since 4.2.0 Support was added for encoding emoji in the post title, content, and excerpt.
    12 * @since 4.4.0 A 'meta_input' array can now be passed to `$postarr` to add post meta data.t
    13 *
    14 * @see sanitize_post()
    15 * @global wpdb $wpdb WordPress database abstraction object.
    16 *
    17 * @param array $postarr {
    18 * An array of elements that make up a post to update or insert.
    19 *
    20 * @type int $ID The post ID. If equal to something other than 0,
    21 * the post with that ID will be updated. Default 0.
    22 * @type int $post_author The ID of the user who added the post. Default is
    23 * the current user ID.
    24 * @type string $post_date The date of the post. Default is the current time.
    25 * @type string $post_date_gmt The date of the post in the GMT timezone. Default is
    26 * the value of `$post_date`.
    27 * @type mixed $post_content The post content. Default empty.
    28 * @type string $post_content_filtered The filtered post content. Default empty.
    29 * @type string $post_title The post title. Default empty.
    30 * @type string $post_excerpt The post excerpt. Default empty.
    31 * @type string $post_status The post status. Default 'draft'.
    32 * @type string $post_type The post type. Default 'post'.
    33 * @type string $comment_status Whether the post can accept comments. Accepts 'open' or 'closed'.
    34 * Default is the value of 'default_comment_status' option.
    35 * @type string $ping_status Whether the post can accept pings. Accepts 'open' or 'closed'.
    36 * Default is the value of 'default_ping_status' option.
    37 * @type string $post_password The password to access the post. Default empty.
    38 * @type string $post_name The post name. Default is the sanitized post title
    39 * when creating a new post.
    40 * @type string $to_ping Space or carriage return-separated list of URLs to ping.
    41 * Default empty.

    View Slide

  3. View Slide

  4. 598 do_action( 'save_post', $post_ID, $post, $upda
    599
    600 /**
    601 * Fires once a post has been saved.
    602 *
    603 * @since 2.0.0
    604 *
    605 * @param int $post_ID Post ID.
    606 * @param WP_Post $post Post object.
    607 * @param bool $update Whether this is an
    608 */
    609 do_action( 'wp_insert_post', $post_ID, $post,
    610
    611 return $post_ID;
    612 }

    View Slide

  5. php > var_dump( PHP_INT_MAX );

    View Slide

  6. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)


    View Slide

  7. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)

    php > var_dump( 18446744073709551615 );

    View Slide

  8. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)

    php > var_dump( 18446744073709551615 );
    float(1.844674407371E+19)


    View Slide

  9. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)

    php > var_dump( 18446744073709551615 );
    float(1.844674407371E+19)

    php > var_dump( 18446744073709551615 > PHP_INT_MAX );

    View Slide

  10. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)

    php > var_dump( 18446744073709551615 );
    float(1.844674407371E+19)

    php > var_dump( 18446744073709551615 > PHP_INT_MAX );
    bool(true)


    View Slide

  11. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)

    php > var_dump( 18446744073709551615 );
    float(1.844674407371E+19)

    php > var_dump( 18446744073709551615 > PHP_INT_MAX );
    bool(true)

    php > var_dump( (int) 18446744073709551615 );

    View Slide

  12. php > var_dump( PHP_INT_MAX );
    int(9223372036854775807)

    php > var_dump( 18446744073709551615 );
    float(1.844674407371E+19)

    php > var_dump( 18446744073709551615 > PHP_INT_MAX );
    bool(true)

    php > var_dump( (int) 18446744073709551615 );
    int(0)

    View Slide

  13. /**
    * Update a post with new post data.
    *
    * The date does not have to be set for drafts. You can set the date and it will
    * not be overridden.
    *
    * @since 1.0.0
    *
    * @param array|object $postarr Optional. Post data. Arrays are expected to be escaped,
    * objects are not. Default array.
    * @param bool $wp_error Optional. Allow return of WP_Error on failure. Default false.
    * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
    */
    function wp_update_post( $postarr = array(), $wp_error = false ) {
    // Logic Checks.
    // Smart Defaults
    return wp_insert_post( $postarr, $wp_error );
    }

    View Slide

  14. /**
    * Update a post with new post data.
    *
    * The date does not have to be set for drafts. You can set the date and it will
    * not be overridden.
    *
    * @since 1.0.0
    *
    * @param array|object $postarr Optional. Post data. Arrays are expected to be escaped,
    * objects are not. Default array.
    * @param bool $wp_error Optional. Allow return of WP_Error on failure. Default false.
    * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
    */
    function wp_update_post( $postarr = array(), $wp_error = false ) {
    // Logic Checks.
    // Smart Defaults
    return wp_insert_post( $postarr, $wp_error );
    }
    // First, get all of the original fields.
    $post = get_post( $postarr['ID'], ARRAY_A );
    if ( is_null( $post ) ) {
    /* ... */
    return 0;
    }

    View Slide

  15. /**
    * Update a post with new post data.
    *
    * The date does not have to be set for drafts. You can set the date and it will
    * not be overridden.
    *
    * @since 1.0.0
    *
    * @param array|object $postarr Optional. Post data. Arrays are expected to be escaped,
    * objects are not. Default array.
    * @param bool $wp_error Optional. Allow return of WP_Error on failure. Default false.
    * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
    */
    function wp_update_post( $postarr = array(), $wp_error = false ) {
    // Logic Checks.
    // Smart Defaults
    return wp_insert_post( $postarr, $wp_error );
    }
    // First, get all of the original fields.
    $post = get_post( $postarr['ID'], ARRAY_A );
    if ( is_null( $post ) ) {
    /* ... */
    return 0;
    }

    View Slide

  16. Permission checks
    wp_insert_post() skips them.

    View Slide

  17. if ( current_user_can( 'edit_posts' ) ) {
    wp_insert_post( [] );
    }

    View Slide

  18. /* if ( current_user_can( 'edit_posts' ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  19. $post_type_object = get_post_type_object( 'post' );
    if ( current_user_can( $post_type_object->cap->create_posts ) ) {
    /* if ( current_user_can( 'edit_posts' ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  20. $post_type_object = get_post_type_object( 'post' );
    if ( current_user_can( $post_type_object->cap->create_posts ) ) {
    /* if ( current_user_can( 'edit_posts' ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  21. $post_type_object = get_post_type_object( 'post' );
    if ( current_user_can( $post_type_object->cap->create_posts ) ) {
    /* if ( current_user_can( 'edit_posts' ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  22. $post_type_object = get_post_type_object( 'slide_deck' );
    if ( current_user_can( $post_type_object->cap->create_posts ) ) {
    /* if ( current_user_can( 'edit_slide_decks' ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  23. $post_type_object = get_post_type_object( 'slide_deck' );
    if ( current_user_can( $post_type_object->cap->create_posts ) ) {
    /* if ( current_user_can( 'create_slide_decks' ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  24. if ( current_user_can( 'edit_post', $post_id ) ) {
    wp_insert_post( [] );
    }

    View Slide

  25. $post_type_object = get_post_type_object( 'post' );
    if (
    current_user_can(
    $post_type_object->cap->edit_post,
    $post_id
    )
    ) {
    /* if ( current_user_can( 'edit_post', $post_id ) ) { */
    wp_insert_post( [] );
    }

    View Slide

  26. // Don't allow contributors to set the
    // post slug for pending review posts.
    if ( 'pending' == $post_status &&
    ! current_user_can( 'publish_posts' )
    ) {
    $post_name = '';
    }

    View Slide

  27. In the beginning

    View Slide

  28. function wp_insert_post( $postarr, $wp_error = false ) {
    global $wpdb;
    $user_id = get_current_user_id();
    $defaults = array(
    'post_author' => $user_id,
    'post_content' => '',
    'post_content_filtered' => '',
    'post_title' => '',
    'post_excerpt' => '',
    'post_status' => 'draft',
    'post_type' => 'post',
    'comment_status' => '',
    'ping_status' => '',
    'post_password' => '',
    'to_ping' => '',
    'pinged' => '',
    'post_parent' => 0,
    'menu_order' => 0,
    'guid' => '',
    'import_id' => 0,
    'context' => '',
    );
    $postarr = wp_parse_args( $postarr, $defaults );
    unset( $postarr['filter'] );

    View Slide

  29. $postarr = wp_parse_args( $postarr, $defaults );
    unset( $postarr['filter'] );
    $postarr = sanitize_post( $postarr, 'db' );
    // Are we updating or creating?
    $post_ID = 0;
    $update = false;
    $guid = $postarr['guid'];
    if ( ! empty( $postarr['ID'] ) ) {
    $update = true;
    // Get the post ID and GUID.
    $post_ID = $postarr['ID'];
    $post_before = get_post( $post_ID );
    if ( is_null( $post_before ) ) {
    if ( $wp_error ) {
    return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
    }
    return 0;
    }
    $guid = get_post_field( 'guid', $post_ID );
    $previous_status = get_post_field( 'post_status', $post_ID );
    } else {
    $previous_status = 'new';
    }

    View Slide

  30. $postarr = wp_parse_args( $postarr, $defaults );
    unset( $postarr['filter'] );
    $postarr = sanitize_post( $postarr, 'db' );
    // Are we updating or creating?
    $post_ID = 0;
    $update = false;
    $guid = $postarr['guid'];
    if ( ! empty( $postarr['ID'] ) ) {
    $update = true;
    // Get the post ID and GUID.
    $post_ID = $postarr['ID'];
    $post_before = get_post( $post_ID );
    if ( is_null( $post_before ) ) {
    if ( $wp_error ) {
    return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
    }
    return 0;
    }
    $guid = get_post_field( 'guid', $post_ID );
    $previous_status = get_post_field( 'post_status', $post_ID );
    } else {
    $previous_status = 'new';
    }
    oring

    View Slide

  31. /**
    * Filters slashed post data just before it is inserted into
    * the database.
    *
    * @since 2.7.0
    *
    * @param array $data An array of slashed post data.
    * @param array $postarr An array of sanitized, but
    * otherwise unmodified post data.
    */
    $data = apply_filters( 'wp_insert_post_data', $data, $postarr );

    View Slide

  32. /**
    * Filters slashed post data just before it is inserted into
    * the database.
    *
    * @since 2.7.0
    *
    * @param array $data An array of slashed post data.
    * @param array $postarr An array of sanitized, but
    * otherwise unmodified post data.
    */
    $data = apply_filters( 'wp_insert_post_data', $data, $postarr );

    View Slide

  33. /**
    * Filters slashed post data just before it is inserted into
    * the database.
    *
    * @since 2.7.0
    *
    * @param array $data An array of slashed post data.
    * @param array $postarr An array of sanitized, but
    * otherwise unmodified post data.
    */
    $data = apply_filters( 'wp_insert_post_data', $data, $postarr );

    View Slide

  34. /**
    * Add "sincerely, -me" to the end of each post before saving.
    *
    * @param array $data An array of slashed post data.
    * @return array A modified array of slashed post data.
    */
    function add_evan_hansen_reference( $data ) {
    $data = wp_unslash( $data );
    $data['post_content'] .= "\n\nsincerely,\n-me";
    return wp_slash( $data );
    }
    add_filter( 'wp_insert_post_data', 'add_evan_hansen_reference' );

    View Slide

  35. /**
    * Add "sincerely, -me" to the end of each post before saving.
    *
    * @param array $data An array of slashed post data.
    * @return array A modified array of slashed post data.
    */
    function add_evan_hansen_reference( $data ) {
    $data = wp_unslash( $data );
    $data['post_content'] .= "\n\nsincerely,\n-me";
    return wp_slash( $data );
    }
    add_filter( 'wp_insert_post_data', 'add_evan_hansen_reference' );

    View Slide

  36. /**
    * Add "sincerely, -me" to the end of each post before saving.
    *
    * @param array $data An array of slashed post data.
    * @return array A modified array of slashed post data.
    */
    function add_evan_hansen_reference( $data ) {
    $data = wp_unslash( $data );
    $data['post_content'] .= "\n\nsincerely,\n-me";
    return wp_slash( $data );
    }
    add_filter( 'wp_insert_post_data', 'add_evan_hansen_reference' );

    View Slide

  37. /**
    * Add "sincerely, -me" to the end of each post before saving.
    *
    * @param array $data An array of slashed post data.
    * @return array A modified array of slashed post data.
    */
    function add_evan_hansen_reference( $data ) {
    $data = wp_unslash( $data );
    $data['post_content'] .= "\n\nsincerely,\n-me";
    return wp_slash( $data );
    }
    add_filter( 'wp_insert_post_data', 'add_evan_hansen_reference' );

    View Slide

  38. return wp_slash( $data );

    View Slide

  39. $data = wp_slash( $data );
    return $data;

    View Slide

  40. $data = wp_slash( $data );
    $data['post_title'] .= " ¯\_(ϑ)_/¯";
    return $data;

    View Slide

  41. $data = wp_slash( $data );
    $data['post_title'] .= " ¯\_(ϑ)_/¯";
    return $data;

    View Slide

  42. $data = wp_slash( $data );
    return $data;

    View Slide

  43. return wp_slash( $data );

    View Slide

  44. $data['post_title'] .= " ¯\_(ϑ)_/¯”;
    return wp_slash( $data );

    View Slide

  45. echo esc_url( $data );

    View Slide

  46. /**
    * Filters slashed post data just before it is inserted into
    * the database.
    *
    * @since 2.7.0
    *
    * @param array $data An array of slashed post data.
    * @param array $postarr An array of sanitized, but
    * otherwise unmodified post data.
    */
    $data = apply_filters( 'wp_insert_post_data', $data, $postarr );

    View Slide

  47. if ( $update ) {
    /**
    * Fires immediately before an existing post is updated in the database.
    *
    * @since 2.5.0
    *
    * @param int $post_ID Post ID.
    * @param array $data Array of unslashed post data.
    */
    do_action( 'pre_post_update', $post_ID, $data );
    if ( false === $wpdb->update( $wpdb->posts, $data, $where ) ) {
    if ( $wp_error ) {
    return new WP_Error( 'db_update_error', __( 'Could not update post in the
    } else {
    return 0;
    }
    }
    } else {
    // If there is a suggested ID, use it if not already present.
    if ( ! empty( $import_id ) ) {
    $import_id = (int) $import_id;
    if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID

    View Slide

  48. *
    * @param int $post_ID Post ID.
    * @param array $data Array of unslashed post data.
    */
    do_action( 'pre_post_update', $post_ID, $data );
    if ( false === $wpdb->update( $wpdb->posts, $data, $where ) ) {
    if ( $wp_error ) {
    return new WP_Error( 'db_update_error', __( 'Could not update post in the
    } else {
    return 0;
    }
    }
    } else {
    // If there is a suggested ID, use it if not already present.
    if ( ! empty( $import_id ) ) {
    $import_id = (int) $import_id;
    if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID
    $data['ID'] = $import_id;
    }
    }
    if ( false === $wpdb->insert( $wpdb->posts, $data ) ) {
    if ( $wp_error ) {
    return new WP_Error( 'db_insert_error', __( 'Could not insert post into th
    } else {

    View Slide

  49. /**
    * Filters slashed post data just before it is inserted into
    * the database.
    *
    * @since 2.7.0
    *
    * @param array $data An array of slashed post data.
    * @param array $postarr An array of sanitized, but
    * otherwise unmodified post data.
    */
    $data = apply_filters( 'wp_insert_post_data', $data, $postarr );

    View Slide

  50. if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
    wp_set_post_categories( $post_ID, $post_category );
    }
    if (
    isset( $postarr['tags_input'] )
    && is_object_in_taxonomy( $post_type, 'post_tag' )
    ) {
    wp_set_post_tags( $post_ID, $postarr['tags_input'] );
    }

    View Slide

  51. wp_set_post_categories( $post_ID, $post_category );
    wp_set_post_tags( $post_ID, $postarr['tags_input'] );

    View Slide

  52. /**
    * Set the terms for a post.
    *
    * @since 2.8.0
    *
    * @see wp_set_object_terms()
    *
    * @param int $post_id Optional. The Post ID.
    * Does not default to the ID of the global $post.
    * @param string|array $tags Optional. An array of terms to set for the post, or a
    * string of terms separated by commas. Default empty.
    * @param string $taxonomy Optional. Taxonomy name. Default 'post_tag'.
    * @param bool $append Optional. If true, don't delete existing terms, just add on.
    * If false, replace the terms with the new terms. Default false.
    * @return array|false|WP_Error Array of term taxonomy IDs of affected terms.
    * WP_Error or false on failure.
    */
    function wp_set_post_terms( $post_id = 0, $tags = '', $taxonomy = 'post_tag', $append = false ) {
    }

    View Slide

  53. /**
    * Create Term and Taxonomy Relationships.
    *
    * Relates an object (post, link etc) to a term and taxonomy type. Creates the
    * term and taxonomy relationship if it doesn't already exist. Creates a term if
    * it doesn't exist (using the slug).
    *
    * A relationship means that the term is grouped in or belongs to the taxonomy.
    * A term has no meaning until it is given context by defining which taxonomy it
    * exists under.
    *
    * @since 2.3.0
    *
    * @global wpdb $wpdb The WordPress database abstraction object.
    *
    * @param int $object_id The object to relate to.
    * @param string|int|array $terms A single term slug, single term id, or array of
    * either term slugs or ids. Will replace all existing
    * related terms in this taxonomy. Passing an empty
    * value will remove all related terms.
    * @param string $taxonomy The context in which to relate the term to
    * the object.
    * @param bool $append Optional. If false will delete difference of terms.
    * Default false.
    * @return array|WP_Error Term taxonomy IDs of the affected terms.
    */
    function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
    }

    View Slide

  54. wp_set_post_categories( $post_ID, $post_category )

    View Slide

  55. if ( 'post' == $post_type && 'auto-draft' != $post_status ) {
    $post_categories = array( get_option('default_category') );
    $append = false;
    } else {
    $post_categories = array();
    }

    View Slide

  56. function wp_set_post_tags( $post_id = 0, $tags = '', $append = false ) {
    return wp_set_post_terms( $post_id, $tags, 'post_tag', $append);
    }

    View Slide

  57. /**
    * Set the terms for a post.
    *
    * @since 2.8.0
    *
    * @see wp_set_object_terms()
    *
    * @param int $post_id Optional. The Post ID.
    * Does not default to the ID of the global $post.
    * @param string|array $tags Optional. An array of terms to set for the post, or a
    * string of terms separated by commas. Default empty.
    * @param string $taxonomy Optional. Taxonomy name. Default 'post_tag'.
    * @param bool $append Optional. If true, don't delete existing terms, just add on.
    * If false, replace the terms with the new terms. Default false.
    * @return array|false|WP_Error Array of term taxonomy IDs of affected terms.
    * WP_Error or false on failure.
    */
    function wp_set_post_terms( $post_id = 0, $tags = '', $taxonomy = 'post_tag', $append = false ) {
    }

    View Slide

  58. Non-hierarchical taxonomy (eg tags)
    wp_set_post_terms(
    12, // Post ID.
    [ 'apple', 'microsoft' ],// Terms (slugs).
    'post_tag' // Taxonomy.
    );

    View Slide

  59. Non-hierarchical taxonomy (eg tags)
    wp_set_post_terms(
    12, // Post ID.
    [ 12, 120 ], // Terms (IDs).
    'post_tag' // Taxonomy.
    );

    View Slide

  60. Non-hierarchical taxonomy (eg tags)
    wp_set_post_terms(
    12, // Post ID.
    [ 'apple', 'microsoft' ],// Terms (slugs).
    'post_tag' // Taxonomy.
    );

    View Slide

  61. Hierarchical taxonomy (eg categories)

    View Slide

  62. Categories
    • Phones
    • Android
    • Apple
    • Laptops
    • Apple
    • Microsoft

    View Slide

  63. Categories
    • Phones (phones)
    • Android (android)
    • Apple (apple)
    • Laptops (laptop)
    • Apple (apple)
    • Microsoft (microsoft)

    View Slide

  64. Hierarchical taxonomy (eg categories)
    wp_set_post_terms(
    12, // Post ID.
    [ 'apple', 'microsoft' ],// Terms (slugs).
    'category' // Taxonomy.
    );

    View Slide

  65. Hierarchical taxonomy (eg categories)
    wp_set_post_terms(
    12, // Post ID.
    [ 12, 120 ], // Terms (IDs).
    'category' // Taxonomy.
    );

    View Slide

  66. /**
    * Set the terms for a post.
    *
    * @since 2.8.0
    *
    * @see wp_set_object_terms()
    *
    * @param int $post_id Optional. The Post ID.
    * Does not default to the ID of the global $post.
    * @param string|array $tags Optional. An array of terms to set for the post, or a
    * string of terms separated by commas. Default empty.
    * @param string $taxonomy Optional. Taxonomy name. Default 'post_tag'.
    * @param bool $append Optional. If true, don't delete existing terms, just add on.
    * If false, replace the terms with the new terms. Default false.
    * @return array|false|WP_Error Array of term taxonomy IDs of affected terms.
    * WP_Error or false on failure.
    */
    function wp_set_post_terms( $post_id = 0, $tags = '', $taxonomy = 'post_tag', $append = false ) {
    }

    View Slide

  67. /*
    * Hierarchical taxonomies must always pass IDs rather
    * than names so that children with the same names but
    * different parents aren't confused.
    */
    if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    $tags = array_unique( array_map( 'intval', $tags ) );
    }

    View Slide

  68. /**
    * Create Term and Taxonomy Relationships.
    *
    * Relates an object (post, link etc) to a term and taxonomy type. Creates the
    * term and taxonomy relationship if it doesn't already exist. Creates a term if
    * it doesn't exist (using the slug).
    *
    * A relationship means that the term is grouped in or belongs to the taxonomy.
    * A term has no meaning until it is given context by defining which taxonomy it
    * exists under.
    *
    * @since 2.3.0
    *
    * @global wpdb $wpdb The WordPress database abstraction object.
    *
    * @param int $object_id The object to relate to.
    * @param string|int|array $terms A single term slug, single term id, or array of
    * either term slugs or ids. Will replace all existing
    * related terms in this taxonomy. Passing an empty
    * value will remove all related terms.
    * @param string $taxonomy The context in which to relate the term to
    * the object.
    * @param bool $append Optional. If false will delete difference of terms.
    * Default false.
    * @return array|WP_Error Term taxonomy IDs of the affected terms.
    */
    function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
    }

    View Slide

  69. /**
    * Create Term and Taxonomy Relationships.
    *
    * Relates an object (post, link etc) to a term and taxonomy type. Creates the
    * term and taxonomy relationship if it doesn't already exist. Creates a term if
    * it doesn't exist (using the slug).
    *
    * A relationship means that the term is grouped in or belongs to the taxonomy.
    * A term has no meaning until it is given context by defining which taxonomy it
    * exists under.
    *
    * @since 2.3.0
    *
    * @global wpdb $wpdb The WordPress database abstraction object.
    *
    * @param int $object_id The object to relate to.
    * @param string|int|array $terms A single term slug, single term id, or array of
    * either term slugs or ids. Will replace all existing
    * related terms in this taxonomy. Passing an empty
    * value will remove all related terms.
    * @param string $taxonomy The context in which to relate the term to
    * the object.
    * @param bool $append Optional. If false will delete difference of terms.
    * Default false.
    * @return array|WP_Error Term taxonomy IDs of the affected terms.
    */
    function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
    }
    Fascinating

    but way, way, way
    beyond the scope
    f this talk

    View Slide

  70. // New-style support for all custom taxonomies.
    foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
    $taxonomy_obj = get_taxonomy( $taxonomy );
    if ( ! $taxonomy_obj ) {
    _doing_it_wrong( /* snip */ );
    continue;
    }
    // array = hierarchical, string = non-hierarchical.
    if ( is_array( $tags ) ) {
    $tags = array_filter( $tags );
    }
    if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
    wp_set_post_terms( $post_ID, $tags, $taxonomy );
    }
    }

    View Slide

  71. // New-style support for all custom taxonomies.
    foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
    $taxonomy_obj = get_taxonomy( $taxonomy );
    if ( ! $taxonomy_obj ) {
    _doing_it_wrong( /* snip */ );
    continue;
    }
    // array = hierarchical, string = non-hierarchical.
    if ( is_array( $tags ) ) {
    $tags = array_filter( $tags );
    }
    if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
    wp_set_post_terms( $post_ID, $tags, $taxonomy );
    }
    }

    View Slide

  72. // New-style support for all custom taxonomies.
    foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
    $taxonomy_obj = get_taxonomy( $taxonomy );
    if ( ! $taxonomy_obj ) {
    _doing_it_wrong( /* snip */ );
    continue;
    }
    // array = hierarchical, string = non-hierarchical.
    if ( is_array( $tags ) ) {
    $tags = array_filter( $tags );
    }
    if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
    wp_set_post_terms( $post_ID, $tags, $taxonomy );
    }
    }

    View Slide

  73. Post meta

    View Slide

  74. wp_insert_post(
    [
    'post_type' => 'musical',
    'post_title' => 'Dear Evan Hansen',
    'meta_input' => [
    'Male lead' => 'Ben Platt',
    'Female lead' => 'Laura Dreyfuss',
    ],
    ]
    );

    View Slide

  75. if ( ! empty( $postarr['meta_input'] ) ) {
    foreach ( $postarr['meta_input'] as $field => $value ) {
    update_post_meta( $post_ID, $field, $value );
    }
    }

    View Slide

  76. update_post_meta( $post_ID, 'Male Lead', 'Ben Platt', ‘Ben Platt' );
    update_post_meta( $post_ID, 'Male Lead', 'Noah Galvin', 'Noah Galvin' );
    update_post_meta( $post_ID, 'Male Lead', 'Taylor Trensch', 'Taylor Trensch' );

    View Slide

  77. /**
    * Update metadata for the specified object. If no value already exists for the specified
    object
    * ID and metadata key, the metadata will be added.
    *
    * @since 2.9.0
    *
    * @global wpdb $wpdb WordPress database abstraction object.
    *
    * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
    * @param int $object_id ID of the object metadata is for
    * @param string $meta_key Metadata key
    * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
    * @param mixed $prev_value Optional. If specified, only update existing metadata

    * entries with the specified value. Otherwise, update all entries.
    * @return int|bool Meta ID if the key didn't exist, true on successful update, 

    *. false on failure.
    */
    function update_metadata($meta_type, $object_id, $meta_key, $meta_value, $prev_value = '') {

    View Slide

  78. /**
    * Filters whether to update metadata of a specific type.
    *
    * The dynamic portion of the hook, `$meta_type`, refers to the meta
    * object type (comment, post, or user). Returning a non-null value
    * will effectively short-circuit the function.
    *
    * @since 3.1.0
    *
    * @param null|bool $check Whether to allow updating metadata for the
    * given type.
    * @param int $object_id Object ID.
    * @param string $meta_key Meta key.
    * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
    * @param mixed $prev_value Optional. If specified, only update existing
    * metadata entries with the specified value.
    * Otherwise, update all entries.
    */
    $check = apply_filters(
    "update_{$meta_type}_metadata",
    null,
    $object_id, $meta_key, $meta_value, $prev_value );
    if ( null !== $check ) {
    return (bool) $check;
    }

    View Slide

  79. /**
    * Filters whether to update metadata of a specific type.
    *
    * The dynamic portion of the hook, `$meta_type`, refers to the meta
    * object type (comment, post, or user). Returning a non-null value
    * will effectively short-circuit the function.
    *
    * @since 3.1.0
    *
    * @param null|bool $check Whether to allow updating metadata for the
    * given type.
    * @param int $object_id Object ID.
    * @param string $meta_key Meta key.
    * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
    * @param mixed $prev_value Optional. If specified, only update existing
    * metadata entries with the specified value.
    * Otherwise, update all entries.
    */
    $check = apply_filters(
    "update_{$meta_type}_metadata",
    null,
    $object_id, $meta_key, $meta_value, $prev_value );
    if ( null !== $check ) {
    return (bool) $check;
    }
    "update_post_metadata",

    View Slide

  80. function pw_update_meta_filter( $check ) {
    // Coin toss.
    if ( rand( 0, 1 ) ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter' );

    View Slide

  81. function pw_update_meta_filter( $check ) {
    // Coin toss.
    if ( rand( 0, 1 ) ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter' );

    View Slide

  82. function pw_update_meta_filter( $check ) {
    // Coin toss.
    if ( rand( 0, 1 ) ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter' );

    View Slide

  83. function pw_update_meta_filter( $check ) {
    // Coin toss.
    if ( rand( 0, 1 ) ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter' );

    View Slide

  84. function pw_update_meta_filter( $check, $post_id, $meta_key, $meta_value ) {
    // Check
    if ( 'Male Lead' !== $meta_key ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    pw_call_custom_functionality( $post_id, $meta_key, $meta_value );
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter', 10, 4 );

    View Slide

  85. function pw_update_meta_filter( $check, $post_id, $meta_key, $meta_value ) {
    // Check
    if ( 'Male Lead' !== $meta_key ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    pw_call_custom_functionality( $post_id, $meta_key, $meta_value );
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter', 10, 4 );

    View Slide

  86. function pw_update_meta_filter( $check, $post_id, $meta_key, $meta_value ) {
    // Check
    if ( 'Male Lead' !== $meta_key ) {
    // Allow function to run.
    return null;
    }
    // Do not allow function to run.
    pw_call_custom_functionality( $post_id, $meta_key, $meta_value );
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter', 10, 4 );

    View Slide

  87. function pw_update_meta_filter( $check, $post_id, $meta_key, $meta_value ) {
    // Check
    if ( 'Male Lead' !== $meta_key ) {
    // Allow function to run.
    return $check;
    }
    // Do not allow function to run.
    pw_call_custom_functionality( $post_id, $meta_key, $meta_value );
    return false;
    }
    add_filter( 'update_post_metadata', 'pw_update_meta_filter', 10, 4 );

    View Slide

  88. Wrapping up
    Actions and filters

    View Slide

  89. if ( $update ) {
    do_action( 'edit_post', $post_ID, $post );
    $post_after = get_post( $post_ID );
    do_action( 'post_updated', $post_ID, $post_after, $post_before );
    }
    Post revision saved.

    View Slide

  90. do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );
    do_action( 'save_post', $post_ID, $post, $update );
    do_action( 'wp_insert_post', $post_ID, $post, $update );

    View Slide

  91. return $postID;
    }

    View Slide

  92. return $postID;
    }
    // Any Questions?

    View Slide