WordPress.org

Plugin Directory

Changeset 1606758


Ignore:
Timestamp:
03/02/17 20:42:00 (3 months ago)
Author:
coffee2code
Message:

Release v1.2:

  • New: Add footer to daily emails to provide context about what the email is, why it is being sent, and where to go to discontinue it
  • Change: Make prefatory post listing text (in widget and email) more informative
    • Include month and day of the month instead of saying "this day"
    • Include count of the number of posts being listed
    • Use separate singular and plural strings
  • Change: Use built-in WP date query syntax for finding older posts
    • Delete add_year_clause_to_query()
    • Move some of the date handling code from add_year_clause_to_query() into get_posts() for use in date_query
  • Change: Split out functionality from cron_email() into single-purpose functions
    • Add get_email_subject() for getting email subject
    • Add get_email_body() for getting email body
    • Bail if either return empty string
  • Change: Prevent object instantiation
    • Add private __construct()
    • Add private __wakeup()
  • Change: Update unit test bootstrap
    • Default WP_TESTS_DIR to /tmp/wordpress-tests-lib rather than erroring out if not defined via environment variable
    • Enable more error output for unit tests
  • Change: Note compatibility through WP 4.7+
  • Change: Remove support for WordPress older than WP 4.6 (should still work for earlier versions back to WP 4.1)
  • Change: Minor inline code documnetation tweaks (fix typos, spacing)
  • Change: Update copyright date (2017)
  • New: Add LICENSE file
  • Change: Update screenshots
Location:
years-ago-today
Files:
2 added
9 edited
3 copied

Legend:

