/**
  * Counts how many posts don't have a bitly url yet.
  * 
  * @subcommand count-posts-missing-url
  */
 public function count_posts_missing_url($args, $assoc_args)
 {
     global $wpdb;
     $post_type_sql = '';
     // get the post types that are supported
     $post_types = bitly_get_post_types();
     // build the sql for querying post types
     if (count($post_types)) {
         foreach ($post_types as $post_type) {
             $sanitized_post_types[] = $wpdb->prepare('%s', $post_type);
         }
         $post_type_sql = sprintf('%s IN ( %s )', "{$wpdb->posts}.post_type", implode(',', $sanitized_post_types));
     }
     // Only do the query if there's post_type sql
     if (empty($post_type_sql)) {
         WP_CLI::error('No supported post types found');
     }
     $query = "\n\t\t\tSELECT COUNT(*)\n\t\t\tFROM {$wpdb->posts}\n\t\t\tLEFT JOIN {$wpdb->postmeta} ON ( {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = 'bitly_url' ) \n\t\t\tWHERE 1=1\n\t\t\tAND ( {$post_type_sql} )\n\t\t\tAND ( {$wpdb->posts}.post_status = 'publish' )\n\t\t\tAND ( {$wpdb->postmeta}.post_id IS NULL )\n\t\t\tGROUP BY {$wpdb->posts}.ID\n\t\t";
     // Get the posts
     $count = $wpdb->query($query);
     WP_CLI::success(sprintf('Found %d posts without a bit.ly url', $count));
 }
/**
 * Cron to process all of the posts that don't have bitly urls
 */
function bitly_process_posts($hourly_limit = null)
{
    global $wpdb;
    if (!bitly_is_url_generation_enabled()) {
        bitly_log('Bit.ly backfill is currently disabled via code');
        return;
    }
    // Check if we should even be running this
    $bitly_processed = get_option('bitly_processed');
    if (!empty($bitly_processed)) {
        bitly_log("All bit.ly URLs were processed. Run reset_process_status if you think this is in error and try again.");
        return;
    }
    // Use the default limit if one was not set
    if (empty($hourly_limit) || !is_numeric($hourly_limit)) {
        $hourly_limit = apply_filters('bitly_hourly_limit', 100);
    }
    // Generate a shortlink for the homepage, if it doesn't exist
    $blog_shortlink = bitly_get_blog_url();
    if (!$blog_shortlink) {
        bitly_log("Set short URL for blog");
        bitly_generate_blog_short_url();
    }
    $post_type_sql = "";
    // get the post types that are supported
    $post_types = bitly_get_post_types();
    // build the sql for querying post types
    if (count($post_types)) {
        foreach ($post_types as $post_type) {
            $sanitized_post_types[] = $wpdb->prepare('%s', $post_type);
        }
        $post_type_sql = sprintf('%s IN ( %s )', "{$wpdb->posts}.post_type", implode(',', $sanitized_post_types));
    }
    // Only do the query if there's post_type sql
    if (!empty($post_type_sql)) {
        bitly_log("Starting to process posts without bit.ly short URLs with a limit of {$hourly_limit}");
        // Get $limit published posts that don't have a bitly url
        // Only query for a maximum of 100 posts at a time
        $processed = 0;
        $per_page = 100;
        do {
            $query = "\n\t\t\t\tSELECT {$wpdb->posts}.ID\n\t\t\t\tFROM {$wpdb->posts}\n\t\t\t\tLEFT JOIN {$wpdb->postmeta} ON ( {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key =  'bitly_url' ) \n\t\t\t\tWHERE 1=1\n\t\t\t\tAND ( {$post_type_sql} )\n\t\t\t\tAND ( {$wpdb->posts}.post_status = 'publish' )\n\t\t\t\tAND ( {$wpdb->postmeta}.post_id IS NULL )\n\t\t\t\tGROUP BY {$wpdb->posts}.ID\n\t\t\t\tORDER BY {$wpdb->posts}.post_date DESC\n\t\t\t\tLIMIT {$per_page}\n\t\t\t";
            // Get the posts
            $posts = $wpdb->get_results($query);
            // Increment the counter
            $processed += count($posts);
            // This could be empty if there was no $post_type_sql
            if (!empty($posts)) {
                // Process these posts
                foreach ($posts as $p) {
                    bitly_log("Generating short_url for post ID {$p->ID}");
                    bitly_generate_short_url($p->ID);
                }
            } else {
                // Kill our scheduled event
                bitly_log("No posts were found. Killing the event.");
                bitly_processed();
            }
            bitly_log("Processed {$processed} posts");
            sleep(2);
        } while (count($posts) && $processed < $hourly_limit);
    } else {
        // Kill our scheduled event
        bitly_log("No bit.ly post types were found. Killing the event.");
        bitly_processed();
    }
    // If $per_page isn't equal to the number of posts found on the last run, we should disable this forever
    if ($per_page != count($posts)) {
        bitly_log("All bit.ly posts were processed. Killing the event.");
        bitly_processed();
    }
}