Skip to content

Commit

Permalink
groups migration
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh Kadis committed Dec 29, 2016
1 parent 4f5b7b0 commit c42e8b1
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ vendor/
*.tar.gz
hugo-content
hugo-images
hugo-groups
geo-api-token.txt
# STDOUT files
html_text.txt
html_tags.txt
20 changes: 15 additions & 5 deletions command.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
require_once( HH_HUGO_COMMAND_DIR . '/inc/process-wp-post-content.php' );
require_once( HH_HUGO_COMMAND_DIR . '/inc/migrate-images.php' );
require_once( HH_HUGO_COMMAND_DIR . '/inc/migrate-post.php' );
require_once( HH_HUGO_COMMAND_DIR . '/inc/migrate-group.php' );


if ( ! class_exists( 'WP_CLI' ) ) {
Expand Down Expand Up @@ -210,7 +211,7 @@ function markdown( $args ) {
function delete_content_dirs( $args, $assoc_args ) {
WP_CLI::confirm( 'Are you sure you want to delete the hugo-content and hugo-images directories?' );

foreach( array( 'hugo-content', 'hugo-images' ) as $dir ) {
foreach( array( 'hugo-content', 'hugo-images', 'hugo-groups' ) as $dir ) {
$path = trailingslashit( HH_HUGO_COMMAND_DIR ) . $dir;
if ( is_dir( $path ) ) {
exec( 'rm -rf ' . escapeshellarg( $path ) );
Expand All @@ -228,6 +229,9 @@ function delete_content_dirs( $args, $assoc_args ) {
* <id>
* : WordPress post ID or slug, or comma-separated list of IDs/slugs
*
* [--parent=<id>]
* : Override hard-coded groups parent page ID
*
* [--dry-run]
* : Simulate without touching any Markdown files or images
*
Expand All @@ -237,12 +241,19 @@ function delete_content_dirs( $args, $assoc_args ) {
*/
function migrate_group( $args, $assoc_args ) {
$dry_run = isset( $assoc_args['dry-run'] );
$parent_id = is_numeric( $assoc_args['parent'] ) ? intval( $assoc_args['parent'] ) : $this->groups_parent_page_id;

// Convert to array
$groups = explode( ',', $args[0] );
// Convert to array if needed
if ( is_string( $args[0] ) ) {
$groups = explode( ',', $args[0] );
} else {
$groups = array( $args[0] );
}

foreach ( $groups as $group ) {
$migrated = new HH_Hugo\Migrate_Group( $group, $dry_run );
// $group could be post ID, post_name, or WP_Post object
$migrated = new HH_Hugo\Migrate_Group( $group, $parent_id, $dry_run );
$result = $migrated->result();

// $result will be in format like array( 'success' => 'message' )
if ( 'success' === array_keys( $result )[0] ) {
Expand Down Expand Up @@ -276,7 +287,6 @@ function migrate_all_groups( $args, $assoc_args ) {
$parent_id = is_numeric( $assoc_args['parent'] ) ? intval( $assoc_args['parent'] ) : $this->groups_parent_page_id;

$this->query = new WP_Query( array(
'fields' => 'ids',
'posts_per_page' => 500,
'post_type' => 'page',
'post_status' => 'publish',
Expand Down
207 changes: 207 additions & 0 deletions inc/migrate-group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
<?php
/**
* Migrate groups from WordPress to Hugo data as YAML
*/
namespace HH_Hugo;

class Migrate_Group {

/**
* @var WP_Post WordPress post object to migrate
*/
protected $page = null;

/**
* @var string Geocoding API with placeholder for city name
*/
protected $geo_api_url = 'https://api.mapbox.com/geocoding/v5/mapbox.places/%s.json?access_token=%s';

/**
* Instantiate and migrate
*
* @param string|int|WP_Post $group WordPress post ID or slug or WP_Post
* @param int $parent_id ID of WordPress parent page
* @param bool $dry_run If true, mock migration only. Defaults to false.
*/
function __construct( $group, $parent_id = 0, $dry_run = false ) {
$content_dir = defined( 'HH_HUGO_UNIT_TESTS_RUNNING' ) ? 'hugo-groups-test' : 'hugo-groups';
$this->dest_dir = trailingslashit( HH_HUGO_COMMAND_DIR ) . $content_dir;

// just return the class for unit testing
if ( empty( $group ) && defined( 'HH_HUGO_UNIT_TESTS_RUNNING' ) ) {
return;
}

$is_wp_post = is_object( $group ) && 'WP_Post' === get_class( $group );
$this->page = $is_wp_post ? $group : $this->get_page( $group, $parent_id );

$this->data = $this->setup_data( $this->page->ID );
$this->filename = sanitize_title( $this->page->post_title ) . '.yml';

if ( ! $dry_run ) {
$written = $this->write_file( $this->filename, $this->data );
if ( ! $written ) {
$this->result = array( 'error' => 'Error writing file: ' . $this->filename );
return;
}
}
$this->result = array( 'success' => 'Migrated ' . $this->filename );
}

/**
* Instantiate and migrate
*
* @param string|int $group WordPress post ID or slug
* @param int $parent_id ID of WordPress parent page
* @return WP_Post
*/
public function get_page( $group, $parent_id ) {
$args = array(
'numberposts' => 1,
'post_type' => 'page',
'post_status' => 'publish',
'post_parent' => $parent_id,
);

if ( is_numeric( $group ) ) {
$args['page_id'] = intval( $group );
} else {
$args['name'] = $group;
}

$pages = get_posts( $args );
if ( empty( $pages ) ) {
$this->result = array( 'error' => 'Could not find group page for: ' . $group );
return null;
}

return $pages[0];
}

/**
* Setup data for conversion to YAML
*
* @param int $page Page ID to migrate
* @return array
*/
public function setup_data( $page_id ) {
$title = get_the_title( $page_id );
$data = array(
'label' => $title,
);

if ( $coordinates = $this->get_coordinates( $title ) ) {
$data['coordinates'] = $coordinates;
}

if ( $external_url = $this->get_external_url( $page_id ) ) {
$data['externalUrl'] = $external_url;
}

return $data;
}

/**
* Turn city / post title into search query
*
* @param string $city
* @return string
*/
public function city_search( $city ) {
$city = preg_replace( '/[^\w]+/', '+', strtolower( $city ) );
return trim( $city, '+' );
}

/**
* Get lat,lon for city name
*
* @param string $city
* @return null|array Lat,Lon array or null if failure
*/
public function get_coordinates( $city ) {
$token_path = trailingslashit( HH_HUGO_COMMAND_DIR ) . 'geo-api-token.txt';
if ( ! file_exists( $token_path ) ) {
return null;
}
$token = file_get_contents( $token_path );
if ( empty( $token ) ) {
return null;
}

$request_url = sprintf( $this->geo_api_url, $this->city_search( $city ), $token );
$response = wp_remote_get( $request_url );

if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
return null;
}

$body = json_decode( wp_remote_retrieve_body( $response ), true );

if ( empty( $body['features'][0]['center'] ) ) {
return null;
}

// Carmen GeoJSON provides [lon, lat] but Leaflet.js wants [lat, lon]
return array_reverse( $body['features'][0]['center'] );
}

/**
* Get external URL from options stored in Simple 301 Redirects plugin
*
* @param int $page_id
* @return string|null URL or null if not found
*/
public function get_external_url( $page_id ) {
$redirects = get_option( '301_redirects', array() );

// search in redirects with and without leading slash
$uri = get_page_uri( $page_id );
if ( ! empty( $redirects[ $uri ] ) ) {
return $redirects[ $uri ];
}

if ( ! empty( $redirects[ '/' . $uri ] ) ) {
return $redirects[ '/' . $uri ];
}

return null;
}

/**
* Emit yaml with a little bit of processing for Hugo's sake
*
* @param array $data Group data
* @return string YAML data
*/
public function get_yaml( $data ) {
$yaml = yaml_emit( $data, YAML_UTF8_ENCODING );
return trim( preg_replace( array( '/^-+\n/', '/\.+$/'), '', $yaml ) );
}

/**
* Write group data file
*
* @param string $filename
* @param array $data
* @return bool
*/
public function write_file( $filename, $data ) {
if ( ! is_dir( $this->dest_dir ) ) {
mkdir( $this->dest_dir, 0755, true );
}

return file_put_contents(
trailingslashit( $this->dest_dir ) . $filename,
$this->get_yaml( $data )
);
}

/**
* Getter for migration results
*
* @return array
*/
public function result() {
return $this->result;
}
}
68 changes: 68 additions & 0 deletions tests/test-migrate-group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
class HH_Hugo_Test_Migrate_Group extends WP_UnitTestCase {
function setUp() {
$this->migrator = new HH_Hugo\Migrate_Group( null );

$this->parent_post = wp_insert_post( array(
'post_title' => 'Local Groups',
'post_name' => 'chapters',
'post_type' => 'page',
'post_status' => 'publish',
) );

$this->group_post = wp_insert_post( array(
'post_title' => 'Atlanta',
'post_name' => 'atlanta',
'post_type' => 'page',
'post_status' => 'publish',
'post_parent' => $this->parent_post,
) );

update_option( '301_redirects', array( '/chapters/atlanta' => 'https://www.meetup.com/HacksHackersATL/' ) );
}

function tearDown() {
wp_delete_post( $this->parent_post, true );
wp_delete_post( $this->group_post, true );
}

/**
* Get contents of test data file
*
* @param string $type 'test' or 'expect'
* @param string $filename
* @return string Contents of file
*/
private function _get_test_data( $type, $filename ) {
return file_get_contents( HH_HUGO_COMMAND_DIR . '/tests/data/' . $type . '/' . $filename );
}

public function test_setup_data() {
$expect = array(
'label' => 'Atlanta',
'coordinates' => array( 33.749100, -84.390200 ),
'externalUrl' => 'https://www.meetup.com/HacksHackersATL/'
);
$this->assertEquals( $expect, $this->migrator->setup_data( $this->group_post ) );
}

public function test_get_yaml() {
$data = $this->migrator->setup_data( $this->group_post );
$actual = $this->migrator->get_yaml( $data );
$expected = "label: Atlanta\ncoordinates:\n- 33.749100\n- -84.390200\nexternalUrl: https://www.meetup.com/HacksHackersATL/";
$this->assertEquals( $expected, $actual );
}

public function test_city_search() {
$tests = array(
array( 'Atlanta', 'atlanta' ),
array( 'Mexico City', 'mexico+city' ),
array( 'Raleigh/Durham', 'raleigh+durham' ),
array( 'Amman, Jordan', 'amman+jordan' ),
array( 'Research Triangle (Chapel Hill/Durham/Raleigh, N.C.)', 'research+triangle+chapel+hill+durham+raleigh+n+c' ),
);
foreach ( $tests as $test ) {
$this->assertEquals( $test[1], $this->migrator->city_search( $test[0] ) );
}
}
}

0 comments on commit c42e8b1

Please sign in to comment.