Unmodified
Added
Removed
  • years-ago-today/tags/1.2/readme.txt

    r1394839 r1606758  
    55License: GPLv2 or later 
    66License URI: http://www.gnu.org/licenses/gpl-2.0.html 
    7 Requires at least: 4.1 
    8 Tested up to: 4.5 
    9 Stable tag: 1.1 
     7Requires at least: 4.6 
     8Tested up to: 4.7 
     9Stable tag: 1.2 
    1010 
    1111Admin dashboard widget (and optional daily email) that lists posts published to your site on this day in years past. 
     
    2020== Installation == 
    2121 
    22 1. Unzip `years-ago-today.zip` inside the plugins directory for your site (typically `/wp-content/plugins/`). Or install via the built-in WordPress plugin installer) 
     221. Install via the built-in WordPress plugin installer. Or download and unzip `years-ago-today.zip` inside the plugins directory for your site (typically `wp-content/plugins/`) 
    23232. Activate the plugin through the 'Plugins' admin menu in WordPress 
    24243. View the widget on your admin dashboard. 
    25254. (Optional.) To sign up for a daily email that lists posts published that day, go to your profile, set the checkbox for '"Years Ago Today" email', and then press the button to update your profile. 
     26 
    2627 
    2728== Screenshots == 
     
    5758== Changelog == 
    5859 
     60= 1.2 (2017-02-20) = 
     61* New: Add footer to daily emails to provide context about what the email is, why it is being sent, and where to go to discontinue it 
     62* Change: Make prefatory post listing text (in widget and email) more informative 
     63    * Include month and day of the month instead of saying "this day" 
     64    * Include count of the number of posts being listed 
     65    * Use separate singular and plural strings 
     66* Change: Use built-in WP date query syntax for finding older posts 
     67    * Delete `add_year_clause_to_query()` 
     68    * Move some of the date handling code from `add_year_clause_to_query()` into `get_posts()` for use in date_query 
     69* Change: Split out functionality from `cron_email()` into single-purpose functions 
     70    * Add `get_email_subject()` for getting email subject 
     71    * Add `get_email_body()` for getting email body 
     72    * Bail if either return empty string 
     73* Change: Prevent object instantiation 
     74    * Add private `__construct()` 
     75    * Add private `__wakeup()` 
     76* Change: Update unit test bootstrap 
     77    * Default `WP_TESTS_DIR` to `/tmp/wordpress-tests-lib` rather than erroring out if not defined via environment variable 
     78    * Enable more error output for unit tests 
     79* Change: Note compatibility through WP 4.7+ 
     80* Change: Remove support for WordPress older than WP 4.6 (should still work for earlier versions back to WP 4.1) 
     81* Change: Minor inline code documnetation tweaks (fix typos, spacing) 
     82* Change: Update copyright date (2017) 
     83* New: Add LICENSE file 
     84* Change: Update screenshots 
     85 
    5986= 1.1 (2016-01-21) = 
    6087* Bugfix: Fix for bug when posts across two days were returned for today by using site's time and not GMT. 
     
    82109== Upgrade Notice == 
    83110 
     111= 1.2 = 
     112Minor update: added footer text to daily emails, show today's date and number of posts in dashboard widget and email, use separate singular and plural strings, compatibility is now WP 4.6-4.7+, updated copyright date (2017), and more 
     113 
    84114= 1.1 = 
    85115Recommended update: bugfix for posts published the day after past todays sometimes being included; adjustments to utilize language packs; minor unit test tweaks; noted compatibility through WP 4.4+; and updated copyright date 
  • years-ago-today/tags/1.2/tests/bootstrap.php

    r1194581 r1606758  
    11<?php 
     2/** 
     3 * PHPUnit bootstrap file 
     4 * 
     5 * @package Years_Ago_Today 
     6 */ 
    27 
    3 require_once getenv( 'WP_TESTS_DIR' ) . '/includes/functions.php'; 
     8ini_set('display_errors','on'); 
     9error_reporting(E_ALL); 
    410 
     11$_tests_dir = getenv( 'WP_TESTS_DIR' ); 
     12if ( ! $_tests_dir ) { 
     13        $_tests_dir = '/tmp/wordpress-tests-lib'; 
     14} 
     15 
     16// Give access to tests_add_filter() function. 
     17require_once $_tests_dir . '/includes/functions.php'; 
     18 
     19/** 
     20 * Manually load the plugin being tested. 
     21 */ 
    522function _manually_load_plugin() { 
    6     require dirname( __FILE__ ) . '/../years-ago-today.php'; 
     23        require dirname( dirname( __FILE__ ) ) . '/years-ago-today.php'; 
    724} 
    825tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' ); 
    926 
    10 require getenv( 'WP_TESTS_DIR' ) . '/includes/bootstrap.php'; 
    11  
     27// Start up the WP testing environment. 
     28require $_tests_dir . '/includes/bootstrap.php'; 
  • years-ago-today/tags/1.2/tests/test-years-ago-today.php

    r1333480 r1606758  
    44 
    55class Years_Ago_Today_Test extends WP_UnitTestCase { 
     6 
     7    public function tearDown() { 
     8        parent::tearDown(); 
     9 
     10        remove_filter( 'c2c_years_ago_today-email-if-no-posts', '__return_true' ); 
     11    } 
     12 
    613 
    714    // 
     
    3239 
    3340    public function test_plugin_version() { 
    34         $this->assertEquals( '1.1', c2c_YearsAgoToday::version() ); 
     41        $this->assertEquals( '1.2', c2c_YearsAgoToday::version() ); 
    3542    } 
    3643 
     
    4552    } 
    4653 
     54    /* 
     55     * wp_dashboard_years_ago_today() 
     56     */ 
     57 
    4758    public function test_shows_message_about_no_previous_year_posts() { 
     59        // Extra non-matching post 
     60        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     61 
    4862        ob_start(); 
    4963        c2c_YearsAgoToday::wp_dashboard_years_ago_today(); 
     
    5165        ob_end_clean(); 
    5266 
    53         $this->assertContains( 'No posts were published on this day from any past year.', $out ); 
    54     } 
     67        $this->assertContains( 'No posts were published on <strong>' . current_time( 'M jS' ) . '</strong> from any past year.', $out ); 
     68    } 
     69 
     70    public function test_shows_singular_message_with_single_matching_past_year_posts() { 
     71        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     72        // Extra non-matching post 
     73        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     74 
     75        ob_start(); 
     76        c2c_YearsAgoToday::wp_dashboard_years_ago_today(); 
     77        $out = ob_get_contents(); 
     78        ob_end_clean(); 
     79 
     80        $this->assertContains( '<strong>1</strong> post has been published on <strong>' . current_time( 'M jS' ) . '</strong> in a previous year:', $out ); 
     81    } 
     82 
     83    public function test_shows_plural_message_with_multiple_matching_past_year_posts() { 
     84        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     85        $this->factory->post->create( array( 'post_date' => $this->get_date( '2014' ) ) ); 
     86        // Extra non-matching post 
     87        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     88 
     89        ob_start(); 
     90        c2c_YearsAgoToday::wp_dashboard_years_ago_today(); 
     91        $out = ob_get_contents(); 
     92        ob_end_clean(); 
     93 
     94        $this->assertContains( '<strong>2</strong> posts have been published on <strong>' . current_time( 'M jS' ) . '</strong> in previous years:', $out ); 
     95    } 
     96 
     97    /* 
     98     * get_posts() 
     99     */ 
    55100 
    56101    public function test_get_posts_query_obj_with_no_matching_past_year_posts() { 
    57102        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012', false ) ) ); 
    58103 
    59         $this->assertFalse( c2c_YearsAgoToday::get_posts()->have_posts() ); 
     104        $posts = c2c_YearsAgoToday::get_posts(); 
     105 
     106        $this->assertTrue( is_a( $posts, 'WP_Query' ) ); 
     107        $this->assertFalse( $posts->have_posts() ); 
    60108    } 
    61109 
     
    85133        $this->assertEquals( get_post( $post_id ), $posts[0] ); 
    86134    } 
     135 
     136    /* 
     137     * get_users_to_email() 
     138     */ 
    87139 
    88140    public function test_get_users_to_email_with_no_users() { 
     
    107159        $this->assertEquals( array( $user1, $user3 ), c2c_YearsAgoToday::get_users_to_email() ); 
    108160    } 
     161 
     162    /* 
     163     * get_first_published_year() 
     164     */ 
    109165 
    110166    public function test_get_first_published_year_with_no_posts() { 
     
    122178    } 
    123179 
     180    /* 
     181     * get_email_subject() 
     182     */ 
     183 
     184    public function test_get_email_subject() { 
     185        $this->assertEquals( 
     186            '[Test Blog] Years Ago Today daily update', 
     187            c2c_YearsAgoToday::get_email_subject() 
     188        ); 
     189    } 
     190 
     191    /* 
     192     * get_email_body() 
     193     */ 
     194 
     195    public function test_get_email_body_with_no_posts() { 
     196        $this->assertEmpty( c2c_YearsAgoToday::get_email_body() ); 
     197    } 
     198 
     199    public function test_get_email_body_with_no_posts_but_email_forced() { 
     200        add_filter( 'c2c_years_ago_today-email-if-no-posts', '__return_true' ); 
     201 
     202        $this->assertEquals( 
     203            sprintf( 
     204                'No posts were published to the site %1$s on <strong>%2$s</strong> in any past year.', 
     205                'Test Blog', 
     206                current_time( 'M jS' ) 
     207            ), 
     208            c2c_YearsAgoToday::get_email_body() 
     209        ); 
     210    } 
     211 
     212    public function test_get_email_body_shows_singular_message_with_single_matching_past_year_posts() { 
     213        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     214        // Extra non-matching post 
     215        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     216 
     217        $this->assertContains( 
     218            '<strong>1</strong> post has been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in a previous year:', 
     219            c2c_YearsAgoToday::get_email_body() 
     220        ); 
     221    } 
     222 
     223    public function test_get_email_body_whole_email_with_single_matching_past_year_posts() { 
     224        $post_title = 'A blast from the past'; 
     225        $post = $this->factory->post->create( array( 'post_title' => $post_title, 'post_date' => $this->get_date( '2012' ) ) ); 
     226        // Extra non-matching post 
     227        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     228 
     229        $email  = '<strong>1</strong> post has been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in a previous year:'; 
     230        $email .= "\n\n== 2012 ==\n"; 
     231        $email .= "* {$post_title} : " . get_permalink( $post ) . "\n"; 
     232 
     233        $this->assertEquals( 
     234            $email, 
     235            c2c_YearsAgoToday::get_email_body() 
     236        ); 
     237    } 
     238 
     239    public function test_get_email_body_shows_plural_message_with_multiple_matching_past_year_posts() { 
     240        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     241        $this->factory->post->create( array( 'post_date' => $this->get_date( '2014' ) ) ); 
     242        // Extra non-matching post 
     243        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     244 
     245        $this->assertContains( 
     246            '<strong>2</strong> posts have been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in previous years:', 
     247            c2c_YearsAgoToday::get_email_body() 
     248        ); 
     249    } 
     250 
     251    public function test_get_email_body_whole_email_with_multiple_matching_past_year_posts() { 
     252        $post_title1 = 'A blast from the past'; 
     253        $post1 = $this->factory->post->create( array( 'post_title' => $post_title1, 'post_date' => $this->get_date( '2012' ) ) ); 
     254        $post_title2 = 'Days of future years past'; 
     255        $post2 = $this->factory->post->create( array( 'post_title' => $post_title2, 'post_date' => $this->get_date( '2014' ) ) ); 
     256        // Extra non-matching post 
     257        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     258 
     259        $email  = '<strong>2</strong> posts have been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in previous years:'; 
     260        $email .= "\n\n== 2014 ==\n"; 
     261        $email .= "* {$post_title2} : " . get_permalink( $post2 ) . "\n"; 
     262        $email .= "\n\n== 2012 ==\n"; 
     263        $email .= "* {$post_title1} : " . get_permalink( $post1 ) . "\n"; 
     264 
     265        $this->assertEquals( 
     266            $email, 
     267            c2c_YearsAgoToday::get_email_body() 
     268        ); 
     269    } 
     270 
     271    /* 
     272     * add_user_email_footer() 
     273     */ 
     274 
     275    public function test_add_user_email_footer() { 
     276        $user_id = $this->factory->user->create(); 
     277        $user_profile_url = get_edit_profile_url( $user_id ); 
     278        $text = <<<HTML 
     279Hi! 
     280 
     281 
     282------------------------------- 
     283You received this email because you have opted into receiving a daily email about posts published on this day in years past on the site Test Blog, which is using the Years Ago Today plugin. 
     284 
     285If you wish to discontinue receiving these emails, simply log into the site and visit your profile at {$user_profile_url} to uncheck the checkbox labeled "Email me daily about posts published on this day in years past." 
     286 
     287HTML; 
     288 
     289        $this->assertEquals( $text, c2c_YearsAgoToday::add_user_email_footer( $user_id, 'Hi!' ) ); 
     290    } 
     291 
    124292} 
  • years-ago-today/tags/1.2/years-ago-today.php

    r1394839 r1606758  
    22/** 
    33 * Plugin Name: Years Ago Today 
    4  * Version:     1.1 
     4 * Version:     1.2 
    55 * Plugin URI:  http://coffee2code.com/wp-plugins/years-ago-today/ 
    66 * Author:      Scott Reilly 
     
    1212 * Description: Admin dashboard widget (and optional daily email) that lists posts published to your site on this day in years past. 
    1313 * 
    14  * Compatible with WordPress 4.1 (and probably earlier) through 4.5+. 
     14 * Compatible with WordPress 4.6 through 4.7+. 
    1515 * 
    1616 * =>> Read the accompanying readme.txt file for instructions and documentation. 
     
    2020 * @package Years_Ago_Today 
    2121 * @author  Scott Reilly 
    22  * @version 1.1 
     22 * @version 1.2 
    2323 */ 
    2424 
     
    2626 * TODO: 
    2727 * - Put CSS in .css file. 
    28  * - Show more info about post in widget, such as author. (Maybe hide by default and show on hover.) 
     28 * - Show more info about post in widget, such as author (if on multi-author site). (Maybe hide by default and show on hover.) 
    2929 * - Add cap to control what users can get the daily email? 
    3030 * - Add way to filter by author. 
    3131 * - Allow post listing template to be overridden. 
     32 * - Add widget for front-end use. 
    3233 */ 
    3334 
    3435/* 
    35     Copyright (c) 2015-2016 by Scott Reilly (aka coffee2code) 
     36    Copyright (c) 2015-2017 by Scott Reilly (aka coffee2code) 
    3637 
    3738    This program is free software; you can redistribute it and/or 
     
    8384 
    8485    /** 
     86     * Prevents instantiation. 
     87     * 
     88     * @since 1.2 
     89     */ 
     90    private function __construct() {} 
     91 
     92    /** 
     93     * Prevents unserializing an instance. 
     94     * 
     95     * @since 1.2 
     96     */ 
     97    private function __wakeup() {} 
     98 
     99    /** 
    85100     * Returns version of the plugin. 
    86101     * 
     
    88103     */ 
    89104    public static function version() { 
    90         return '1.1'; 
     105        return '1.2'; 
    91106    } 
    92107 
     
    116131        // Register dashboard widget. 
    117132        add_action( 'wp_dashboard_setup',       array( __CLASS__, 'dashboard_setup' ) ); 
    118  
    119         // Modify posts query for year ago searches. 
    120         add_action( 'posts_where',              array( __CLASS__, 'add_year_clause_to_query' ), 10, 2 ); 
    121133 
    122134        // Adds the checkbox to user profiles. 
     
    176188 
    177189    /** 
    178      * Sends out daily email. 
    179      * 
    180      * @since 1.0 
    181      */ 
    182     public static function cron_email() { 
    183         // Get list of users who want the daily email. 
    184         $users = self::get_users_to_email(); 
    185  
    186         // If no one wants the email, there's nothing else to do. 
    187         if ( ! $users ) { 
    188             return; 
    189         } 
    190  
     190     * Returns the body of the daily email. 
     191     * 
     192     * @since 1.2 
     193     * 
     194     * @return string 
     195     */ 
     196    public static function get_email_body() { 
    191197        // Get the list of posts from years ago. 
    192198        $query = self::get_posts(); 
    193199 
     200        $site_name = wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ); 
     201 
    194202        // If there were no posts, check a filter to see if an email shouldn't be sent. 
    195203        if ( ! $query->have_posts() && ! apply_filters( 'c2c_years_ago_today-email-if-no-posts', false ) ) { 
    196             return; 
     204            $body = ''; 
    197205        }  elseif ( ! $query->have_posts() ) { 
    198206            $body = apply_filters( 
    199207                'c2c_years_ago_today-email-body-no-posts', 
    200208                sprintf( 
    201                     __( 'No posts were published to the site %s on this day from any past year.', 'years-ago-today' ), 
    202                     wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
     209                    /* translators: 1: name of the site, 2: date string for today */ 
     210                    __( 'No posts were published to the site %1$s on <strong>%2$s</strong> in any past year.', 'years-ago-today' ), 
     211                    $site_name, 
     212                    /* translators: date string for today */ 
     213                    date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
    203214                ) 
    204215            ); 
     
    206217            // Build out email body. 
    207218            $body = sprintf( 
    208                 __( 'The following post(s) have been published to the site %s on this day in previous years:', 'wporg' ), 
    209                 wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
     219                /* translators: 1: number of posts, 2: site name, 3: date string for today */ 
     220                _n( 
     221                    '<strong>%1$d</strong> post has been published to the site %2$s on <strong>%3$s</strong> in a previous year:', 
     222                    '<strong>%1$d</strong> posts have been published to the site %2$s on <strong>%3$s</strong> in previous years:', 
     223                    $query->post_count, 
     224                    'years-ago-today' 
     225                ), 
     226                $query->post_count, 
     227                $site_name, 
     228                /* translators: date string for today */ 
     229                date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
    210230            ); 
    211231 
    212232            $year = ''; 
    213             while ( $query->have_posts() ) : $query->the_post(); 
     233            while ( $query->have_posts() ) : 
     234                $query->the_post(); 
    214235                $this_year = get_the_date( 'Y' ); 
    215236                // Only output the year once. 
     
    223244        } 
    224245 
    225         // Build subject. 
    226         $subject = sprintf( 
     246        return $body; 
     247    } 
     248 
     249    /** 
     250     * Returns the subject line for the daily email. 
     251     * 
     252     * @since 1.2 
     253     * 
     254     * @return string 
     255     */ 
     256    public static function get_email_subject() { 
     257        return sprintf( 
     258            /* translators: %s: site name in subject for daily email */ 
    227259            __( '[%s] Years Ago Today daily update', 'years-ago-today' ), 
    228260            wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
    229261        ); 
     262    } 
     263 
     264    /** 
     265     * Amends a user-specific footer to an email body. 
     266     * 
     267     * Adds an explanation about the email to the recipient. Serves to remind 
     268     * the user why they are receiving the email, what it is about, and how to 
     269     * stop it. 
     270     * 
     271     * @since 1.2 
     272     * 
     273     * @param  int    $user_id The user ID. 
     274     * @param  string $body.   The email body. 
     275     * @return string 
     276     */ 
     277    public static function add_user_email_footer( $user_id, $body ) { 
     278        $body .= "\n\n\n-------------------------------\n"; 
     279        $body .= sprintf( 
     280            __( 'You received this email because you have opted into receiving a daily email about posts published on this day in years past on the site %s, which is using the Years Ago Today plugin.', 'years-ago-today' ), 
     281            wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
     282        ); 
     283        $body .= "\n\n"; 
     284        $body .= sprintf( 
     285            __( 'If you wish to discontinue receiving these emails, simply log into the site and visit your profile at %s to uncheck the checkbox labeled "Email me daily about posts published on this day in years past."', 'years-ago-today' ), 
     286            get_edit_profile_url( $user_id ) 
     287        ); 
     288        $body .= "\n"; 
     289 
     290        return $body; 
     291    } 
     292 
     293    /** 
     294     * Sends out daily email. 
     295     * 
     296     * @since 1.0 
     297     * @todo  Handle large volume of users better, perhaps via chunked BCCs. 
     298     */ 
     299    public static function cron_email() { 
     300        // Get list of users who want the daily email. 
     301        $users = self::get_users_to_email(); 
     302 
     303        // If no one wants the email, there's nothing else to do. 
     304        if ( ! $users ) { 
     305            return; 
     306        } 
     307 
     308        // Get the content of the email. 
     309        $subject = self::get_email_subject(); 
     310        $body    = self::get_email_body(); 
     311 
     312        // If no subject or body for the email, then there's nothing else to do. 
     313        if ( ! $subject || ! $body ) { 
     314            return; 
     315        } 
    230316 
    231317        // Send email to each user. 
    232318        foreach ( $users as $user ) { 
    233319            if ( $user->user_email ) { 
    234                 wp_mail( $user->user_email, $subject, $body ); 
     320                wp_mail( $user->user_email, $subject, self::add_user_email_footer( $user->ID, $body ) ); 
    235321            } 
    236322        } 
     
    261347 
    262348        if ( $q->have_posts() ) : 
    263             echo '<p>' . __( 'The following post(s) have been published to the site on this day in previous years:', 'years-ago-today' ) . '</p>'; 
     349            echo '<p>'; 
     350            echo sprintf( 
     351                /* translators: 1: number of posts, 2: site name, 2: date string for today */ 
     352                _n( 
     353                    '<strong>%1$d</strong> post has been published on <strong>%2$s</strong> in a previous year:', 
     354                    '<strong>%1$d</strong> posts have been published on <strong>%2$s</strong> in previous years:', 
     355                    $q->post_count, 
     356                    'years-ago-today' 
     357                ), 
     358                $q->post_count, 
     359                /* translators: date string for today */ 
     360                date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
     361            ); 
     362            echo '</p>'; 
    264363            echo '<ul class="years-ago-today-posts">'; 
    265364            $year = ''; 
    266             while ( $q->have_posts() ) : $q->the_post(); 
     365            while ( $q->have_posts() ) : 
     366                $q->the_post(); 
    267367                $this_year = get_the_date( 'Y' ); 
    268368                // Only output the year once. 
     
    276376            echo '</ul>'; 
    277377        else : 
    278             echo '<p>' . __( 'No posts were published on this day from any past year.', 'years-ago-today' ) . '</p>'; 
     378            echo '<p>'; 
     379            printf( 
     380                /* translators: %s: date string for today */ 
     381                __( 'No posts were published on <strong>%s</strong> from any past year.', 'years-ago-today' ), 
     382                /* translators: date string for today */ 
     383                date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
     384            ); 
     385            echo '</p>'; 
    279386        endif; 
    280387 
    281388        echo '</div>'; 
    282     } 
    283  
    284     /** 
    285      * Adjusts WHERE clause to include date range to find years ago posts. 
    286      * 
    287      * @since 1.0 
    288      * 
    289      * @param string   $where The SQL WHERE clause. 
    290      * @param WP_Query $query The query object. 
    291      * @return string 
    292      */ 
    293     public static function add_year_clause_to_query( $where, $query ) { 
    294         global $wpdb; 
    295  
    296         if ( isset( $query->query_vars['is_years_ago_today'] ) && '1' == $query->query_vars['is_years_ago_today'] ) { 
    297  
    298             $first_year = self::get_first_published_year(); 
    299             $current_year = mysql2date( 'Y', current_time( 'mysql' ) ); 
    300  
    301             $years = range( $first_year, $current_year - 1 ); 
    302             $now   = current_time( 'timestamp' ); 
    303             $month = mysql2date( 'm', $now ); 
    304             $day   = mysql2date( 'd', $now ); 
    305  
    306             // Check data with more performant BETWEEN rather than using DATE() 
    307             // or its variations (YEAR(), MONTH(), DAYOFMONTH()). 
    308             $date_ranges = array(); 
    309             foreach ( $years as $year ) { 
    310                 $date_ranges[] = $wpdb->prepare( 
    311                     '( post_date_gmt BETWEEN %s AND %s )', 
    312                     "${year}-${month}-{$day} 00:00:00", 
    313                     "${year}-${month}-{$day} 23:59:59" 
    314                 ); 
    315             } 
    316  
    317             if ( $date_ranges ) { 
    318                 $where .= ' AND (' . implode( ' OR ', $date_ranges ) . ' ) '; 
    319             } 
    320  
    321         } 
    322  
    323         return $where; 
    324389    } 
    325390 
     
    340405        } 
    341406 
    342         // If not in the cache, figure it out.', 
     407        // If not in the cache, figure it out. 
    343408        if ( false === $first_year ) { 
    344             // Query for the earlies published year. 
     409            // Query for the earliest published year. 
    345410            $first_year = $wpdb->get_var( "SELECT YEAR(MIN(post_date)) FROM $wpdb->posts WHERE post_status IN ( 'publish', 'private' )" ); 
    346411 
     
    363428     * @since 1.0 
    364429     * 
    365      * @param bool            $return_posts True to return just an array of posts, false to return WP_Query object. Default false. 
    366      * @return array|WP_Query Array is return_posts is true, WP_Query if false. 
     430     * @param bool $return_posts Return array of queried posts or the WP_Query 
     431     *                           object? True to return array posts, false to 
     432     *                           return WP_Query object. Default false. 
     433     * @return array|WP_Query    Array if return_posts is true, WP_Query if false. 
    367434     */ 
    368435    public static function get_posts( $return_posts = false ) { 
     436        $first_year   = self::get_first_published_year(); 
     437        $current_year = mysql2date( 'Y', current_time( 'mysql' ) ); 
     438 
     439        $years = range( $first_year, $current_year - 1 ); 
     440        $now   = current_time( 'timestamp' ); 
     441        $month = mysql2date( 'm', $now ); 
     442        $day   = mysql2date( 'd', $now ); 
     443 
    369444        $query = new WP_Query( array( 
    370             'post_parent'        => '', 
    371             'post_status'        => array( 'publish' ), 
    372             'post_type'          => array( 'post' ), 
    373             'posts_per_page'     => -1, 
    374             'is_years_ago_today' => 1, 
     445            'post_parent'    => '', 
     446            'post_status'    => array( 'publish' ), 
     447            'post_type'      => array( 'post' ), 
     448            'posts_per_page' => -1, 
     449            'date_query'     => array( 
     450                'year'  => $years, 
     451                'month' => $month, 
     452                'day'   => $day, 
     453            ), 
    375454        ) ); 
    376455 
     
    379458 
    380459    /** 
    381      * Adds hook to outputs CSS for the display of the Trashed By column if 
    382      * on the appropriate admin page. 
     460     * Adds hook to outputs CSS for the display of the Years Ago today widget. 
    383461     * 
    384462     * @since 1.0 
     
    420498     * 
    421499     * @param  int  $user_id The user ID. 
    422      * @return bool True if the option saved successfully. 
     500     * @return bool          True if the option saved successfully. 
    423501     */ 
    424502    public static function option_save( $user_id ) { 
  • years-ago-today/trunk/readme.txt

    r1394839 r1606758  
    55License: GPLv2 or later 
    66License URI: http://www.gnu.org/licenses/gpl-2.0.html 
    7 Requires at least: 4.1 
    8 Tested up to: 4.5 
    9 Stable tag: 1.1 
     7Requires at least: 4.6 
     8Tested up to: 4.7 
     9Stable tag: 1.2 
    1010 
    1111Admin dashboard widget (and optional daily email) that lists posts published to your site on this day in years past. 
     
    2020== Installation == 
    2121 
    22 1. Unzip `years-ago-today.zip` inside the plugins directory for your site (typically `/wp-content/plugins/`). Or install via the built-in WordPress plugin installer) 
     221. Install via the built-in WordPress plugin installer. Or download and unzip `years-ago-today.zip` inside the plugins directory for your site (typically `wp-content/plugins/`) 
    23232. Activate the plugin through the 'Plugins' admin menu in WordPress 
    24243. View the widget on your admin dashboard. 
    25254. (Optional.) To sign up for a daily email that lists posts published that day, go to your profile, set the checkbox for '"Years Ago Today" email', and then press the button to update your profile. 
     26 
    2627 
    2728== Screenshots == 
     
    5758== Changelog == 
    5859 
     60= 1.2 (2017-02-20) = 
     61* New: Add footer to daily emails to provide context about what the email is, why it is being sent, and where to go to discontinue it 
     62* Change: Make prefatory post listing text (in widget and email) more informative 
     63    * Include month and day of the month instead of saying "this day" 
     64    * Include count of the number of posts being listed 
     65    * Use separate singular and plural strings 
     66* Change: Use built-in WP date query syntax for finding older posts 
     67    * Delete `add_year_clause_to_query()` 
     68    * Move some of the date handling code from `add_year_clause_to_query()` into `get_posts()` for use in date_query 
     69* Change: Split out functionality from `cron_email()` into single-purpose functions 
     70    * Add `get_email_subject()` for getting email subject 
     71    * Add `get_email_body()` for getting email body 
     72    * Bail if either return empty string 
     73* Change: Prevent object instantiation 
     74    * Add private `__construct()` 
     75    * Add private `__wakeup()` 
     76* Change: Update unit test bootstrap 
     77    * Default `WP_TESTS_DIR` to `/tmp/wordpress-tests-lib` rather than erroring out if not defined via environment variable 
     78    * Enable more error output for unit tests 
     79* Change: Note compatibility through WP 4.7+ 
     80* Change: Remove support for WordPress older than WP 4.6 (should still work for earlier versions back to WP 4.1) 
     81* Change: Minor inline code documnetation tweaks (fix typos, spacing) 
     82* Change: Update copyright date (2017) 
     83* New: Add LICENSE file 
     84* Change: Update screenshots 
     85 
    5986= 1.1 (2016-01-21) = 
    6087* Bugfix: Fix for bug when posts across two days were returned for today by using site's time and not GMT. 
     
    82109== Upgrade Notice == 
    83110 
     111= 1.2 = 
     112Minor update: added footer text to daily emails, show today's date and number of posts in dashboard widget and email, use separate singular and plural strings, compatibility is now WP 4.6-4.7+, updated copyright date (2017), and more 
     113 
    84114= 1.1 = 
    85115Recommended update: bugfix for posts published the day after past todays sometimes being included; adjustments to utilize language packs; minor unit test tweaks; noted compatibility through WP 4.4+; and updated copyright date 
  • years-ago-today/trunk/tests/bootstrap.php

    r1194581 r1606758  
    11<?php 
     2/** 
     3 * PHPUnit bootstrap file 
     4 * 
     5 * @package Years_Ago_Today 
     6 */ 
    27 
    3 require_once getenv( 'WP_TESTS_DIR' ) . '/includes/functions.php'; 
     8ini_set('display_errors','on'); 
     9error_reporting(E_ALL); 
    410 
     11$_tests_dir = getenv( 'WP_TESTS_DIR' ); 
     12if ( ! $_tests_dir ) { 
     13        $_tests_dir = '/tmp/wordpress-tests-lib'; 
     14} 
     15 
     16// Give access to tests_add_filter() function. 
     17require_once $_tests_dir . '/includes/functions.php'; 
     18 
     19/** 
     20 * Manually load the plugin being tested. 
     21 */ 
    522function _manually_load_plugin() { 
    6     require dirname( __FILE__ ) . '/../years-ago-today.php'; 
     23        require dirname( dirname( __FILE__ ) ) . '/years-ago-today.php'; 
    724} 
    825tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' ); 
    926 
    10 require getenv( 'WP_TESTS_DIR' ) . '/includes/bootstrap.php'; 
    11  
     27// Start up the WP testing environment. 
     28require $_tests_dir . '/includes/bootstrap.php'; 
  • years-ago-today/trunk/tests/test-years-ago-today.php

    r1333480 r1606758  
    44 
    55class Years_Ago_Today_Test extends WP_UnitTestCase { 
     6 
     7    public function tearDown() { 
     8        parent::tearDown(); 
     9 
     10        remove_filter( 'c2c_years_ago_today-email-if-no-posts', '__return_true' ); 
     11    } 
     12 
    613 
    714    // 
     
    3239 
    3340    public function test_plugin_version() { 
    34         $this->assertEquals( '1.1', c2c_YearsAgoToday::version() ); 
     41        $this->assertEquals( '1.2', c2c_YearsAgoToday::version() ); 
    3542    } 
    3643 
     
    4552    } 
    4653 
     54    /* 
     55     * wp_dashboard_years_ago_today() 
     56     */ 
     57 
    4758    public function test_shows_message_about_no_previous_year_posts() { 
     59        // Extra non-matching post 
     60        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     61 
    4862        ob_start(); 
    4963        c2c_YearsAgoToday::wp_dashboard_years_ago_today(); 
     
    5165        ob_end_clean(); 
    5266 
    53         $this->assertContains( 'No posts were published on this day from any past year.', $out ); 
    54     } 
     67        $this->assertContains( 'No posts were published on <strong>' . current_time( 'M jS' ) . '</strong> from any past year.', $out ); 
     68    } 
     69 
     70    public function test_shows_singular_message_with_single_matching_past_year_posts() { 
     71        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     72        // Extra non-matching post 
     73        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     74 
     75        ob_start(); 
     76        c2c_YearsAgoToday::wp_dashboard_years_ago_today(); 
     77        $out = ob_get_contents(); 
     78        ob_end_clean(); 
     79 
     80        $this->assertContains( '<strong>1</strong> post has been published on <strong>' . current_time( 'M jS' ) . '</strong> in a previous year:', $out ); 
     81    } 
     82 
     83    public function test_shows_plural_message_with_multiple_matching_past_year_posts() { 
     84        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     85        $this->factory->post->create( array( 'post_date' => $this->get_date( '2014' ) ) ); 
     86        // Extra non-matching post 
     87        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     88 
     89        ob_start(); 
     90        c2c_YearsAgoToday::wp_dashboard_years_ago_today(); 
     91        $out = ob_get_contents(); 
     92        ob_end_clean(); 
     93 
     94        $this->assertContains( '<strong>2</strong> posts have been published on <strong>' . current_time( 'M jS' ) . '</strong> in previous years:', $out ); 
     95    } 
     96 
     97    /* 
     98     * get_posts() 
     99     */ 
    55100 
    56101    public function test_get_posts_query_obj_with_no_matching_past_year_posts() { 
    57102        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012', false ) ) ); 
    58103 
    59         $this->assertFalse( c2c_YearsAgoToday::get_posts()->have_posts() ); 
     104        $posts = c2c_YearsAgoToday::get_posts(); 
     105 
     106        $this->assertTrue( is_a( $posts, 'WP_Query' ) ); 
     107        $this->assertFalse( $posts->have_posts() ); 
    60108    } 
    61109 
     
    85133        $this->assertEquals( get_post( $post_id ), $posts[0] ); 
    86134    } 
     135 
     136    /* 
     137     * get_users_to_email() 
     138     */ 
    87139 
    88140    public function test_get_users_to_email_with_no_users() { 
     
    107159        $this->assertEquals( array( $user1, $user3 ), c2c_YearsAgoToday::get_users_to_email() ); 
    108160    } 
     161 
     162    /* 
     163     * get_first_published_year() 
     164     */ 
    109165 
    110166    public function test_get_first_published_year_with_no_posts() { 
     
    122178    } 
    123179 
     180    /* 
     181     * get_email_subject() 
     182     */ 
     183 
     184    public function test_get_email_subject() { 
     185        $this->assertEquals( 
     186            '[Test Blog] Years Ago Today daily update', 
     187            c2c_YearsAgoToday::get_email_subject() 
     188        ); 
     189    } 
     190 
     191    /* 
     192     * get_email_body() 
     193     */ 
     194 
     195    public function test_get_email_body_with_no_posts() { 
     196        $this->assertEmpty( c2c_YearsAgoToday::get_email_body() ); 
     197    } 
     198 
     199    public function test_get_email_body_with_no_posts_but_email_forced() { 
     200        add_filter( 'c2c_years_ago_today-email-if-no-posts', '__return_true' ); 
     201 
     202        $this->assertEquals( 
     203            sprintf( 
     204                'No posts were published to the site %1$s on <strong>%2$s</strong> in any past year.', 
     205                'Test Blog', 
     206                current_time( 'M jS' ) 
     207            ), 
     208            c2c_YearsAgoToday::get_email_body() 
     209        ); 
     210    } 
     211 
     212    public function test_get_email_body_shows_singular_message_with_single_matching_past_year_posts() { 
     213        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     214        // Extra non-matching post 
     215        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     216 
     217        $this->assertContains( 
     218            '<strong>1</strong> post has been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in a previous year:', 
     219            c2c_YearsAgoToday::get_email_body() 
     220        ); 
     221    } 
     222 
     223    public function test_get_email_body_whole_email_with_single_matching_past_year_posts() { 
     224        $post_title = 'A blast from the past'; 
     225        $post = $this->factory->post->create( array( 'post_title' => $post_title, 'post_date' => $this->get_date( '2012' ) ) ); 
     226        // Extra non-matching post 
     227        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     228 
     229        $email  = '<strong>1</strong> post has been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in a previous year:'; 
     230        $email .= "\n\n== 2012 ==\n"; 
     231        $email .= "* {$post_title} : " . get_permalink( $post ) . "\n"; 
     232 
     233        $this->assertEquals( 
     234            $email, 
     235            c2c_YearsAgoToday::get_email_body() 
     236        ); 
     237    } 
     238 
     239    public function test_get_email_body_shows_plural_message_with_multiple_matching_past_year_posts() { 
     240        $this->factory->post->create( array( 'post_date' => $this->get_date( '2012' ) ) ); 
     241        $this->factory->post->create( array( 'post_date' => $this->get_date( '2014' ) ) ); 
     242        // Extra non-matching post 
     243        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     244 
     245        $this->assertContains( 
     246            '<strong>2</strong> posts have been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in previous years:', 
     247            c2c_YearsAgoToday::get_email_body() 
     248        ); 
     249    } 
     250 
     251    public function test_get_email_body_whole_email_with_multiple_matching_past_year_posts() { 
     252        $post_title1 = 'A blast from the past'; 
     253        $post1 = $this->factory->post->create( array( 'post_title' => $post_title1, 'post_date' => $this->get_date( '2012' ) ) ); 
     254        $post_title2 = 'Days of future years past'; 
     255        $post2 = $this->factory->post->create( array( 'post_title' => $post_title2, 'post_date' => $this->get_date( '2014' ) ) ); 
     256        // Extra non-matching post 
     257        $this->factory->post->create( array( 'post_date' => $this->get_date( '2015', false ) ) ); 
     258 
     259        $email  = '<strong>2</strong> posts have been published to the site Test Blog on <strong>' . current_time( 'M jS' ) . '</strong> in previous years:'; 
     260        $email .= "\n\n== 2014 ==\n"; 
     261        $email .= "* {$post_title2} : " . get_permalink( $post2 ) . "\n"; 
     262        $email .= "\n\n== 2012 ==\n"; 
     263        $email .= "* {$post_title1} : " . get_permalink( $post1 ) . "\n"; 
     264 
     265        $this->assertEquals( 
     266            $email, 
     267            c2c_YearsAgoToday::get_email_body() 
     268        ); 
     269    } 
     270 
     271    /* 
     272     * add_user_email_footer() 
     273     */ 
     274 
     275    public function test_add_user_email_footer() { 
     276        $user_id = $this->factory->user->create(); 
     277        $user_profile_url = get_edit_profile_url( $user_id ); 
     278        $text = <<<HTML 
     279Hi! 
     280 
     281 
     282------------------------------- 
     283You received this email because you have opted into receiving a daily email about posts published on this day in years past on the site Test Blog, which is using the Years Ago Today plugin. 
     284 
     285If you wish to discontinue receiving these emails, simply log into the site and visit your profile at {$user_profile_url} to uncheck the checkbox labeled "Email me daily about posts published on this day in years past." 
     286 
     287HTML; 
     288 
     289        $this->assertEquals( $text, c2c_YearsAgoToday::add_user_email_footer( $user_id, 'Hi!' ) ); 
     290    } 
     291 
    124292} 
  • years-ago-today/trunk/years-ago-today.php

    r1394839 r1606758  
    22/** 
    33 * Plugin Name: Years Ago Today 
    4  * Version:     1.1 
     4 * Version:     1.2 
    55 * Plugin URI:  http://coffee2code.com/wp-plugins/years-ago-today/ 
    66 * Author:      Scott Reilly 
     
    1212 * Description: Admin dashboard widget (and optional daily email) that lists posts published to your site on this day in years past. 
    1313 * 
    14  * Compatible with WordPress 4.1 (and probably earlier) through 4.5+. 
     14 * Compatible with WordPress 4.6 through 4.7+. 
    1515 * 
    1616 * =>> Read the accompanying readme.txt file for instructions and documentation. 
     
    2020 * @package Years_Ago_Today 
    2121 * @author  Scott Reilly 
    22  * @version 1.1 
     22 * @version 1.2 
    2323 */ 
    2424 
     
    2626 * TODO: 
    2727 * - Put CSS in .css file. 
    28  * - Show more info about post in widget, such as author. (Maybe hide by default and show on hover.) 
     28 * - Show more info about post in widget, such as author (if on multi-author site). (Maybe hide by default and show on hover.) 
    2929 * - Add cap to control what users can get the daily email? 
    3030 * - Add way to filter by author. 
    3131 * - Allow post listing template to be overridden. 
     32 * - Add widget for front-end use. 
    3233 */ 
    3334 
    3435/* 
    35     Copyright (c) 2015-2016 by Scott Reilly (aka coffee2code) 
     36    Copyright (c) 2015-2017 by Scott Reilly (aka coffee2code) 
    3637 
    3738    This program is free software; you can redistribute it and/or 
     
    8384 
    8485    /** 
     86     * Prevents instantiation. 
     87     * 
     88     * @since 1.2 
     89     */ 
     90    private function __construct() {} 
     91 
     92    /** 
     93     * Prevents unserializing an instance. 
     94     * 
     95     * @since 1.2 
     96     */ 
     97    private function __wakeup() {} 
     98 
     99    /** 
    85100     * Returns version of the plugin. 
    86101     * 
     
    88103     */ 
    89104    public static function version() { 
    90         return '1.1'; 
     105        return '1.2'; 
    91106    } 
    92107 
     
    116131        // Register dashboard widget. 
    117132        add_action( 'wp_dashboard_setup',       array( __CLASS__, 'dashboard_setup' ) ); 
    118  
    119         // Modify posts query for year ago searches. 
    120         add_action( 'posts_where',              array( __CLASS__, 'add_year_clause_to_query' ), 10, 2 ); 
    121133 
    122134        // Adds the checkbox to user profiles. 
     
    176188 
    177189    /** 
    178      * Sends out daily email. 
    179      * 
    180      * @since 1.0 
    181      */ 
    182     public static function cron_email() { 
    183         // Get list of users who want the daily email. 
    184         $users = self::get_users_to_email(); 
    185  
    186         // If no one wants the email, there's nothing else to do. 
    187         if ( ! $users ) { 
    188             return; 
    189         } 
    190  
     190     * Returns the body of the daily email. 
     191     * 
     192     * @since 1.2 
     193     * 
     194     * @return string 
     195     */ 
     196    public static function get_email_body() { 
    191197        // Get the list of posts from years ago. 
    192198        $query = self::get_posts(); 
    193199 
     200        $site_name = wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ); 
     201 
    194202        // If there were no posts, check a filter to see if an email shouldn't be sent. 
    195203        if ( ! $query->have_posts() && ! apply_filters( 'c2c_years_ago_today-email-if-no-posts', false ) ) { 
    196             return; 
     204            $body = ''; 
    197205        }  elseif ( ! $query->have_posts() ) { 
    198206            $body = apply_filters( 
    199207                'c2c_years_ago_today-email-body-no-posts', 
    200208                sprintf( 
    201                     __( 'No posts were published to the site %s on this day from any past year.', 'years-ago-today' ), 
    202                     wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
     209                    /* translators: 1: name of the site, 2: date string for today */ 
     210                    __( 'No posts were published to the site %1$s on <strong>%2$s</strong> in any past year.', 'years-ago-today' ), 
     211                    $site_name, 
     212                    /* translators: date string for today */ 
     213                    date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
    203214                ) 
    204215            ); 
     
    206217            // Build out email body. 
    207218            $body = sprintf( 
    208                 __( 'The following post(s) have been published to the site %s on this day in previous years:', 'wporg' ), 
    209                 wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
     219                /* translators: 1: number of posts, 2: site name, 3: date string for today */ 
     220                _n( 
     221                    '<strong>%1$d</strong> post has been published to the site %2$s on <strong>%3$s</strong> in a previous year:', 
     222                    '<strong>%1$d</strong> posts have been published to the site %2$s on <strong>%3$s</strong> in previous years:', 
     223                    $query->post_count, 
     224                    'years-ago-today' 
     225                ), 
     226                $query->post_count, 
     227                $site_name, 
     228                /* translators: date string for today */ 
     229                date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
    210230            ); 
    211231 
    212232            $year = ''; 
    213             while ( $query->have_posts() ) : $query->the_post(); 
     233            while ( $query->have_posts() ) : 
     234                $query->the_post(); 
    214235                $this_year = get_the_date( 'Y' ); 
    215236                // Only output the year once. 
     
    223244        } 
    224245 
    225         // Build subject. 
    226         $subject = sprintf( 
     246        return $body; 
     247    } 
     248 
     249    /** 
     250     * Returns the subject line for the daily email. 
     251     * 
     252     * @since 1.2 
     253     * 
     254     * @return string 
     255     */ 
     256    public static function get_email_subject() { 
     257        return sprintf( 
     258            /* translators: %s: site name in subject for daily email */ 
    227259            __( '[%s] Years Ago Today daily update', 'years-ago-today' ), 
    228260            wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
    229261        ); 
     262    } 
     263 
     264    /** 
     265     * Amends a user-specific footer to an email body. 
     266     * 
     267     * Adds an explanation about the email to the recipient. Serves to remind 
     268     * the user why they are receiving the email, what it is about, and how to 
     269     * stop it. 
     270     * 
     271     * @since 1.2 
     272     * 
     273     * @param  int    $user_id The user ID. 
     274     * @param  string $body.   The email body. 
     275     * @return string 
     276     */ 
     277    public static function add_user_email_footer( $user_id, $body ) { 
     278        $body .= "\n\n\n-------------------------------\n"; 
     279        $body .= sprintf( 
     280            __( 'You received this email because you have opted into receiving a daily email about posts published on this day in years past on the site %s, which is using the Years Ago Today plugin.', 'years-ago-today' ), 
     281            wp_specialchars_decode( get_option('blogname'), ENT_QUOTES ) 
     282        ); 
     283        $body .= "\n\n"; 
     284        $body .= sprintf( 
     285            __( 'If you wish to discontinue receiving these emails, simply log into the site and visit your profile at %s to uncheck the checkbox labeled "Email me daily about posts published on this day in years past."', 'years-ago-today' ), 
     286            get_edit_profile_url( $user_id ) 
     287        ); 
     288        $body .= "\n"; 
     289 
     290        return $body; 
     291    } 
     292 
     293    /** 
     294     * Sends out daily email. 
     295     * 
     296     * @since 1.0 
     297     * @todo  Handle large volume of users better, perhaps via chunked BCCs. 
     298     */ 
     299    public static function cron_email() { 
     300        // Get list of users who want the daily email. 
     301        $users = self::get_users_to_email(); 
     302 
     303        // If no one wants the email, there's nothing else to do. 
     304        if ( ! $users ) { 
     305            return; 
     306        } 
     307 
     308        // Get the content of the email. 
     309        $subject = self::get_email_subject(); 
     310        $body    = self::get_email_body(); 
     311 
     312        // If no subject or body for the email, then there's nothing else to do. 
     313        if ( ! $subject || ! $body ) { 
     314            return; 
     315        } 
    230316 
    231317        // Send email to each user. 
    232318        foreach ( $users as $user ) { 
    233319            if ( $user->user_email ) { 
    234                 wp_mail( $user->user_email, $subject, $body ); 
     320                wp_mail( $user->user_email, $subject, self::add_user_email_footer( $user->ID, $body ) ); 
    235321            } 
    236322        } 
     
    261347 
    262348        if ( $q->have_posts() ) : 
    263             echo '<p>' . __( 'The following post(s) have been published to the site on this day in previous years:', 'years-ago-today' ) . '</p>'; 
     349            echo '<p>'; 
     350            echo sprintf( 
     351                /* translators: 1: number of posts, 2: site name, 2: date string for today */ 
     352                _n( 
     353                    '<strong>%1$d</strong> post has been published on <strong>%2$s</strong> in a previous year:', 
     354                    '<strong>%1$d</strong> posts have been published on <strong>%2$s</strong> in previous years:', 
     355                    $q->post_count, 
     356                    'years-ago-today' 
     357                ), 
     358                $q->post_count, 
     359                /* translators: date string for today */ 
     360                date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
     361            ); 
     362            echo '</p>'; 
    264363            echo '<ul class="years-ago-today-posts">'; 
    265364            $year = ''; 
    266             while ( $q->have_posts() ) : $q->the_post(); 
     365            while ( $q->have_posts() ) : 
     366                $q->the_post(); 
    267367                $this_year = get_the_date( 'Y' ); 
    268368                // Only output the year once. 
     
    276376            echo '</ul>'; 
    277377        else : 
    278             echo '<p>' . __( 'No posts were published on this day from any past year.', 'years-ago-today' ) . '</p>'; 
     378            echo '<p>'; 
     379            printf( 
     380                /* translators: %s: date string for today */ 
     381                __( 'No posts were published on <strong>%s</strong> from any past year.', 'years-ago-today' ), 
     382                /* translators: date string for today */ 
     383                date_i18n( __( 'M jS' ), current_time( 'timestamp' ) ) 
     384            ); 
     385            echo '</p>'; 
    279386        endif; 
    280387 
    281388        echo '</div>'; 
    282     } 
    283  
    284     /** 
    285      * Adjusts WHERE clause to include date range to find years ago posts. 
    286      * 
    287      * @since 1.0 
    288      * 
    289      * @param string   $where The SQL WHERE clause. 
    290      * @param WP_Query $query The query object. 
    291      * @return string 
    292      */ 
    293     public static function add_year_clause_to_query( $where, $query ) { 
    294         global $wpdb; 
    295  
    296         if ( isset( $query->query_vars['is_years_ago_today'] ) && '1' == $query->query_vars['is_years_ago_today'] ) { 
    297  
    298             $first_year = self::get_first_published_year(); 
    299             $current_year = mysql2date( 'Y', current_time( 'mysql' ) ); 
    300  
    301             $years = range( $first_year, $current_year - 1 ); 
    302             $now   = current_time( 'timestamp' ); 
    303             $month = mysql2date( 'm', $now ); 
    304             $day   = mysql2date( 'd', $now ); 
    305  
    306             // Check data with more performant BETWEEN rather than using DATE() 
    307             // or its variations (YEAR(), MONTH(), DAYOFMONTH()). 
    308             $date_ranges = array(); 
    309             foreach ( $years as $year ) { 
    310                 $date_ranges[] = $wpdb->prepare( 
    311                     '( post_date_gmt BETWEEN %s AND %s )', 
    312                     "${year}-${month}-{$day} 00:00:00", 
    313                     "${year}-${month}-{$day} 23:59:59" 
    314                 ); 
    315             } 
    316  
    317             if ( $date_ranges ) { 
    318                 $where .= ' AND (' . implode( ' OR ', $date_ranges ) . ' ) '; 
    319             } 
    320  
    321         } 
    322  
    323         return $where; 
    324389    } 
    325390 
     
    340405        } 
    341406 
    342         // If not in the cache, figure it out.', 
     407        // If not in the cache, figure it out. 
    343408        if ( false === $first_year ) { 
    344             // Query for the earlies published year. 
     409            // Query for the earliest published year. 
    345410            $first_year = $wpdb->get_var( "SELECT YEAR(MIN(post_date)) FROM $wpdb->posts WHERE post_status IN ( 'publish', 'private' )" ); 
    346411 
     
    363428     * @since 1.0 
    364429     * 
    365      * @param bool            $return_posts True to return just an array of posts, false to return WP_Query object. Default false. 
    366      * @return array|WP_Query Array is return_posts is true, WP_Query if false. 
     430     * @param bool $return_posts Return array of queried posts or the WP_Query 
     431     *                           object? True to return array posts, false to 
     432     *                           return WP_Query object. Default false. 
     433     * @return array|WP_Query    Array if return_posts is true, WP_Query if false. 
    367434     */ 
    368435    public static function get_posts( $return_posts = false ) { 
     436        $first_year   = self::get_first_published_year(); 
     437        $current_year = mysql2date( 'Y', current_time( 'mysql' ) ); 
     438 
     439        $years = range( $first_year, $current_year - 1 ); 
     440        $now   = current_time( 'timestamp' ); 
     441        $month = mysql2date( 'm', $now ); 
     442        $day   = mysql2date( 'd', $now ); 
     443 
    369444        $query = new WP_Query( array( 
    370             'post_parent'        => '', 
    371             'post_status'        => array( 'publish' ), 
    372             'post_type'          => array( 'post' ), 
    373             'posts_per_page'     => -1, 
    374             'is_years_ago_today' => 1, 
     445            'post_parent'    => '', 
     446            'post_status'    => array( 'publish' ), 
     447            'post_type'      => array( 'post' ), 
     448            'posts_per_page' => -1, 
     449            'date_query'     => array( 
     450                'year'  => $years, 
     451                'month' => $month, 
     452                'day'   => $day, 
     453            ), 
    375454        ) ); 
    376455 
     
    379458 
    380459    /** 
    381      * Adds hook to outputs CSS for the display of the Trashed By column if 
    382      * on the appropriate admin page. 
     460     * Adds hook to outputs CSS for the display of the Years Ago today widget. 
    383461     * 
    384462     * @since 1.0 
     
    420498     * 
    421499     * @param  int  $user_id The user ID. 
    422      * @return bool True if the option saved successfully. 
     500     * @return bool          True if the option saved successfully. 
    423501     */ 
    424502    public static function option_save( $user_id ) { 
Note: See TracChangeset for help on using the changeset viewer.