WordPress Tech: Converting “Multi Part Posts” to “Organize Series”

For the very limited audience that used the “Multi Part Posts” plugin to organize your WordPress posts, you will be impacted when this plugin someday stops working, as the author has removed it.  It already had some incompatibilities with WordPress 3.9.8, which would prevent the New Post page from rendering in some cases.

After some research, I concluded that the “Organize Series” plugin was the next best choice to meet my needs.  The question became, how to convert from “Multi Part Posts” to “Organize Series” ?

I developed the following approach, which worked for me…

NOTE:  each table will have a prefix defined when you set up wordpress.  replace wp_ with whatever you used

 

AS-IS: “Multi Part Posts”

Each post that is part of a series is referenced in 2 entries in table “wp_postmeta”. Focus on post_id 1024 in this example:

(25835,1024,’enable_multi_part’,’enabled’)

(25818,1015,’multi_part_data’,'[1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038]’)

where the fields are:
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL DEFAULT ‘0’,
`meta_key` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meta_value` longtext COLLATE utf8mb4_unicode_ci,

The first entry (‘enable_multi_part’) is inconsequential in my use of “Multi Part Posts”, as I never disabled it for a post. Unlike “Organize Series”, there are no names for “Multi Part Posts” series. The ‘meta_value’ array in the second entry (‘multi_part_data’) contains all the posts that are part of the series, in the order they must appear. It’s that simple.

Note that the same meta_value is repeated for as many posts are in the series, so it’s critical to purge duplicates! For example, my system had 1843 multi_part_data entries, but only
128 of them were unique series.

TO-BE: “Organize Series”

Each series is ‘registered’ in two tables:

wp_terms

`term_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ”,
`slug` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ”,
`term_group` bigint(10) NOT NULL DEFAULT ‘0’,

Example: (41,’manageseries-name’,’manageseries-slug’,0)
Note: the name and slug can be the same

wp_term_taxonomy

`term_taxonomy_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`term_id` bigint(20) unsigned NOT NULL DEFAULT ‘0’,
`taxonomy` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ”,
`description` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`parent` bigint(20) unsigned NOT NULL DEFAULT ‘0’,
`count` bigint(20) NOT NULL DEFAULT ‘0’,

Example: (41,41,’series’,”,0,2)

Since both tables are auto-incrementing, the next entry would be (42,42,’series’,”,0,0)

Articles that are a member of a series are noted in a third table:

wp_term_relationships

`object_id` bigint(20) unsigned NOT NULL DEFAULT ‘0’,
`term_taxonomy_id` bigint(20) unsigned NOT NULL DEFAULT ‘0’,
`term_order` int(11) NOT NULL DEFAULT ‘0’,

Note that the object_id is the new container for post_id from “Multi Part Posts”

Example: (14829,41,0),(14828,41,0)

HOW-TO: Convert from “Multi Part Posts” to “Organize Series”

0. mysqldump -u username -p database_name > data-dump.sql
1. Parse all ‘multi_part_data’ arrays from wp_postmeta, purging duplicates
2. Create a wp_terms entry for each array
a. name and slug can be obtained from an incrementing counter
3. Create a wp_term_taxonomy entry for each array
a. the auto-assigned term_id from wp_terms is used
b. taxonomy is ‘series’
c. description is left blank
d. parent is hardcoded to zero
e. the count is set to the sum of posts in the series
4. Iterate on each array to make a wp_term_relationships value entry for each object_id
a. the object_id is the post_id from “Multi Part Posts”
b. the auto-assigned term_taxonomy_id is fed to the wp_term_relationships term_taxonomy_id
c. hardcode the term_order to zero

 

Here is an example script that runs steps 1-4 after you’ve done step 0:

#/bin/ksh

#multi-part2series.ksh

let cnt=1
for series in `grep “INSERT INTO .gas_postmeta.” data-dump.sql | tr ‘(‘ “\n” | grep multi_part_data | cut -d”)” -f1 | cut -d”‘” -f4 | sort | sort -u | sed ‘s/^\[//’ | sed ‘s/\]$//’`
do
echo “–$cnt”
echo “INSERT INTO gas_terms VALUES (NULL,’article $cnt’,’article $cnt’,0);”
posts=`echo $series | tr ‘,’ “\n” | wc -l`
echo “INSERT INTO gas_term_taxonomy VALUES (NULL,LAST_INSERT_ID(),’series’,”,0,$posts);”

oldIFS=$IFS
IFS=”,”
for post_id in $series
do
echo “INSERT INTO gas_term_relationships VALUES ($post_id,LAST_INSERT_ID(),0);”
done
IFS=$oldIFS

((cnt=cnt+1))
done

Run the script as: ​./multi-part2series.ksh >test.sql 

Once the script runs, back up your database, review the SQL, and decide if you want to proceed. 
If so, run something like this: mysql -u <user> -p<pass> <database> < test.sql 

It runs fast. 

If you get no errors, check your series to see if "Organize Series" is presenting them correctly. Adjust as needed. 

Enjoy!