From 5febb68e198787ff16aa2c70f19a3ed2d30c9284 Mon Sep 17 00:00:00 2001
From: lucha <lucha@paranoici.org>
Date: Wed, 17 Aug 2016 17:43:22 +0200
Subject: [PATCH] command to convert NGG galleries to standard Wordpress ones

---
 bin/noblogs.in |  21 +++++
 lib/ngg.php    | 242 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 263 insertions(+)
 create mode 100644 lib/ngg.php

diff --git a/bin/noblogs.in b/bin/noblogs.in
index 05fd9a7..d7e9e41 100755
--- a/bin/noblogs.in
+++ b/bin/noblogs.in
@@ -68,6 +68,10 @@ Known commands:
       Set read-only mode for the local noblogs installation. The argument
       must be either the literal 'on' or 'off'.
 
+  ngg-convert BLOG
+      Convert Next Gen Gallery (NGG) photo galleries to stardard Wordpress
+      galleries, and then notify (via email) admins of the fact.
+
 <?php
   exit(1);
 }
@@ -415,6 +419,23 @@ function do_set_readonly($args) {
 }
 
 
+function do_ngg_convert($args) {
+    require_once(dirname(__FILE__) . '/ngg.php');
+    foreach ($args as $arg) {
+    $blog = noblogs_get_blog($arg);
+    if (!$blog) {
+      echo "Blog {$arg} not found.\n";
+      continue;
+    }
+    switch_to_blog($blog->blog_id);
+    echo "Converting blog ${arg}: \n";
+    $post_ids = ngg_convert();
+    ngg_alert_admin($post_ids);
+    restore_current_blog();
+  }
+}
+
+
 // Command-line parsing.
 $cmd = $argv[1];
 if (!$cmd) {
diff --git a/lib/ngg.php b/lib/ngg.php
new file mode 100644
index 0000000..63cf2ff
--- /dev/null
+++ b/lib/ngg.php
@@ -0,0 +1,242 @@
+<?php
+
+require_once(NOBLOGS_ROOT . '/wp-admin/includes/media.php');
+require_once(NOBLOGS_ROOT . '/wp-admin/includes/file.php');
+require_once(NOBLOGS_ROOT . '/wp-admin/includes/image.php');
+
+function ngg_get_post_ids( $limit = -1 ) {
+	$args = array(
+		's'           => '[nggallery',
+		'post_type'   => array( 'post', 'page' ),
+		'post_status' => 'any',
+		'nopaging'    => true,
+		'fields'      => 'ids',
+		'posts_per_page' => $limit
+	);
+
+	$query = new WP_Query( $args );
+	return $query->posts;
+}
+
+function do_ngg_count($args) {
+	foreach ($args as $arg) {
+    $blog = noblogs_get_blog($arg);
+    if (!$blog) {
+      echo "Blog {$arg} not found.\n";
+      continue;
+    }
+    switch_to_blog($blog->blog_id);
+    $post_ids = ngg_get_post_ids();
+    $count = count($post_ids);
+    echo "${arg} : ${count} \n";
+    foreach ( $post_ids as $post_id ) {
+    	$post = get_post( $post_id );
+    	$gallery_count = count(ngg_find_gallery_shortcodes($post));
+    	echo "\t ${post_id}: ${gallery_count} \n";
+    }
+    restore_current_blog();
+  }
+}
+
+function ngg_upload_image($post, $path, $image){
+	$url = home_url( trailingslashit( $path ) . $image->filename );
+	// Let's use a hash trick here to find our attachment post after it's been sideloaded.
+	$hash = md5( 'attachment-hash' . $url . $image->description . time() . rand( 1, 999 ) );
+	$result = media_sideload_image( $url, $post->ID, $hash );
+	if ( is_wp_error( $result ) ) {
+		echo sprintf( "Error loading %s: %s\n", $url, $result->get_error_message() );
+		return;
+	} else {
+		$attachments = get_posts( array(
+			'post_parent' => $post->ID,
+			's' => $hash,
+			'post_type' => 'attachment',
+			'posts_per_page' => -1,
+		) );
+
+		if ( ! $attachments || ! is_array( $attachments ) || count( $attachments ) != 1 ) {
+			echo sprintf( "Error: Could not insert attachment for %d\n", $post->ID );
+			return;
+		}
+	}
+	return $attachments[0];
+}
+
+function ngg_upload_gallery($post,$gallery_id){
+	global $wpdb;
+	$path = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}ngg_gallery WHERE gid = ". intval( $gallery_id ), ARRAY_A  );
+	$images = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}ngg_pictures WHERE galleryid = ". intval( $gallery_id ) . " ORDER BY sortorder, pid ASC" );
+
+	if ( ! $path || ! $images ) {
+		echo sprintf( "Warning: Could not find images for nggallery %d\n", $gallery_id );
+		return;
+	}
+	$attached_images = [];
+
+	foreach ( $images as $image ) {
+		$attachment = ngg_upload_image($post, $path['path'], $image);
+
+		// Titles should fallback to the filename.
+		if ( ! trim( $image->alttext ) ) {
+			$image->alttext = $image->filename;
+		}
+
+		$attachment->post_title = $image->alttext;
+		$attachment->post_content = $image->description;
+		$attachment->menu_order = $image->sortorder;
+
+		update_post_meta( $attachment->ID, '_wp_attachment_image_alt', $image->alttext );
+
+		wp_update_post( $attachment );
+		$attached_images[] = $attachment->ID;
+		echo sprintf( "Log: Added attachment %d for post %d \n", $attachment->ID, $post->ID );
+	}
+	return array( $images, $attached_images );
+}
+
+// If there are existing images attached the post,
+// let's remember to exclude them from our new gallery.
+function ngg_exclude_existing_attachments($post_ID){
+	$existing_attachments_ids = get_posts( array(
+			'post_type' => 'attachment',
+			'post_status' => 'inherit',
+			'post_parent' => $post_ID,
+			'post_mime_type' => 'image',
+			'fields' => 'ids',
+		) );
+
+	$attr = array();
+	if ( $existing_attachments_ids )
+		$attr['exclude'] = implode( ',', $existing_attachments_ids );
+
+	return $attr;
+}
+
+function ngg_find_gallery_shortcodes($post){
+	$matches = null;
+	preg_match_all( '/\[nggallery.*?\]/si', $post->post_content, $matches );
+	return $matches[0];
+}
+
+function ngg_parse_shortcode($shortcode){
+	$atts = shortcode_parse_atts($shortcode);
+	return intval( $atts['id'] );
+}
+
+function ngg_convert() {
+	global $wpdb;
+	$uploads = wp_upload_dir();
+	$baseurl = $uploads['baseurl'];
+	$posts_count = 0;
+	$gallery_count = 0;
+	$images_count = 0;
+	$blog_id =  get_current_blog_id();
+
+	$post_ids = ngg_get_post_ids();
+	foreach ( $post_ids as $post_id ) {
+		$post = get_post( $post_id );
+		$matches = null;
+
+		// If there are existing images attached the post,
+		// let's remember to exclude them from our new gallery.
+		$code_attr = ngg_exclude_existing_attachments($post->ID);
+
+		foreach ( ngg_find_gallery_shortcodes($post)  as $shortcode ){
+			$gallery_id = ngg_parse_shortcode($shortcode);
+
+			list ($gallery_images, $attached_images) = ngg_upload_gallery($post, $gallery_id);
+
+			if ( count($gallery_images) != count($attached_images) ) {
+				echo "Not replacing ${shortcode}. ";
+				echo sprintf("%d of %d images converted.\n", count($attached_images), count($gallery_images));
+				continue;
+			}
+
+			// Construct the [gallery] shortcode
+			$code_attr['ids'] = implode(',', $attached_images);
+			$new_shortcode = '[gallery';
+			foreach ( $code_attr as $key => $value )
+				$new_shortcode .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
+			$new_shortcode .= ']';
+
+			$post->post_content = str_replace( $shortcode, $new_shortcode, $post->post_content );
+			echo sprintf( "Log: Blog id %d. Updated gallery id %d of post %d \n",  $blog_id, $gallery_id, $post->ID );
+			$images_count += count($attached_images);
+			$gallery_count++;
+		}
+
+		// Booyaga!
+		wp_update_post( $post );
+		$posts_count++;
+	}
+
+	echo "Log: Converted ${posts_count} posts, ${gallery_count} galleries and ${images_count} images \n";
+	return $post_ids;
+}
+
+function ngg_alert_admin($post_ids = null) {
+	if (!$post_ids){
+		$post_ids = ngg_get_post_ids();
+	}
+	$posts_count = count($post_ids);
+
+	$blog_id =  get_current_blog_id();
+	$blog_name = get_bloginfo('name');
+	if (!$blog_name){
+		$blog_name = home_url();
+	}
+	$blog_url = site_url();
+	$admin_email = get_bloginfo('admin_email');
+	$admin_user = get_user_by( 'email', $admin_email);
+	$admin_name = $admin_user->user_nicename;
+	if (!$admin_name){
+		$admin_name = $admin_email;
+	}
+
+	$post_list = "";
+	foreach ( $post_ids as $post_id ) {
+		$post_title = get_post($post_id)->post_title;
+		$post_url = get_permalink($post_id);
+		$post_list = $post_list . "${post_title}: ${post_url} \n";
+	}
+
+	$mail_body = <<<EOT
+Dear ${admin_name},
+you are receiving this message because your are the admin of the blog "${blog_name}"
+${blog_url}
+
+We are in the process of removing the NextGen Gallery Plugin and converting all existing
+image galleries to the standard Wordpress media manager.
+
+In your blog, we have found that the following posts include NextGen Galleries that should
+have been converted:
+${post_list}
+If everything went well, you do not have to do anything at all.
+Please check that the images are showing correctly, and let us know if something went wrong.
+
+with love and +kaos
+Autistici/Inventati
+-------------------
+
+Caro ${admin_name},
+ricevi questa email perché sei l'amministratore del blog "${blog_name}"
+${blog_url}
+
+Stiamo per rimuovere il plugin NextGen Gallery e abbiamo trasferito tutte le gallerie
+di immagini al gestore di media di Wordpress.
+
+Nel tuo blog, ci sono i seguenti posts che includevano gallerie di NextGen e che sono
+state convertite:
+${post_list}
+Se è andato tutto a buon fine, non devi fare nient'altro.
+Controlla che le immagini si visualizzano correttamente, e facci sapere se c'è qualcosa
+che non va.
+
+con amore e +kaos
+Autistici/Inventati
+
+EOT;
+	echo "Sending email to ${admin_email} \n";
+	wp_mail($admin_email, "[Noblogs] Removing NextGen Gallery Plugin",
+		$mail_body, 'From: Autistici/Inventati <info@autistici.org>' . "\r\n");
+}
-- 
GitLab