diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh new file mode 100755 index 000000000..9f009876b --- /dev/null +++ b/bin/install-wp-tests.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash + +if [ $# -lt 3 ]; then + echo "usage: $0 [db-host] [wp-version]" + exit 1 +fi + +DB_NAME=$1 +DB_USER=$2 +DB_PASS=$3 +DB_HOST=${4-localhost} +WP_VERSION=${5-latest} + +WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} +WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} + +download() { + if [ `which curl` ]; then + curl -s "$1" > "$2"; + elif [ `which wget` ]; then + wget -nv -O "$2" "$1" + fi +} + +if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then + WP_TESTS_TAG="tags/$WP_VERSION" +else + # http serves a single offer, whereas https serves multiple + download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json + grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json + LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') + if [[ -z "$LATEST_VERSION" ]]; then + echo "Latest WordPress version could not be found" + exit 1 + fi + WP_TESTS_TAG="tags/$LATEST_VERSION" +fi + +set -ex + +install_wp() { + + if [ -d $WP_CORE_DIR ]; then + return; + fi + + mkdir -p $WP_CORE_DIR + + if [ $WP_VERSION == 'latest' ]; then + local ARCHIVE_NAME='latest' + else + local ARCHIVE_NAME="wordpress-$WP_VERSION" + fi + + download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz + tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR + + download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php +} + +install_test_suite() { + # portable in-place argument for both GNU sed and Mac OSX sed + if [[ $(uname -s) == 'Darwin' ]]; then + local ioption='-i .bak' + else + local ioption='-i' + fi + + # set up testing suite if it doesn't yet exist + if [ ! -d $WP_TESTS_DIR ]; then + # set up testing suite + mkdir -p $WP_TESTS_DIR + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + fi + + cd $WP_TESTS_DIR + + if [ ! -f wp-tests-config.php ]; then + download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php + fi + +} + +install_db() { + # parse DB_HOST for port or socket references + local PARTS=(${DB_HOST//\:/ }) + local DB_HOSTNAME=${PARTS[0]}; + local DB_SOCK_OR_PORT=${PARTS[1]}; + local EXTRA="" + + if ! [ -z $DB_HOSTNAME ] ; then + if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then + EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" + elif ! [ -z $DB_SOCK_OR_PORT ] ; then + EXTRA=" --socket=$DB_SOCK_OR_PORT" + elif ! [ -z $DB_HOSTNAME ] ; then + EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" + fi + fi + + # create database + mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA +} + +install_wp +install_test_suite +install_db diff --git a/includes/msm-sitemap-builder-cron.php b/includes/msm-sitemap-builder-cron.php index 2a43637ff..a2bcf5c86 100644 --- a/includes/msm-sitemap-builder-cron.php +++ b/includes/msm-sitemap-builder-cron.php @@ -305,6 +305,8 @@ public static function generate_sitemap_for_year_month_day( $args ) { $date_stamp = Metro_Sitemap::get_date_stamp( $year, $month, $day ); if ( Metro_Sitemap::date_range_has_posts( $date_stamp, $date_stamp ) ) { Metro_Sitemap::generate_sitemap_for_date( $date_stamp ); + } else { + Metro_Sitemap::delete_sitemap_for_date( $date_stamp ); } self::find_next_day_to_process( $year, $month, $day ); diff --git a/includes/wp-cli.php b/includes/wp-cli.php index 7e31a9041..9b2fbda5b 100644 --- a/includes/wp-cli.php +++ b/includes/wp-cli.php @@ -148,6 +148,8 @@ function generate_sitemap_for_year_month_day( $args, $assoc_args ) { $date_stamp = Metro_Sitemap::get_date_stamp( $year, $month, $day ); if ( Metro_Sitemap::date_range_has_posts( $date_stamp, $date_stamp ) ) { Metro_Sitemap::generate_sitemap_for_date( $date_stamp ); // TODO: simplify; this function should accept the year, month, day and translate accordingly + } else { + Metro_Sitemap::delete_sitemap_for_date( $date_stamp ); } } diff --git a/msm-sitemap.php b/msm-sitemap.php index fd7a6fb92..be0389c32 100644 --- a/msm-sitemap.php +++ b/msm-sitemap.php @@ -395,10 +395,7 @@ public static function generate_sitemap_for_date( $sitemap_date ) { if ( ! $post_count ) { // If no entries - delete the whole sitemap post if ( $sitemap_exists ) { - $total_url_count -= intval( get_post_meta( $sitemap_id, 'msm_indexed_url_count', true ) ); - update_option( 'msm_sitemap_indexed_url_count' , $total_url_count ); - wp_delete_post( $sitemap_id, true ); - do_action( 'msm_delete_sitemap_post', $sitemap_id, $year, $month, $day ); + self::delete_sitemap_by_id( $sitemap_id ); } return; } @@ -468,6 +465,32 @@ public static function generate_sitemap_for_date( $sitemap_date ) { wp_reset_postdata(); } + public static function delete_sitemap_for_date( $sitemap_date ) { + list( $year, $month, $day ) = explode( '-', $sitemap_date ); + $sitemap_id = self::get_sitemap_post_id( $year, $month, $day ); + if ( ! $sitemap_id ) { + return false; + } + return self::delete_sitemap_by_id( $sitemap_id ); + } + + public static function delete_sitemap_by_id( $sitemap_id ) { + $sitemap = get_post( $sitemap_id ); + if ( ! $sitemap ) { + return false; + } + + $sitemap_date = date( 'Y-m-d', strtotime( $sitemap->post_date ) ); + list( $year, $month, $day ) = explode( '-', $sitemap_date ); + + $total_url_count = self::get_total_indexed_url_count(); + $total_url_count -= intval( get_post_meta( $sitemap_id, 'msm_indexed_url_count', true ) ); + update_option( 'msm_sitemap_indexed_url_count' , $total_url_count ); + + wp_delete_post( $sitemap_id, true ); + do_action( 'msm_delete_sitemap_post', $sitemap_id, $year, $month, $day ); + } + /** * Register our CPT */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 60068823b..4c9d30e08 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,19 +1,15 @@ array( 'msm-sitemap/msm-sitemap.php' ), -); -require getenv( 'WP_TESTS_DIR' ) . '/includes/bootstrap.php'; \ No newline at end of file +$_tests_dir = getenv( 'WP_TESTS_DIR' ); +if ( ! $_tests_dir ) { + $_tests_dir = '/tmp/wordpress-tests-lib'; +} + +require_once $_tests_dir . '/includes/functions.php'; + +function _manually_load_plugin() { + require dirname( dirname( __FILE__ ) ) . '/msm-sitemap.php'; +} +tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' ); + +require $_tests_dir . '/includes/bootstrap.php'; diff --git a/tests/test_sitemap_creation.php b/tests/test_sitemap_creation.php index 492b21a9f..75585e436 100644 --- a/tests/test_sitemap_creation.php +++ b/tests/test_sitemap_creation.php @@ -15,6 +15,11 @@ class WP_Test_Sitemap_Creation extends WP_UnitTestCase { * Generate posts and build the sitemap */ function setup() { + if ( ! class_exists( 'MSM_Sitemap_Builder_Cron' ) ) { + require dirname( dirname( __FILE__ ) ) . '/includes/msm-sitemap-builder-cron.php'; + MSM_Sitemap_Builder_Cron::setup(); + } + $this->test_base = new MSM_SiteMap_Test(); // Create posts for the last num_days days @@ -73,4 +78,40 @@ function test_sitemap_posts_were_created() { wp_reset_postdata(); } } -} \ No newline at end of file + + /** + * This is a long and convoluted test. + * + * Checks to see that a sitemap for a day is deleted when all posts for that day are deleted too. + */ + function test_delete_empty_sitemap() { + global $wpdb; + + list( $sitemap ) = get_posts( array( + 'post_type' => Metro_Sitemap::SITEMAP_CPT, + 'posts_per_page' => 1, + ) ); + + $sitemap_date = date( 'Y-m-d', strtotime( $sitemap->post_date ) ); + list( $year, $month, $day ) = explode( '-', $sitemap_date ); + $start_date = $sitemap_date . ' 00:00:00'; + $end_date = $sitemap_date . ' 23:59:59'; + $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_status = 'publish' AND post_date >= %s AND post_date <= %s AND post_type = 'post' LIMIT 1", $start_date, $end_date ) ); + + $expected_total_urls = Metro_Sitemap::get_total_indexed_url_count() - count( $post_ids ); + + foreach ( $post_ids as $post_id ) { + wp_delete_post( $post_id, true ); + } + + MSM_Sitemap_Builder_Cron::generate_sitemap_for_year_month_day( array( + 'year' => $year, + 'month' => $month, + 'day' => $day, + ) ); + + $this->assertEmpty( get_post( $sitemap->ID ), 'Sitemap with no posts was not deleted' ); + $this->assertEquals( $expected_total_urls, Metro_Sitemap::get_total_indexed_url_count(), 'Mismatch in total indexed URLs' ); + $this->assertEquals( 1, did_action( 'msm_delete_sitemap_post' ), 'msm_delete_sitemap_post action did not fire' ); + } +}