From 41216278531a373a211a34b39075797a4c669d7a Mon Sep 17 00:00:00 2001 From: ryelle Date: Thu, 23 Jul 2015 16:06:31 -0400 Subject: [PATCH 1/2] Add CLI file with scaffolded CLI command `wp respimg add-srcset`. --- class-cli-command.php | 22 ++++++++++++++++++++++ wp-tevko-responsive-images.php | 4 ++++ 2 files changed, 26 insertions(+) create mode 100644 class-cli-command.php diff --git a/class-cli-command.php b/class-cli-command.php new file mode 100644 index 0000000..1cca586 --- /dev/null +++ b/class-cli-command.php @@ -0,0 +1,22 @@ + tags to use srcset. + * + * ## OPTIONS + * + * [--dry-run] + * : Don't save anything, just return stats about potential changes + * + * @subcommand add-srcset + */ + function add_srcset( $args, $assoc_args ) { + WP_CLI::success( "Command works!" ); + } +} + +WP_CLI::add_command( 'respimg', 'ResponsiveImagesCLI' ); diff --git a/wp-tevko-responsive-images.php b/wp-tevko-responsive-images.php index b75b5eb..da5e976 100644 --- a/wp-tevko-responsive-images.php +++ b/wp-tevko-responsive-images.php @@ -21,6 +21,10 @@ require_once plugin_dir_path( __FILE__ ) . 'class-respimg.php'; require_once plugin_dir_path( __FILE__ ) . 'class-wp-image-editor-respimg.php'; +if ( defined('WP_CLI') && WP_CLI ) { + require_once( __DIR__ . '/class-cli-command.php' ); +} + /** * Enqueue bundled version of the Picturefill library. */ From 5b1c9fc3d9552d9431391322436f75bdcdc022de Mon Sep 17 00:00:00 2001 From: ryelle Date: Thu, 23 Jul 2015 16:06:58 -0400 Subject: [PATCH 2/2] First pass at `wp respimg add-srcset` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses DOMDocument to find images, then pulls the image ID from the `wp-image-*` class (could switch to whatever content filtering is used for #144, so we’re not reliant on something that might be disabled). Generate the srcset, add it to the image tag, and update the post. --- class-cli-command.php | 142 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/class-cli-command.php b/class-cli-command.php index 1cca586..d435239 100644 --- a/class-cli-command.php +++ b/class-cli-command.php @@ -9,13 +9,153 @@ class ResponsiveImagesCLI extends WP_CLI_Command { * * ## OPTIONS * + * [...] + * : One or more post IDs to convert + * * [--dry-run] * : Don't save anything, just return stats about potential changes * * @subcommand add-srcset */ function add_srcset( $args, $assoc_args ) { - WP_CLI::success( "Command works!" ); + global $wpdb; + $dry_run = \WP_CLI\Utils\get_flag_value( $assoc_args, 'dry-run' ); + $posts = array_map( 'intval', $args ); + $posts = array_filter( $posts ); + + if ( ! class_exists( 'DOMDocument' ) ) { + WP_CLI::error( 'This functionality requires DOMDocument.' ); + } + + if ( ! $posts ){ + $post_types = $this->get_enabled_post_types(); + $post_statuses = $this->get_skipped_post_status(); + + $posts = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_type IN ($post_types) AND post_status NOT IN ($post_statuses);" ); + } + + $count = 0; + foreach ( $posts as $post_id ) { + $post = get_post( $post_id ); + if ( ! $post ) { + continue; + } + $original_content = $post->post_content; + + // Save a revision right before updating (if necessary, `wp_save_post_revision` + // won't save if the post == the last revision) + if ( ! $dry_run ) { + wp_save_post_revision( $post_id ); + } + + // Parse the content for any local s. + $updated_content = $original_content; + + $doc = new DOMDocument(); + @$doc->loadHTML( $updated_content ); + $images = $doc->getElementsByTagName('img'); + + $old_imgs = $new_imgs = array(); + foreach ( $images as $img ) { + if ( $img->hasAttribute( 'srcset' ) ) { + continue; + } + $old = 'src="' . $img->getAttribute('src') .'"'; + $new = false; + + $attachment_id = false; + $size = 'medium'; + if ( $img->hasAttribute('class') ) { + $class = $img->getAttribute('class'); + if ( preg_match( '/wp-image-(\d*)/i', $class, $matches ) ){ + $attachment_id = intval( $matches[1] ); + } + if ( preg_match( '/size-(\S*)/i', $class, $matches ) ){ + $size = $matches[1]; + } + } + if ( $attachment_id && $size ) { + $srcset = tevkori_get_srcset_array( $attachment_id, $size ); + if ( ! is_array( $srcset ) ) { + continue; + } + + $srcset = implode( ', ', $srcset ); + $new = $old . ' srcset="' . $srcset . '"'; + + if ( $img->hasAttribute('width') ) { + $data = wp_get_attachment_image_src( $attachment_id, $size ); + $new .= ' width="' . $data[1] . '"'; + } + + if ( $img->hasAttribute('height') ) { + $data = wp_get_attachment_image_src( $attachment_id, $size ); + $new .= ' height="' . $data[2] . '"'; + } + } + + // Make sure we have a new image before adding to our replacement array + if ( $new ) { + $old_imgs[] = $old; + $new_imgs[] = $new; + } + } + + $updated_content = str_replace( $old_imgs, $new_imgs, $original_content ); + + // Save if we've changed anything + if ( $updated_content != $original_content ) { + $result = false; + + if ( ! $dry_run ) { + // Something is unsetting publish and title?? + $result = wp_update_post( array( + 'ID' => $post_id, + 'post_content' => $updated_content, + ) ); + if ( $result ) { + $count++; + } + } else { + $count++; + } + WP_CLI::line( sprintf( '%s %s [%s] was updated, srcset was added to %s images.', $post->post_type, $post->post_title, $post_id, count( $new_imgs ) ) ); + } + } + + if ( ! $dry_run ) { + WP_CLI::success( sprintf( "%s posts were updated.", $count ) ); + } else { + WP_CLI::success( sprintf( "%s posts can be updated. Run again without --dry-run to update them.", $count ) ); + } + } + + /** + * Return user-facing post types which should be filtered. + */ + protected function get_enabled_post_types(){ + $post_types = get_post_types(array( + 'public' => true, + )); + if ( ! is_array( $post_types ) ) { + return ''; + } + + // Don't process attachments + unset( $post_types['attachment'] ); + + $post_types = apply_filters( 'respimg_cli_enabled_post_types', $post_types ); + + return "'" . implode( "', '", $post_types ) . "'"; + } + + /** + * Return the post statuses we should skip + */ + protected function get_skipped_post_status(){ + $status = apply_filters( 'respimg_cli_skipped_status', array( 'auto-draft', 'inherit', 'trash' ) ); + + return "'" . implode( "', '", $status ) . "'"; } }