Inventory_Presser_Photo_Numberer
Source Source
File: includes/class-photo-numberer.php
class Inventory_Presser_Photo_Numberer { /** * Adds hooks * * @return void */ public function add_hooks() { // Check if photos are attached to a vehicle parent. add_action( 'add_attachment', array( __CLASS__, 'maybe_number_photo' ), 10, 1 ); add_action( 'edit_attachment', array( __CLASS__, 'maybe_number_photo' ), 10, 1 ); /** * Put the sequence number in the title of the post to which photos are * attached in the Media Library table view. */ add_filter( 'the_title', array( $this, 'add_sequence_number_to_titles' ), 10, 2 ); } /** * Dynamically changes post titles of vehicle attachments in the dashboard * to identify their sequence number. * * @param string $title The post title. * @param int $id The post ID. * @return string */ public function add_sequence_number_to_titles( $title, $id = null ) { // Don't double dip during REST API requests. if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return $title; } // What post? if ( empty( $id ) ) { return $title; } if ( ! is_admin() ) { return $title; } // Is this the Media Library upload.php? if ( ! function_exists( 'get_current_screen' ) ) { return $title; } $screen = get_current_screen(); if ( empty( $screen->parent_file ) || 'upload.php' !== $screen->parent_file ) { // No. return $title; } if ( 'attachment' !== get_post_type( $id ) ) { // No. return $title; } $parent = get_post_parent( $id ); if ( empty( $parent ) || INVP::POST_TYPE !== $parent->post_type ) { // No. return $title; } // Get the photo count. return sprintf( '%s (%s %s %s %s)', $title, __( 'Photo', 'inventory-presser' ), INVP::get_meta( 'photo_number', $id ), __( 'of', 'inventory-presser' ), invp_get_the_photo_count( $parent->ID ) ); } /** * Deletes transients that store vehicle photos to help load galleries. * * @param int $post_id The post ID of a vehicle. * @return void */ public static function delete_photo_transients( $post_id ) { delete_transient( 'invp_get_the_photos_images_' . $post_id ); delete_transient( 'invp_get_the_photos_image_urls_' . $post_id ); } /** * Filter callback on add_attachment. Decides whether to write meta values * on attachments if they are uploaded to vehicles. If this method * determines the photo sequence number to be 1, the attachment is also set * as the featured image. * * @param int $post_id Attachment ID. * @return void */ public static function maybe_number_photo( $post_id ) { // Don't double dip during REST API requests. if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return; } if ( null === $post_id ) { return; } // Is this new attachment even attached to a post? $attachment = get_post( $post_id ); if ( empty( $attachment->post_parent ) ) { // No. return; } // Is this even attached to a vehicle? if ( INVP::POST_TYPE !== get_post_type( $attachment->post_parent ) ) { // No. return; } // Save the VIN in the photo meta. self::save_meta_vin( $post_id, $attachment->post_parent ); // Save a md5 hash checksum of the attachment in meta. self::save_meta_hash( $post_id ); // Assign and save a sequence number for the photo like 1, 2, 3, etc. self::save_meta_photo_number( $post_id, $attachment->post_parent ); // Delete the transients that hold this vehicle's photos. self::delete_photo_transients( $attachment->post_parent ); } /** * Reassigns sequence numbers to all photos attached to a vehicle post. * Useful after multiple attachments or when a photo is deleted. * * @param int $post_id The post ID of a vehicle. * @return void */ public static function renumber_photos( $post_id ) { // Get all of this vehicle's photos that have numbers. $posts = get_children( array( 'meta_key' => apply_filters( 'invp_prefix_meta_key', 'photo_number' ), 'orderby' => 'meta_value_num', 'post_parent' => $post_id, 'post_type' => 'attachment', ) ); // Get all of this post's attachments with or without numbers. $unnumbered_posts = get_children( array( 'post_parent' => $post_id, 'post_type' => 'attachment', ) ); if ( count( $posts ) === count( $unnumbered_posts ) ) { return; } foreach ( $unnumbered_posts as $unnumbered_post ) { $have_post_ids = array_column( $posts, 'ID' ); if ( ! in_array( $unnumbered_post->ID, $have_post_ids, true ) ) { $posts[ $unnumbered_post->ID ] = $unnumbered_post; } } $photo_count = count( $posts ); if ( 0 === $photo_count ) { return; } $n = 1; foreach ( $posts as $child_post_id => $post ) { self::save_meta_photo_number( $child_post_id, $post_id, $n ); if ( 1 === $n ) { // This is photo number 1, it should be the featured image. set_post_thumbnail( $post_id, $child_post_id ); } ++$n; } self::delete_photo_transients( $post_id ); } /** * Saves an MD5 hash checksum of the attachment file bytes in the attachment * post meta. This 32 character string can be used for file comparisons * while not taxing the server as much as other methods. * * @param int $post_id The post ID of the attachment. * @return void */ public static function save_meta_hash( $post_id ) { // Save a md5 hash checksum of the attachment in meta. $file_path = get_attached_file( $post_id ); if ( false === $file_path ) { return; } update_post_meta( $post_id, apply_filters( 'invp_prefix_meta_key', 'hash' ), hash_file( 'md5', $file_path ) ); } /** * Saves a sequence number like 1, 2, or 99 in attachment post meta. This * number dictates the order in which the photos will be disabled in sliders * and galleries. * * @param int $post_id The post ID of the attachment. * @param int $parent_post_id The post ID of the vehicle to which $post_id is a child. * @param int $sequence_number The sequence number to save. Do not provide to append. * @return void */ public static function save_meta_photo_number( $post_id, $parent_post_id, $sequence_number = null ) { if ( null === $sequence_number ) { // Does this photo already have a sequence number? if ( ! empty( INVP::get_meta( 'photo_number', $post_id ) ) ) { // Yes. return; } // Is the number in the slug? // photo-5-of-19-of-vinsgsdkdkdkgf. $number = 0; if ( ! empty( $_POST['slug'] ) && preg_match( '/photo\-([0-9]+)\-of\-[0-9]+\-of\-.*/', sanitize_text_field( wp_unslash( $_POST['slug'] ) ), $matches ) ) { $number = intval( $matches[1] ); } else { /** * This hook fires after the attachment(s) are added, so the * vehicle may have 1 photo that is numbered, and the 3 that * were just added have the vehicle as a parent but do not have * number meta values. This request is for one of the 3, they * are all happening simultaneously. */ global $wpdb; $numbered_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( `{$wpdb->prefix}posts`.`ID` ) FROM `{$wpdb->prefix}postmeta` LEFT JOIN `{$wpdb->prefix}posts` ON `{$wpdb->prefix}posts`.`ID` = `{$wpdb->prefix}postmeta`.`post_id` WHERE `{$wpdb->prefix}posts`.`post_parent` = %d AND `post_type` = 'attachment' AND `meta_key` = %s", $parent_post_id, apply_filters( 'invp_prefix_meta_key', 'photo_number' ) ) ); // How many unnumbered photos does this vehicle have? $unnumbered_count = invp_get_the_photo_count( $parent_post_id ) - $numbered_count; if ( 1 < $unnumbered_count ) { /** * Abort. There are a couple unnumbered photos running this * method simultaneously. Let the photos remain unnumbered * until the user presses the Save Draft or Update button in * the editor. */ return; } $number = 1 + $numbered_count; if ( 1 === $number ) { // This is photo number 1, it should be the featured image. set_post_thumbnail( $parent_post_id, $post_id ); } } } else { $number = $sequence_number; } // Save the photo number in the photo's meta. if ( 0 !== $number ) { update_post_meta( $post_id, apply_filters( 'invp_prefix_meta_key', 'photo_number' ), $number ); } } /** * Saves the vehicle VIN in attachment meta when an attachment is uploaded * to a vehicle post. * * @param int $post_id The post ID of the attachment. * @param int $parent_post_id The post ID of the vehicle to which $post_id is a child. * @return void */ public static function save_meta_vin( $post_id, $parent_post_id ) { $vin = invp_get_the_VIN( $parent_post_id ); if ( empty( $vin ) ) { return; } update_post_meta( $post_id, apply_filters( 'invp_prefix_meta_key', 'vin' ), $vin ); } }
Expand full source codeCollapse full source codeView on Github
Methods Methods
- add_hooks — Adds hooks
- add_sequence_number_to_titles — Dynamically changes post titles of vehicle attachments in the dashboard to identify their sequence number.
- delete_photo_transients — Deletes transients that store vehicle photos to help load galleries.
- maybe_number_photo — Filter callback on add_attachment. Decides whether to write meta values on attachments if they are uploaded to vehicles. If this method determines the photo sequence number to be 1, the attachment is also set as the featured image.
- renumber_photos — Reassigns sequence numbers to all photos attached to a vehicle post.
- save_meta_hash — Saves an MD5 hash checksum of the attachment file bytes in the attachment post meta. This 32 character string can be used for file comparisons while not taxing the server as much as other methods.
- save_meta_photo_number — Saves a sequence number like 1, 2, or 99 in attachment post meta. This number dictates the order in which the photos will be disabled in sliders and galleries.
- save_meta_vin — Saves the vehicle VIN in attachment meta when an attachment is uploaded to a vehicle post.