From 0a380d3d228ebaf289ddca31bbcfc34a6b058f60 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Thu, 16 Apr 2015 18:45:24 -0500 Subject: [PATCH 01/27] Add our oEmbed service for raw URLs Very simplistic implementation: recognizes raw URLs as supported oEmbeddable objects. Doesn't allow any parameter setting. Also tweaked README a little. Affects #16 Closes #8 --- documentcloud.php | 27 +++++++++++++++++++++++---- readme.txt | 5 ++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index ce2ac1a..6541829 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -3,7 +3,7 @@ * Plugin Name: DocumentCloud * Plugin URI: https://www.documentcloud.org/ * Description: Embed DocumentCloud resources in WordPress content. - * Version: 0.1.1 + * Version: 0.1.2 * Authors: Chris Amico, Justin Reese * License: GPLv2 ***/ @@ -29,17 +29,36 @@ class WP_DocumentCloud { function __construct() { + // Register us as an oEmbed provider + add_action('init', array(&$this, 'register_dc_oembed_provider')); + // Register [documentcloud] shortcode using old embed method add_shortcode('documentcloud', array(&$this, 'embed_shortcode')); + // Setup TinyMCE shortcode-generation plugin add_action('init', array(&$this, 'register_tinymce_filters')); - + + // Process shortcodes and add admin settings add_action('save_post', array(&$this, 'save')); - add_action('admin_menu', array(&$this, 'add_options_page')); - add_action('admin_init', array(&$this, 'settings_init')); } + function register_dc_oembed_provider() { + /* + Hello developer. If you wish to test this plugin against your + local installation of DocumentCloud (with its own testing + domain), uncomment-out the next three lines and replace + `[your_domain]` with, uh, your domain. You'll also want to keep + the provider HTTP unless cURL can happily access your domain via + HTTPS. Please remember not to commit these back to the repo. + */ + // add_filter( 'http_request_host_is_external', '__return_true' ); + // wp_oembed_add_provider('http://[your_domain]/documents/*','http://[your_domain]/api/oembed.{format}'); + // wp_oembed_add_provider('https://[your_domain]/documents/*','http://[your_domain]/api/oembed.{format}'); + + wp_oembed_add_provider('https://www.documentcloud.org/documents/*', 'https://www.documentcloud.org/api/oembed.{format}'); + } + function register_tinymce_filters() { add_filter('mce_external_plugins', array(&$this, 'add_tinymce_plugin') diff --git a/readme.txt b/readme.txt index a9a80d4..4944989 100644 --- a/readme.txt +++ b/readme.txt @@ -9,7 +9,7 @@ Embed DocumentCloud resources in WordPress content. == Description == -[DocumentCloud](https://www.documentcloud.org/) is a free service allowing journalists to analyze, annotate and publish documents, funded by the Knight Foundation. Initial development of this plugin supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. +[DocumentCloud](https://www.documentcloud.org/) is a service that allows journalists to analyze, annotate and publish documents, hosted by Investigative Reporters & Editors. Initial development of this plugin supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. DocumentCloud's normal embed code looks like this: @@ -43,5 +43,4 @@ This will use default height and width settings, which you can update in the Wor 1. Upload the documentcloud directory to `wp-content/plugins/documentcloud` 2. Activate the plugin -3. In your posts, add documents using the DocumentCloud button, or the `[documentcloud]` shortcode. - +3. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode From aa8af3265d2df9f21c7748356386612cc11d3cd7 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Fri, 17 Apr 2015 18:47:41 -0500 Subject: [PATCH 02/27] Generate embeds using oEmbed * Fetch embed codes from the new oEmbed service instead of creating them manually (but leave existing functions in place until we're sure they can be discarded) * Support both `maxwidth/maxheight` and `height/width` shortcode attrs, but only sends `max*` to the provider * Nominally backwards-compatible with existing shortcodes and settings (should be tested) * Piggy-backs on WordPress's internal oembed caching; to disable, change `add_shortcode('documentcloud', array(&$this, 'handle_dc_shortcode_with_caching'));` to `add_shortcode('documentcloud', array(&$this, 'handle_dc_shortcode'));` Affects #16 Closes #14 --- documentcloud.php | 154 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 147 insertions(+), 7 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index 6541829..a8860e5 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -3,7 +3,7 @@ * Plugin Name: DocumentCloud * Plugin URI: https://www.documentcloud.org/ * Description: Embed DocumentCloud resources in WordPress content. - * Version: 0.1.2 + * Version: 0.2 * Authors: Chris Amico, Justin Reese * License: GPLv2 ***/ @@ -29,18 +29,22 @@ class WP_DocumentCloud { function __construct() { - // Register us as an oEmbed provider add_action('init', array(&$this, 'register_dc_oembed_provider')); - // Register [documentcloud] shortcode using old embed method - add_shortcode('documentcloud', array(&$this, 'embed_shortcode')); - + add_shortcode('documentcloud', array(&$this, 'handle_dc_shortcode_with_caching')); + add_filter('oembed_fetch_url', array(&$this, 'add_dc_arguments'), 10, 3); + // Setup TinyMCE shortcode-generation plugin add_action('init', array(&$this, 'register_tinymce_filters')); - // Process shortcodes and add admin settings - add_action('save_post', array(&$this, 'save')); + // Setup admin settings add_action('admin_menu', array(&$this, 'add_options_page')); add_action('admin_init', array(&$this, 'settings_init')); + + // Register [documentcloud] shortcode using old embed method + // add_shortcode('documentcloud', array(&$this, 'embed_shortcode')); + + // Store metadata upon post save + // add_action('save_post', array(&$this, 'save')); } function register_dc_oembed_provider() { @@ -56,9 +60,143 @@ function register_dc_oembed_provider() { // wp_oembed_add_provider('http://[your_domain]/documents/*','http://[your_domain]/api/oembed.{format}'); // wp_oembed_add_provider('https://[your_domain]/documents/*','http://[your_domain]/api/oembed.{format}'); + wp_oembed_add_provider('http://www.documentcloud.org/documents/*', 'https://www.documentcloud.org/api/oembed.{format}'); wp_oembed_add_provider('https://www.documentcloud.org/documents/*', 'https://www.documentcloud.org/api/oembed.{format}'); } + function default_dc_atts() { + // Notably, `maxwidth/maxheight` are NOT set here, even though + // they are proper attributes, because we let the user set them + // in the settings area. See notes on `handle_dc_shortcode()`. + return array( + 'url' => null, + 'container' => null, + 'notes' => null, + 'responsive_offset' => null, + 'default_page' => null, + 'default_note' => null, + 'zoom' => null, + 'search' => null, + 'sidebar' => 'false', // Backwards-compatibility + 'text' => 'true', // Backwards-compatibility + 'pdf' => 'true', // Backwards-compatibility + 'responsive' => null, + ); + } + + function add_dc_arguments($provider, $url, $args) { + foreach ($args as $key => $value) { + switch ($key) { + // We don't want to pass these three to the provider + case 'height': + case 'width': + case 'discover': + break; + default: + $provider = add_query_arg( $key, $value, $provider ); + break; + } + } + return $provider; + } + + function handle_dc_shortcode($atts) { + $filtered_atts = shortcode_atts($this->default_dc_atts(), $atts); + + // This is a tricky bit of logic that ends up: + // 1. Allowing both `width/height` and `maxwidth/maxheight` as + // acceptable shortcode parameters; + // 2. Only sending `maxwidth/maxheight` to the oEmbed service; + // 3. Respecting the user's settings + // To understand it, you must deeply understand the flow of + // data through the WordPress bowels, or at least misunderstand + // it in the same way we do. It could likely be cleaned up, + // but should be WELL TESTED if so. + if (isset($atts['maxheight'])) { + $filtered_atts['maxheight'] = $atts['maxheight']; + } else if (isset($atts['height'])) { + $filtered_atts['maxheight'] = $atts['height']; + } else { + $filtered_atts['maxheight'] = get_option('documentcloud_default_height', 600); + } + if (isset($atts['maxwidth'])) { + $filtered_atts['maxwidth'] = $atts['maxwidth']; + } else if (isset($atts['width'])) { + $filtered_atts['maxwidth'] = $atts['width']; + } else { + $filtered_atts['maxwidth'] = get_option('documentcloud_default_width', 620); + } + + // Either the `url` or `id` attributes are required, but `id` + // is only supported for backwards compatibility. If it's used, + // we force this to embed a document. I.e., it can't be used + // for embedding notes, pages, or other non-document resources. + if (!$atts['url']) { + if (!$atts['id']) { + return ''; + } + else { + $url = $filtered_atts['url'] = "https://www.documentcloud.org/documents/{$atts['id']}.html"; + } + } else { + $url = $atts['url']; + } + + return wp_oembed_get($url, $filtered_atts); + } + + // This is an exact clone of `handle_dc_shortcode`, except that it + // lets WordPress cache the result of the oEmbed call. Thanks to + // http://bit.ly/1HykA0U for this pattern. + function handle_dc_shortcode_with_caching($atts) { + global $wp_embed; + + $filtered_atts = shortcode_atts($this->default_dc_atts(), $atts); + + // This is a tricky bit of logic that ends up: + // 1. Allowing both `width/height` and `maxwidth/maxheight` as + // acceptable shortcode parameters; + // 2. Only sending `maxwidth/maxheight` to the oEmbed service; + // 3. Respecting the user's settings + // To understand it, you must deeply understand the flow of + // data through the WordPress bowels, or at least misunderstand + // it in the same way we do. It could likely be cleaned up, + // but should be WELL TESTED if so. + if (isset($atts['maxheight'])) { + $filtered_atts['maxheight'] = $atts['maxheight']; + } else if (isset($atts['height'])) { + $filtered_atts['maxheight'] = $atts['height']; + } else { + $filtered_atts['maxheight'] = get_option('documentcloud_default_height', 600); + } + if (isset($atts['maxwidth'])) { + $filtered_atts['maxwidth'] = $atts['maxwidth']; + } else if (isset($atts['width'])) { + $filtered_atts['maxwidth'] = $atts['width']; + } else { + $filtered_atts['maxwidth'] = get_option('documentcloud_default_width', 620); + } + + // Either the `url` or `id` attributes are required, but `id` + // is only supported for backwards compatibility. If it's used, + // we force this to embed a document. I.e., it can't be used + // for embedding notes, pages, or other non-document resources. + if (!$atts['url']) { + if (!$atts['id']) { + return ''; + } + else { + $url = $filtered_atts['url'] = "https://www.documentcloud.org/documents/{$atts['id']}.html"; + } + } else { + $url = $atts['url']; + } + + return $wp_embed->shortcode($filtered_atts, $url); + } + + // TinyMCE and settings page + function register_tinymce_filters() { add_filter('mce_external_plugins', array(&$this, 'add_tinymce_plugin') @@ -148,6 +286,8 @@ function full_width_field() { function settings_section() {} + // Hopefully can remove from here down? + function save($post_id) { // tell the post if we're carrying a wide load From 7b10de000b0bf5a23b7be03a40f0ca7705595b5c Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Fri, 17 Apr 2015 19:07:56 -0500 Subject: [PATCH 03/27] Store settings as constants and reduce redundancy * Create class constants for regularly-modifiable settings (mostly for testing) * Consolidate cached and non-cached shortcode call and just toggle where it mattesr Affects #16 --- documentcloud.php | 78 ++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 59 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index a8860e5..192e544 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -26,11 +26,15 @@ */ class WP_DocumentCloud { + + const CACHING_ENABLED = false, + OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', + OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org'; function __construct() { add_action('init', array(&$this, 'register_dc_oembed_provider')); - add_shortcode('documentcloud', array(&$this, 'handle_dc_shortcode_with_caching')); + add_shortcode('documentcloud', array(&$this, 'handle_dc_shortcode')); add_filter('oembed_fetch_url', array(&$this, 'add_dc_arguments'), 10, 3); // Setup TinyMCE shortcode-generation plugin @@ -51,17 +55,15 @@ function register_dc_oembed_provider() { /* Hello developer. If you wish to test this plugin against your local installation of DocumentCloud (with its own testing - domain), uncomment-out the next three lines and replace - `[your_domain]` with, uh, your domain. You'll also want to keep - the provider HTTP unless cURL can happily access your domain via - HTTPS. Please remember not to commit these back to the repo. + domain), set the OEMBED_PROVIDER and OEMBED_RESOURCE_DOMAIN + constants above to your local testing domain. You'll also want + to uncomment the next line to let WordPress connect to local + domains. */ - // add_filter( 'http_request_host_is_external', '__return_true' ); - // wp_oembed_add_provider('http://[your_domain]/documents/*','http://[your_domain]/api/oembed.{format}'); - // wp_oembed_add_provider('https://[your_domain]/documents/*','http://[your_domain]/api/oembed.{format}'); + // add_filter( 'http_request_host_is_external', '__return_true'); - wp_oembed_add_provider('http://www.documentcloud.org/documents/*', 'https://www.documentcloud.org/api/oembed.{format}'); - wp_oembed_add_provider('https://www.documentcloud.org/documents/*', 'https://www.documentcloud.org/api/oembed.{format}'); + wp_oembed_add_provider("http://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); + wp_oembed_add_provider("https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); } function default_dc_atts() { @@ -136,63 +138,21 @@ function handle_dc_shortcode($atts) { return ''; } else { - $url = $filtered_atts['url'] = "https://www.documentcloud.org/documents/{$atts['id']}.html"; + $url = $filtered_atts['url'] = "https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/{$atts['id']}.html"; } } else { $url = $atts['url']; } - return wp_oembed_get($url, $filtered_atts); - } - - // This is an exact clone of `handle_dc_shortcode`, except that it - // lets WordPress cache the result of the oEmbed call. Thanks to - // http://bit.ly/1HykA0U for this pattern. - function handle_dc_shortcode_with_caching($atts) { - global $wp_embed; - - $filtered_atts = shortcode_atts($this->default_dc_atts(), $atts); - - // This is a tricky bit of logic that ends up: - // 1. Allowing both `width/height` and `maxwidth/maxheight` as - // acceptable shortcode parameters; - // 2. Only sending `maxwidth/maxheight` to the oEmbed service; - // 3. Respecting the user's settings - // To understand it, you must deeply understand the flow of - // data through the WordPress bowels, or at least misunderstand - // it in the same way we do. It could likely be cleaned up, - // but should be WELL TESTED if so. - if (isset($atts['maxheight'])) { - $filtered_atts['maxheight'] = $atts['maxheight']; - } else if (isset($atts['height'])) { - $filtered_atts['maxheight'] = $atts['height']; + if (WP_DocumentCloud::CACHING_ENABLED) { + // This lets WordPress cache the result of the oEmbed call. + // Thanks to http://bit.ly/1HykA0U for this pattern. + global $wp_embed; + return $wp_embed->shortcode($filtered_atts, $url); } else { - $filtered_atts['maxheight'] = get_option('documentcloud_default_height', 600); - } - if (isset($atts['maxwidth'])) { - $filtered_atts['maxwidth'] = $atts['maxwidth']; - } else if (isset($atts['width'])) { - $filtered_atts['maxwidth'] = $atts['width']; - } else { - $filtered_atts['maxwidth'] = get_option('documentcloud_default_width', 620); - } - - // Either the `url` or `id` attributes are required, but `id` - // is only supported for backwards compatibility. If it's used, - // we force this to embed a document. I.e., it can't be used - // for embedding notes, pages, or other non-document resources. - if (!$atts['url']) { - if (!$atts['id']) { - return ''; - } - else { - $url = $filtered_atts['url'] = "https://www.documentcloud.org/documents/{$atts['id']}.html"; - } - } else { - $url = $atts['url']; + return wp_oembed_get($url, $filtered_atts); } - return $wp_embed->shortcode($filtered_atts, $url); } // TinyMCE and settings page From 690dff1fa0ae29d25acc27e4a7c9d529b3701271 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Mon, 20 Apr 2015 17:50:25 -0500 Subject: [PATCH 04/27] Simplify height/width calculations I previously overcomplicated the height/width calculations out of deference to WordPress's internal height/width calculator. Realized the plugin already set its own defaults and thus I could simplify things by starting with that, and maintain better backwards-compatibility too. * Remove complicated height/width calculations * Make precedence order clear Affects #16 --- documentcloud.php | 72 +++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index 192e544..86a558c 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -27,9 +27,11 @@ class WP_DocumentCloud { - const CACHING_ENABLED = false, - OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', - OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org'; + const CACHING_ENABLED = false, + DEFAULT_EMBED_HEIGHT = 620, + DEFAULT_EMBED_WIDTH = 600, + OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', + OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org'; function __construct() { @@ -66,10 +68,8 @@ function register_dc_oembed_provider() { wp_oembed_add_provider("https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); } - function default_dc_atts() { - // Notably, `maxwidth/maxheight` are NOT set here, even though - // they are proper attributes, because we let the user set them - // in the settings area. See notes on `handle_dc_shortcode()`. + function get_default_atts() { + // TODO: Add admin options to adjust all defaults. return array( 'url' => null, 'container' => null, @@ -79,20 +79,31 @@ function default_dc_atts() { 'default_note' => null, 'zoom' => null, 'search' => null, - 'sidebar' => 'false', // Backwards-compatibility - 'text' => 'true', // Backwards-compatibility - 'pdf' => 'true', // Backwards-compatibility - 'responsive' => null, + 'responsive' => 'true', + // The following defaults match the existing plugin, except + // `height/width` are prefixed `max*` per the oEmbed spec. + // You can still use `height/width` for backwards + // compatibility, but they'll be mapped to `max*`. + // Precedence (lower number == higher priority): + // 1. `width` on shortcode + // 2. `maxwidth` from shortcode + // 3. Settings > DocumentCloud > "Default embed width" + // 4. `WP_DocumentCloud::DEFAULT_EMBED_WIDTH` + 'maxheight' => intval(get_option('documentcloud_default_height', WP_DocumentCloud::DEFAULT_EMBED_HEIGHT)), + 'maxwidth' => intval(get_option('documentcloud_default_width', WP_DocumentCloud::DEFAULT_EMBED_WIDTH)), + 'sidebar' => 'false', + 'text' => 'true', + 'pdf' => 'true', ); } function add_dc_arguments($provider, $url, $args) { foreach ($args as $key => $value) { switch ($key) { - // We don't want to pass these three to the provider case 'height': case 'width': case 'discover': + // Don't pass these attributes to the provider break; default: $provider = add_query_arg( $key, $value, $provider ); @@ -103,31 +114,10 @@ function add_dc_arguments($provider, $url, $args) { } function handle_dc_shortcode($atts) { - $filtered_atts = shortcode_atts($this->default_dc_atts(), $atts); - - // This is a tricky bit of logic that ends up: - // 1. Allowing both `width/height` and `maxwidth/maxheight` as - // acceptable shortcode parameters; - // 2. Only sending `maxwidth/maxheight` to the oEmbed service; - // 3. Respecting the user's settings - // To understand it, you must deeply understand the flow of - // data through the WordPress bowels, or at least misunderstand - // it in the same way we do. It could likely be cleaned up, - // but should be WELL TESTED if so. - if (isset($atts['maxheight'])) { - $filtered_atts['maxheight'] = $atts['maxheight']; - } else if (isset($atts['height'])) { - $filtered_atts['maxheight'] = $atts['height']; - } else { - $filtered_atts['maxheight'] = get_option('documentcloud_default_height', 600); - } - if (isset($atts['maxwidth'])) { - $filtered_atts['maxwidth'] = $atts['maxwidth']; - } else if (isset($atts['width'])) { - $filtered_atts['maxwidth'] = $atts['width']; - } else { - $filtered_atts['maxwidth'] = get_option('documentcloud_default_width', 620); - } + $default_atts = $this->get_default_atts(); + // Smooshes together passed-in shortcode attributes with + // default attributes/values. + $filtered_atts = shortcode_atts($default_atts, $atts); // Either the `url` or `id` attributes are required, but `id` // is only supported for backwards compatibility. If it's used, @@ -144,6 +134,14 @@ function handle_dc_shortcode($atts) { $url = $atts['url']; } + // `height/width` beat `maxheight/maxwidth`; see full precedence list in `get_default_atts(). + if (isset($atts['height'])) { + $filtered_atts['maxheight'] = $atts['height']; + } + if (isset($atts['width'])) { + $filtered_atts['maxwidth'] = $atts['width']; + } + if (WP_DocumentCloud::CACHING_ENABLED) { // This lets WordPress cache the result of the oEmbed call. // Thanks to http://bit.ly/1HykA0U for this pattern. From 00c0b07539197a45adf7484e6933a76514b9554d Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Mon, 20 Apr 2015 17:52:22 -0500 Subject: [PATCH 05/27] Support `format=wide` shortcode param And make it supreme above all other width declarations to be consistent with previous plugin behavior. Affects #16 --- documentcloud.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/documentcloud.php b/documentcloud.php index 86a558c..b4d124c 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -30,6 +30,7 @@ class WP_DocumentCloud { const CACHING_ENABLED = false, DEFAULT_EMBED_HEIGHT = 620, DEFAULT_EMBED_WIDTH = 600, + DEFAULT_EMBED_FULL_WIDTH = 940, OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org'; @@ -91,6 +92,7 @@ function get_default_atts() { // 4. `WP_DocumentCloud::DEFAULT_EMBED_WIDTH` 'maxheight' => intval(get_option('documentcloud_default_height', WP_DocumentCloud::DEFAULT_EMBED_HEIGHT)), 'maxwidth' => intval(get_option('documentcloud_default_width', WP_DocumentCloud::DEFAULT_EMBED_WIDTH)), + 'format' => 'normal', 'sidebar' => 'false', 'text' => 'true', 'pdf' => 'true', @@ -100,6 +102,7 @@ function get_default_atts() { function add_dc_arguments($provider, $url, $args) { foreach ($args as $key => $value) { switch ($key) { + case 'format': case 'height': case 'width': case 'discover': @@ -142,6 +145,16 @@ function handle_dc_shortcode($atts) { $filtered_atts['maxwidth'] = $atts['width']; } + // If the format is set to wide, it blows away all other width + // settings. + if ($filtered_atts['format'] == 'wide') { + $filtered_atts['maxwidth'] = get_option('documentcloud_full_width', DEFAULT_EMBED_FULL_WIDTH); + } + + // For the benefit of some templates + global $post; + $is_wide = intval($filtered_atts['maxwidth']) > $default_atts['maxwidth']; + if (WP_DocumentCloud::CACHING_ENABLED) { // This lets WordPress cache the result of the oEmbed call. // Thanks to http://bit.ly/1HykA0U for this pattern. @@ -153,7 +166,7 @@ function handle_dc_shortcode($atts) { } - // TinyMCE and settings page + // Setup TinyMCE shortcode button function register_tinymce_filters() { add_filter('mce_external_plugins', From 95d0c872de228fbc6eb14fa76896c568e3b8b7e0 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Mon, 20 Apr 2015 17:54:24 -0500 Subject: [PATCH 06/27] Re-enable saving post metadata * Adjust `save()` as minimally as necessary to support new function names and the dual-`width/maxwidth` presence * Add note re: need for new post_metadata key * Add note re: functions we should be able to remove once tested Affects #16 --- documentcloud.php | 52 ++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index b4d124c..f5877bf 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -51,7 +51,7 @@ function __construct() { // add_shortcode('documentcloud', array(&$this, 'embed_shortcode')); // Store metadata upon post save - // add_action('save_post', array(&$this, 'save')); + add_action('save_post', array(&$this, 'save')); } function register_dc_oembed_provider() { @@ -190,21 +190,8 @@ function register_button($buttons) { return $buttons; } - function get_defaults() { - // add admin options to adjust these defaults - // storing js params as strings instead of real booleans - return array( - 'url' => null, - 'id' => null, - 'height' => get_option('documentcloud_default_height', 600), - 'width' => get_option('documentcloud_default_width', 620), - 'format' => 'normal', - 'sidebar' => 'false', - 'text' => 'true', - 'pdf' => 'true' - ); - } - + // Setup settings for plugin + function add_options_page() { add_options_page('DocumentCloud', 'DocumentCloud', 'manage_options', 'documentcloud', array(&$this, 'render_options_page')); @@ -257,8 +244,6 @@ function full_width_field() { function settings_section() {} - // Hopefully can remove from here down? - function save($post_id) { // tell the post if we're carrying a wide load @@ -270,7 +255,7 @@ function save($post_id) { )) ) { return; } - $defaults = $this->get_defaults(); + $defaults = $this->get_default_atts(); $wide_assets = get_post_meta($post_id, 'wide_assets', true); $documents = get_post_meta($post_id, 'documentcloud', true); $matches = array(); @@ -283,6 +268,11 @@ function save($post_id) { $atts = shortcode_parse_atts($args[$i]); $atts = shortcode_atts($defaults, $atts); + // TODO: Reconsider using document ID as array key, + // because we'll be using this same shortcode to + // consume more than just documents in the future. + // Perhaps we can use `url` as key? + // get a doc id to keep array keys consistent if (isset($atts['url']) && !isset($atts['id']) ) { $atts['id'] = $this->parse_id_from_url($atts['url']); @@ -290,7 +280,8 @@ function save($post_id) { // if no id, don't bother storing because it's wrong if ($atts['id'] != null) { - if ($atts['format'] == "wide" || $atts['width'] > $defaults['width']) { + $width = isset($atts['width']) ? $atts['width'] : $atts['maxwidth']; + if ($atts['format'] == "wide" || $width > $defaults['maxwidth']) { $wide_assets[$atts['id']] = true; } else { $wide_assets[$atts['id']] = false; @@ -303,7 +294,6 @@ function save($post_id) { } update_post_meta($post_id, 'documents', $documents); update_post_meta($post_id, 'wide_assets', $wide_assets); - } function parse_id_from_url($url) { @@ -316,6 +306,26 @@ function parse_id_from_url($url) { } } + // TODO: Remove this once we've ensured `handle_dc_shortcode()` + // replicates all the functionality properly. Note that `save()` + // has been adjusted to use `get_default_atts()`, but I left + // `embed_shortcode()` using `get_defaults()` for inspection. + + function get_defaults() { + // add admin options to adjust these defaults + // storing js params as strings instead of real booleans + return array( + 'url' => null, + 'id' => null, + 'height' => get_option('documentcloud_default_height', 600), + 'width' => get_option('documentcloud_default_width', 620), + 'format' => 'normal', + 'sidebar' => 'false', + 'text' => 'true', + 'pdf' => 'true' + ); + } + function embed_shortcode($atts, $content, $code) { global $post; $defaults = $this->get_defaults(); From 04d7a371dc3907d541548afe14e7f0e0b532d841 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Mon, 20 Apr 2015 17:54:38 -0500 Subject: [PATCH 07/27] Tweak note/formatting Affects #16 --- documentcloud.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index f5877bf..f29698f 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -124,7 +124,7 @@ function handle_dc_shortcode($atts) { // Either the `url` or `id` attributes are required, but `id` // is only supported for backwards compatibility. If it's used, - // we force this to embed a document. I.e., it can't be used + // we force this to embed a document. I.e., `id` can't be used // for embedding notes, pages, or other non-document resources. if (!$atts['url']) { if (!$atts['id']) { @@ -205,7 +205,7 @@ function render_options_page() { ?>

- + Date: Tue, 21 Apr 2015 10:27:30 -0500 Subject: [PATCH 08/27] Remove `responsive: 'true'` default Was committed accidentally. Not ready to be the default within WP. Affects #16 --- documentcloud.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentcloud.php b/documentcloud.php index f29698f..392d5cc 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -80,7 +80,7 @@ function get_default_atts() { 'default_note' => null, 'zoom' => null, 'search' => null, - 'responsive' => 'true', + 'responsive' => null, // The following defaults match the existing plugin, except // `height/width` are prefixed `max*` per the oEmbed spec. // You can still use `height/width` for backwards From 6bd58e77477206595b0572ee7b0deb009fad2906 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 21 Apr 2015 17:28:06 -0500 Subject: [PATCH 09/27] Updated readme with oEmbed info and new options Affects #16 --- readme.txt | 65 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/readme.txt b/readme.txt index 4944989..bfac92e 100644 --- a/readme.txt +++ b/readme.txt @@ -1,9 +1,11 @@ === DocumentCloud === Contributors: chrisamico, reefdog -Tags: documentcloud, documents +Tags: documentcloud, documents, journalism, reporting, research Requires at least: 3.2 -Tested up to: 3.9.1 +Tested up to: 4.1.1 Stable tag: trunk +License: GPLv2 +License URI: http://www.gnu.org/licenses/gpl-2.0.html Embed DocumentCloud resources in WordPress content. @@ -11,36 +13,49 @@ Embed DocumentCloud resources in WordPress content. [DocumentCloud](https://www.documentcloud.org/) is a service that allows journalists to analyze, annotate and publish documents, hosted by Investigative Reporters & Editors. Initial development of this plugin supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. -DocumentCloud's normal embed code looks like this: +This plugin allows you embed DocumentCloud documents using a custom shortcode: -
- - - -That works great as long as you edit in HTML mode. Switch to the visual editor, and your container `div` disappears and your JavaScript is broken. + [documentcloud url="http://www.documentcloud.org/documents/265231-11-07-2011-letter-to-idaho-congressional.html"] -To get around this, use this short code: +When you save, WordPress fetches and stores the actual embed code HTML from the DocumentCloud servers using oEmbed. You can freely toggle between visual and HTML mode without mangling embed code, and your embed will always be up to date with the latest embed code. - [documentcloud id="265231-11-07-2011-letter-to-idaho-congressional"] - -Or use the URL from DocumentCloud: +By default, the embed will be 600px wide and 620px tall. You can set your own defaults in Settings > DocumentCloud, or override the defaults on individual embeds using these attributes: - [documentcloud url="http://www.documentcloud.org/documents/265231-11-07-2011-letter-to-idaho-congressional.html"] + [documentcloud url="http://www.documentcloud.org/documents/265231-11-07-2011-letter-to-idaho-congressional.html" width="400" height="500"] -This will use default height and width settings, which you can update in the WordPress admin. To override defaults on a specific document, pass them into the shortcode: +Here's the full list of embed options you can pass via shortcode attributes: - [documentcloud id="265231-11-07-2011-letter-to-idaho-congressional" width="400" height="500" sidebar="true"] +- `url` (**required**, string): Full URL of the DocumentCloud resource. +- `container` (string): ID of element to insert the document into; if excluded, embedder will create its own container. +- `height` (integer): Height (in pixels) of the embed. +- `width` (integer): Width (in pixels) of the embed. +- `responsive` (boolean): Use responsive layout. +- `responsive_offset` (integer): Distance (in pixels) to vertically offset the viewer for some responsive embeds. +- `default_page` (integer): Page number to have the document scroll to by default. +- `default_note` (integer): ID of the note that the document should highlight by default. +- `notes` (boolean): Show/hide notes: +- `search` (boolean): Hide or show search form. +- `sidebar` (boolean): Hide or show sidebar. Defaults `false`. +- `pdf` (boolean): Hide or show link to download original PDF. +- `text` (boolean): Hide or show text tab. +- `zoom` (boolean): Hide or show zoom slider. +- `format` (string): Indicate to the theme that this is a wide asset by setting this to `wide`. Defaults `normal`. +You can read more about publishing and embedding DocumentCloud resources on https://www.documentcloud.org/help/publishing. == Installation == -1. Upload the documentcloud directory to `wp-content/plugins/documentcloud` -2. Activate the plugin -3. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode +1. Upload the contents of the plugin to `wp-content/plugins/documentcloud` +2. Activate the plugin through the "Plugins" menu +3. Optionally set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) +4. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode + +== Changelog == + += 0.2 = +* Fetch embed code via oEmbed instead of generating statically. +* Added new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. +* Deprecated `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. + += 0.1 = +* Initial release. \ No newline at end of file From 562d344d4a5a8d18034c39d2b6f9623d085fc32d Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 21 Apr 2015 17:43:14 -0500 Subject: [PATCH 10/27] Create README for GitHub too The readme.txt for WordPress looks ugly here at GitHub. Copy relevant info over. --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.txt | 6 +++--- 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..c6686e4 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# DocumentCloud WordPress plugin + +The DocumentCloud WordPress plugin lets you embed [DocumentCloud](https://www.documentcloud.org/) resources into WordPress content using [shortcodes](https://codex.wordpress.org/Shortcode_API). + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html"] + +## Installation + +1. Upload the contents of the plugin to `wp-content/plugins/documentcloud` +2. Activate the plugin through the "Plugins" menu +3. Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud +4. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode + +## Usage + +There are many options you can set using shortcode attributes: + +- `url` (**required**, string): Full URL of the DocumentCloud resource. +- `container` (string): ID of element to insert the document into; if excluded, embedder will create its own container. +- `height` (integer): Height (in pixels) of the embed. +- `width` (integer): Width (in pixels) of the embed. +- `responsive` (boolean): Use responsive layout. +- `responsive_offset` (integer): Distance (in pixels) to vertically offset the viewer for some responsive embeds. +- `default_page` (integer): Page number to have the document scroll to by default. +- `default_note` (integer): ID of the note that the document should highlight by default. +- `notes` (boolean): Show/hide notes: +- `search` (boolean): Hide or show search form. +- `sidebar` (boolean): Hide or show sidebar. Defaults `false`. +- `pdf` (boolean): Hide or show link to download original PDF. +- `text` (boolean): Hide or show text tab. +- `zoom` (boolean): Hide or show zoom slider. +- `format` (string): Indicate to the theme that this is a wide asset by setting this to `wide`. Defaults `normal`. + +For example, if you want to embed a document at 800px wide with no sidebar, pre-scrolled to page 3: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="800" sidebar="false" default_page="3"] + +## Changelog + +### 0.2 +* Fetch embed code via oEmbed instead of generating statically. +* Added new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. +* Deprecated `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. + +### 0.1 +* Initial release. + +## History + +Initial development of this plugin by Chris Amico (@eyeseast) supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. + +## License + +The DocumentCloud WordPress plugin is [GPLv2](http://www.gnu.org/licenses/gpl-2.0.html). \ No newline at end of file diff --git a/readme.txt b/readme.txt index bfac92e..6c5ce43 100644 --- a/readme.txt +++ b/readme.txt @@ -15,13 +15,13 @@ Embed DocumentCloud resources in WordPress content. This plugin allows you embed DocumentCloud documents using a custom shortcode: - [documentcloud url="http://www.documentcloud.org/documents/265231-11-07-2011-letter-to-idaho-congressional.html"] + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html"] When you save, WordPress fetches and stores the actual embed code HTML from the DocumentCloud servers using oEmbed. You can freely toggle between visual and HTML mode without mangling embed code, and your embed will always be up to date with the latest embed code. By default, the embed will be 600px wide and 620px tall. You can set your own defaults in Settings > DocumentCloud, or override the defaults on individual embeds using these attributes: - [documentcloud url="http://www.documentcloud.org/documents/265231-11-07-2011-letter-to-idaho-congressional.html" width="400" height="500"] + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="400" height="500"] Here's the full list of embed options you can pass via shortcode attributes: @@ -47,7 +47,7 @@ You can read more about publishing and embedding DocumentCloud resources on http 1. Upload the contents of the plugin to `wp-content/plugins/documentcloud` 2. Activate the plugin through the "Plugins" menu -3. Optionally set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) +3. Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud 4. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode == Changelog == From 2e33f8eedf5768e3191960275cc6958368cedabf Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 21 Apr 2015 17:48:01 -0500 Subject: [PATCH 11/27] Add upgrade notice for WordPress readme WP likes upgrade notices. Here's an upgrade notice. Since you like upgrade notices. --- readme.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 6c5ce43..58a05f3 100644 --- a/readme.txt +++ b/readme.txt @@ -58,4 +58,9 @@ You can read more about publishing and embedding DocumentCloud resources on http * Deprecated `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. = 0.1 = -* Initial release. \ No newline at end of file +* Initial release. + +== Upgrade Notice == + += 0.2 = +Adds oEmbed support for future-proofing embed codes. Provides additional embed options like `default_page`. From de73c798a358d618dd7f9aeddffd83745614846c Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Thu, 23 Apr 2015 14:21:34 -0500 Subject: [PATCH 12/27] Recompose embed URL to known patterns, incl notes Supports documents and known note variants. Affects #16 Closes #4 --- documentcloud.php | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index 392d5cc..427159f 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -31,8 +31,9 @@ class WP_DocumentCloud { DEFAULT_EMBED_HEIGHT = 620, DEFAULT_EMBED_WIDTH = 600, DEFAULT_EMBED_FULL_WIDTH = 940, - OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', - OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org'; + OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org', + OEMBED_PROVIDER = 'http://www.documentcloud.org/api/oembed.{format}', + DOCUMENT_PATTERN = '^(?Phttps?)://www\.documentcloud\.org/documents/(?P[0-9]+-[a-z0-9-]+)'; function __construct() { @@ -134,7 +135,7 @@ function handle_dc_shortcode($atts) { $url = $filtered_atts['url'] = "https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/{$atts['id']}.html"; } } else { - $url = $atts['url']; + $url = $filtered_atts['url'] = $this->clean_url($atts['url']); } // `height/width` beat `maxheight/maxwidth`; see full precedence list in `get_default_atts(). @@ -166,6 +167,27 @@ function handle_dc_shortcode($atts) { } + function clean_url($url) { + $patterns = array( + // Document + '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '\.html$}', + // Notes and note variants + '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '/annotations/(?P[0-9]+)\.(html|js)$}', + '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '.html#document/p([0-9]+)/a(?P[0-9]+)$}', + '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '.html#annotations/a(?P[0-9]+)$}', + ); + + $elements = array(); + foreach ($patterns as $pattern) { + $perfect_match = preg_match($pattern, $url, $elements); + if ($perfect_match) { + return "{$elements['protocol']}://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/{$elements['document_id']}" . + ($elements['note_id'] ? "/annotations/{$elements['note_id']}" : '') . '.html'; + } + } + return $url; + } + // Setup TinyMCE shortcode button function register_tinymce_filters() { From 205c5f71f83b6cc40ea9981a9bf56d9cb04248bb Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Thu, 23 Apr 2015 14:25:15 -0500 Subject: [PATCH 13/27] =?UTF-8?q?Fix=20pattern=20for=20`#annotation/?= =?UTF-8?q?=E2=80=A6`=20note=20URL=20variant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentcloud.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index 427159f..67ca81c 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -64,7 +64,7 @@ function register_dc_oembed_provider() { to uncomment the next line to let WordPress connect to local domains. */ - // add_filter( 'http_request_host_is_external', '__return_true'); + add_filter( 'http_request_host_is_external', '__return_true'); wp_oembed_add_provider("http://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); wp_oembed_add_provider("https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); @@ -174,7 +174,7 @@ function clean_url($url) { // Notes and note variants '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '/annotations/(?P[0-9]+)\.(html|js)$}', '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '.html#document/p([0-9]+)/a(?P[0-9]+)$}', - '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '.html#annotations/a(?P[0-9]+)$}', + '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '.html#annotation/a(?P[0-9]+)$}', ); $elements = array(); From 30b65a29315e98f7c2b1bf773f4febbdd330b130 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Thu, 23 Apr 2015 14:35:53 -0500 Subject: [PATCH 14/27] Use HTTPS for oEmbed provider Accidentally converted to HTTP --- documentcloud.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentcloud.php b/documentcloud.php index 67ca81c..82a5dc8 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -32,7 +32,7 @@ class WP_DocumentCloud { DEFAULT_EMBED_WIDTH = 600, DEFAULT_EMBED_FULL_WIDTH = 940, OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org', - OEMBED_PROVIDER = 'http://www.documentcloud.org/api/oembed.{format}', + OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', DOCUMENT_PATTERN = '^(?Phttps?)://www\.documentcloud\.org/documents/(?P[0-9]+-[a-z0-9-]+)'; function __construct() { From 32271e1fa786ce067b4f9c7bf8e7ba34e63892fa Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Thu, 23 Apr 2015 14:56:12 -0500 Subject: [PATCH 15/27] Update version number and docs for notes --- README.md | 20 ++++++++++++++++---- documentcloud.php | 2 +- readme.txt | 21 +++++++++++++++++---- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c6686e4..d54f349 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,19 @@ The DocumentCloud WordPress plugin lets you embed [DocumentCloud](https://www.do 1. Upload the contents of the plugin to `wp-content/plugins/documentcloud` 2. Activate the plugin through the "Plugins" menu 3. Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud -4. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode +4. In your posts, embed documents or notes using the DocumentCloud button or the `[documentcloud]` shortcode ## Usage -There are many options you can set using shortcode attributes: +There are many options you can set using shortcode attributes. Some are specific to the type of resource you're embedding. + +### All resources (documents and notes): - `url` (**required**, string): Full URL of the DocumentCloud resource. -- `container` (string): ID of element to insert the document into; if excluded, embedder will create its own container. +- `container` (string): ID of element to insert the embed into; if excluded, embedder will create its own container. + +### Documents only: + - `height` (integer): Height (in pixels) of the embed. - `width` (integer): Width (in pixels) of the embed. - `responsive` (boolean): Use responsive layout. @@ -35,8 +40,15 @@ For example, if you want to embed a document at 800px wide with no sidebar, pre- [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="800" sidebar="false" default_page="3"] +To embed a note, use any note-specific URL: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html#document/p1/a53674"] + ## Changelog +### 0.3 +* Added support for embedding notes. + ### 0.2 * Fetch embed code via oEmbed instead of generating statically. * Added new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. @@ -47,7 +59,7 @@ For example, if you want to embed a document at 800px wide with no sidebar, pre- ## History -Initial development of this plugin by Chris Amico (@eyeseast) supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. +Initial development of this plugin by Chris Amico (@eyeseast) supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. Development continued by Justin Reese (@reefdog) at [DocumentCloud](https://www.documentcloud.org/). ## License diff --git a/documentcloud.php b/documentcloud.php index 82a5dc8..ec6ebd1 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -3,7 +3,7 @@ * Plugin Name: DocumentCloud * Plugin URI: https://www.documentcloud.org/ * Description: Embed DocumentCloud resources in WordPress content. - * Version: 0.2 + * Version: 0.3 * Authors: Chris Amico, Justin Reese * License: GPLv2 ***/ diff --git a/readme.txt b/readme.txt index 58a05f3..29e54db 100644 --- a/readme.txt +++ b/readme.txt @@ -13,20 +13,27 @@ Embed DocumentCloud resources in WordPress content. [DocumentCloud](https://www.documentcloud.org/) is a service that allows journalists to analyze, annotate and publish documents, hosted by Investigative Reporters & Editors. Initial development of this plugin supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. -This plugin allows you embed DocumentCloud documents using a custom shortcode: +This plugin allows you embed DocumentCloud resources using a custom shortcode: [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html"] When you save, WordPress fetches and stores the actual embed code HTML from the DocumentCloud servers using oEmbed. You can freely toggle between visual and HTML mode without mangling embed code, and your embed will always be up to date with the latest embed code. -By default, the embed will be 600px wide and 620px tall. You can set your own defaults in Settings > DocumentCloud, or override the defaults on individual embeds using these attributes: +By default, documents will be 600px wide and 620px tall. You can set your own defaults in Settings > DocumentCloud, or override the defaults on individual embeds using these attributes: [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="400" height="500"] -Here's the full list of embed options you can pass via shortcode attributes: +You can also forego width/height and have the document fill the horizontal width of its container by using the `responsive="true"` shortcode. (Notes ignore width/height and always act responsively.) + +Here's the full list of embed options you can pass via shortcode attributes. + +All resources (documents and notes): - `url` (**required**, string): Full URL of the DocumentCloud resource. -- `container` (string): ID of element to insert the document into; if excluded, embedder will create its own container. +- `container` (string): ID of element to insert the embed into; if excluded, embedder will create its own container. + +Documents only: + - `height` (integer): Height (in pixels) of the embed. - `width` (integer): Width (in pixels) of the embed. - `responsive` (boolean): Use responsive layout. @@ -52,6 +59,9 @@ You can read more about publishing and embedding DocumentCloud resources on http == Changelog == += 0.3 = +* Added support for embedding notes. + = 0.2 = * Fetch embed code via oEmbed instead of generating statically. * Added new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. @@ -62,5 +72,8 @@ You can read more about publishing and embedding DocumentCloud resources on http == Upgrade Notice == += 0.3 = +Adds support for embedding notes. + = 0.2 = Adds oEmbed support for future-proofing embed codes. Provides additional embed options like `default_page`. From 60f5f2c624acdd6285411873056433643ab489f7 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 28 Apr 2015 13:49:58 -0500 Subject: [PATCH 16/27] Default to responsive Per discussion and consensus among @eyeseast, @aschweigert, @knowtheory, @anthonydb and @reefdog. Affects #14 --- README.md | 1 + documentcloud.php | 2 +- readme.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d54f349..c22393c 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ To embed a note, use any note-specific URL: ### 0.3 * Added support for embedding notes. +* Default to responsive ### 0.2 * Fetch embed code via oEmbed instead of generating statically. diff --git a/documentcloud.php b/documentcloud.php index ec6ebd1..06e871c 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -81,7 +81,7 @@ function get_default_atts() { 'default_note' => null, 'zoom' => null, 'search' => null, - 'responsive' => null, + 'responsive' => 'true', // The following defaults match the existing plugin, except // `height/width` are prefixed `max*` per the oEmbed spec. // You can still use `height/width` for backwards diff --git a/readme.txt b/readme.txt index 29e54db..cb49fed 100644 --- a/readme.txt +++ b/readme.txt @@ -61,6 +61,7 @@ You can read more about publishing and embedding DocumentCloud resources on http = 0.3 = * Added support for embedding notes. +* Default to responsive = 0.2 = * Fetch embed code via oEmbed instead of generating statically. From 88894c0d86b26e3ab63af302faade6da7c6f629d Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 28 Apr 2015 14:33:23 -0500 Subject: [PATCH 17/27] Remove old functions and tweak some comments --- documentcloud.php | 84 +++-------------------------------------------- 1 file changed, 5 insertions(+), 79 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index 06e871c..2b5219a 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -119,8 +119,8 @@ function add_dc_arguments($provider, $url, $args) { function handle_dc_shortcode($atts) { $default_atts = $this->get_default_atts(); - // Smooshes together passed-in shortcode attributes with - // default attributes/values. + // Smooshes together passed-in shortcode attrs with defaults + // and filters to only those we accept. $filtered_atts = shortcode_atts($default_atts, $atts); // Either the `url` or `id` attributes are required, but `id` @@ -135,6 +135,8 @@ function handle_dc_shortcode($atts) { $url = $filtered_atts['url'] = "https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/{$atts['id']}.html"; } } else { + // Some resources (like notes) have multiple possible + // user-facing URLs. We recompose them into a single form. $url = $filtered_atts['url'] = $this->clean_url($atts['url']); } @@ -149,7 +151,7 @@ function handle_dc_shortcode($atts) { // If the format is set to wide, it blows away all other width // settings. if ($filtered_atts['format'] == 'wide') { - $filtered_atts['maxwidth'] = get_option('documentcloud_full_width', DEFAULT_EMBED_FULL_WIDTH); + $filtered_atts['maxwidth'] = get_option('documentcloud_full_width', WP_DocumentCloud::DEFAULT_EMBED_FULL_WIDTH); } // For the benefit of some templates @@ -328,82 +330,6 @@ function parse_id_from_url($url) { } } - // TODO: Remove this once we've ensured `handle_dc_shortcode()` - // replicates all the functionality properly. Note that `save()` - // has been adjusted to use `get_default_atts()`, but I left - // `embed_shortcode()` using `get_defaults()` for inspection. - - function get_defaults() { - // add admin options to adjust these defaults - // storing js params as strings instead of real booleans - return array( - 'url' => null, - 'id' => null, - 'height' => get_option('documentcloud_default_height', 600), - 'width' => get_option('documentcloud_default_width', 620), - 'format' => 'normal', - 'sidebar' => 'false', - 'text' => 'true', - 'pdf' => 'true' - ); - } - - function embed_shortcode($atts, $content, $code) { - global $post; - $defaults = $this->get_defaults(); - extract(shortcode_atts($defaults, $atts)); - - // we need a document ID or URL, or it's a no op - if ($url && !$id) { - // parse id from url - $id = $this->parse_id_from_url($url); - } - - // still no id? nothin doing - if (!$id) return; - - // we only deal with integers - $height = intval($height); - $width = intval($width); - if ($format == 'wide') { - $width = get_option('documentcloud_full_width', 940); - } - - $is_wide = $width > $defaults['width']; - - // full control in single templates - if (is_single() || is_page()) { - return " -
- - "; - - } else { - // index view is always normal width, no sidebar - return " -
- - "; - } - } } new WP_DocumentCloud; From 40dda422c75206052660abd05c9d3eb1443b0c36 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 28 Apr 2015 14:38:03 -0500 Subject: [PATCH 18/27] Append `$SITEURL` with slash if it's not there `$SITEURL` seems to behave inconsistently, so just buffaloing a solution by checking for trailing slash and adding it if it doesn't exist. --- js/window.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/window.php b/js/window.php index 4d7bdaa..4c7d27d 100644 --- a/js/window.php +++ b/js/window.php @@ -6,6 +6,9 @@ } $SITEURL .= $_SERVER[ 'HTTP_HOST' ] or $_SERVER[ 'SERVER_NAME' ]; $SITEURL .= $_GET[ 'wpbase' ]; +if (substr($SITEURL, -1) != '/') { + $SITEURL .= '/'; +} ?> From 622b31147a59652c21fc030871a2ccf46c633415 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 28 Apr 2015 16:01:17 -0500 Subject: [PATCH 19/27] Use theme's width/height as defaults When there's no shortcode or user-defined default, use the theme's defaults for embed sizes instead of defining our own final defaults. Closes #19 --- documentcloud.php | 57 ++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index 2b5219a..2e0d421 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -28,8 +28,6 @@ class WP_DocumentCloud { const CACHING_ENABLED = false, - DEFAULT_EMBED_HEIGHT = 620, - DEFAULT_EMBED_WIDTH = 600, DEFAULT_EMBED_FULL_WIDTH = 940, OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org', OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', @@ -64,14 +62,30 @@ function register_dc_oembed_provider() { to uncomment the next line to let WordPress connect to local domains. */ - add_filter( 'http_request_host_is_external', '__return_true'); + // add_filter( 'http_request_host_is_external', '__return_true'); wp_oembed_add_provider("http://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); wp_oembed_add_provider("https://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/*", WP_DocumentCloud::OEMBED_PROVIDER); } + function get_default_sizes() { + $wp_embed_defaults = wp_embed_defaults(); + + $height = intval(get_option('documentcloud_default_height', $wp_embed_defaults['height'])); + $width = intval(get_option('documentcloud_default_width', $wp_embed_defaults['width'])); + $full_width = intval(get_option('documentcloud_full_width', WP_DocumentCloud::DEFAULT_EMBED_FULL_WIDTH)); + + return array ( + 'height' => $height, + 'width' => $width, + 'full_width' => $full_width, + ); + } + + // TODO: Add admin options to adjust all defaults. function get_default_atts() { - // TODO: Add admin options to adjust all defaults. + $default_sizes = $this->get_default_sizes(); + return array( 'url' => null, 'container' => null, @@ -88,11 +102,11 @@ function get_default_atts() { // compatibility, but they'll be mapped to `max*`. // Precedence (lower number == higher priority): // 1. `width` on shortcode - // 2. `maxwidth` from shortcode + // 2. `maxwidth` on shortcode // 3. Settings > DocumentCloud > "Default embed width" - // 4. `WP_DocumentCloud::DEFAULT_EMBED_WIDTH` - 'maxheight' => intval(get_option('documentcloud_default_height', WP_DocumentCloud::DEFAULT_EMBED_HEIGHT)), - 'maxwidth' => intval(get_option('documentcloud_default_width', WP_DocumentCloud::DEFAULT_EMBED_WIDTH)), + // 4. `wp_embed_defaults()['width']` + 'maxheight' => $default_sizes['height'], + 'maxwidth' => $default_sizes['width'], 'format' => 'normal', 'sidebar' => 'false', 'text' => 'true', @@ -118,10 +132,12 @@ function add_dc_arguments($provider, $url, $args) { } function handle_dc_shortcode($atts) { - $default_atts = $this->get_default_atts(); + $default_sizes = $this->get_default_sizes(); + $default_atts = $this->get_default_atts(); + // Smooshes together passed-in shortcode attrs with defaults // and filters to only those we accept. - $filtered_atts = shortcode_atts($default_atts, $atts); + $filtered_atts = shortcode_atts($default_atts, $atts); // Either the `url` or `id` attributes are required, but `id` // is only supported for backwards compatibility. If it's used, @@ -140,7 +156,7 @@ function handle_dc_shortcode($atts) { $url = $filtered_atts['url'] = $this->clean_url($atts['url']); } - // `height/width` beat `maxheight/maxwidth`; see full precedence list in `get_default_atts(). + // `height/width` beat `maxheight/maxwidth`; see full precedence list in `get_default_atts()`. if (isset($atts['height'])) { $filtered_atts['maxheight'] = $atts['height']; } @@ -151,12 +167,13 @@ function handle_dc_shortcode($atts) { // If the format is set to wide, it blows away all other width // settings. if ($filtered_atts['format'] == 'wide') { - $filtered_atts['maxwidth'] = get_option('documentcloud_full_width', WP_DocumentCloud::DEFAULT_EMBED_FULL_WIDTH); + $filtered_atts['maxwidth'] = $default_sizes['full_width']; } - // For the benefit of some templates + // For the benefit of some templates, notify template that + // we're requesting an asset wider than the default size. global $post; - $is_wide = intval($filtered_atts['maxwidth']) > $default_atts['maxwidth']; + $is_wide = intval($filtered_atts['maxwidth']) > $default_sizes['width']; if (WP_DocumentCloud::CACHING_ENABLED) { // This lets WordPress cache the result of the oEmbed call. @@ -252,18 +269,18 @@ function settings_init() { } function default_height_field() { - $option = intval(get_option('documentcloud_default_height', 600)); - echo ""; + $default_sizes = $this->get_default_sizes(); + echo ""; } function default_width_field() { - $option = intval(get_option('documentcloud_default_width', 620)); - echo ""; + $default_sizes = $this->get_default_sizes(); + echo ""; } function full_width_field() { - $option = intval(get_option('documentcloud_full_width', 620)); - echo ""; + $default_sizes = $this->get_default_sizes(); + echo ""; } function settings_section() {} From e3a85d0d27d62e3f5c783167395ab0b7feae1b99 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 28 Apr 2015 16:27:31 -0500 Subject: [PATCH 20/27] Let width attr disable responsiveness Trying to balance user intent: now that we're responsive by default, it stands to reason that a user indicating a width directly on a shortcode actually wants that width, so we should disable responsiveness unless they have actually ALSO indicated they want responsiveness, in which case they are confused and we'll go with responsive. Affects #14 --- README.md | 8 ++++---- documentcloud.php | 11 +++++++++++ readme.txt | 18 +++++++++++------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c22393c..1cf702a 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ There are many options you can set using shortcode attributes. Some are specific ### Documents only: - `height` (integer): Height (in pixels) of the embed. -- `width` (integer): Width (in pixels) of the embed. -- `responsive` (boolean): Use responsive layout. +- `width` (integer): Width (in pixels) of the embed. If used, will implicitly set `responsive="false"`. +- `responsive` (boolean): Use responsive layout, which dynamically adjusts width to fill content area. Defaults `true`. - `responsive_offset` (integer): Distance (in pixels) to vertically offset the viewer for some responsive embeds. - `default_page` (integer): Page number to have the document scroll to by default. - `default_note` (integer): ID of the note that the document should highlight by default. @@ -36,9 +36,9 @@ There are many options you can set using shortcode attributes. Some are specific - `zoom` (boolean): Hide or show zoom slider. - `format` (string): Indicate to the theme that this is a wide asset by setting this to `wide`. Defaults `normal`. -For example, if you want to embed a document at 800px wide with no sidebar, pre-scrolled to page 3: +For example, if you want to embed a document at 800px wide, pre-scrolled to page 3: - [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="800" sidebar="false" default_page="3"] + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" responsive="false" width="800" default_page="3"] To embed a note, use any note-specific URL: diff --git a/documentcloud.php b/documentcloud.php index 2e0d421..fb2287a 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -163,6 +163,15 @@ function handle_dc_shortcode($atts) { if (isset($atts['width'])) { $filtered_atts['maxwidth'] = $atts['width']; } + + // `responsive` defaults true, but our responsive layout + // ignores width declarations. If a user indicates a width and + // hasn't otherwise specifically indicated `responsive='true'`, + // it's safe to assume they expect us to respect the width, so + // we disable the responsive flag. + if ((isset($atts['width']) || isset($atts['maxwidth'])) && (string) $atts['responsive'] != 'true') { + $filtered_atts['responsive'] = 'false'; + } // If the format is set to wide, it blows away all other width // settings. @@ -241,6 +250,8 @@ function add_options_page() { function render_options_page() { ?>

DocumentCloud Options

+ +

Any widths set here will only take effect if you set responsive="false" on an embed.

diff --git a/readme.txt b/readme.txt index cb49fed..60fe494 100644 --- a/readme.txt +++ b/readme.txt @@ -19,11 +19,15 @@ This plugin allows you embed DocumentCloud resources using a custom shortcode: When you save, WordPress fetches and stores the actual embed code HTML from the DocumentCloud servers using oEmbed. You can freely toggle between visual and HTML mode without mangling embed code, and your embed will always be up to date with the latest embed code. -By default, documents will be 600px wide and 620px tall. You can set your own defaults in Settings > DocumentCloud, or override the defaults on individual embeds using these attributes: +By default, documents will have a responsive width (it will narrow and widen as necessary to fill available content area) and use the theme's default height. If you want to override this, you can either set `responsive="false"` or explicitly set a `width`: - [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="400" height="500"] + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="600"] -You can also forego width/height and have the document fill the horizontal width of its container by using the `responsive="true"` shortcode. (Notes ignore width/height and always act responsively.) +You can set your own defaults in Settings > DocumentCloud, but default widths will be ignored unless `responsive` is disabled: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" responsive="false"] + +Notes ignore `width/height` and always act responsively. Here's the full list of embed options you can pass via shortcode attributes. @@ -35,16 +39,16 @@ All resources (documents and notes): Documents only: - `height` (integer): Height (in pixels) of the embed. -- `width` (integer): Width (in pixels) of the embed. -- `responsive` (boolean): Use responsive layout. +- `width` (integer): Width (in pixels) of the embed. If used, will implicitly set `responsive="false"`. +- `responsive` (boolean): Use responsive layout, which dynamically adjusts width to fill content area. Defaults `true`. - `responsive_offset` (integer): Distance (in pixels) to vertically offset the viewer for some responsive embeds. - `default_page` (integer): Page number to have the document scroll to by default. - `default_note` (integer): ID of the note that the document should highlight by default. - `notes` (boolean): Show/hide notes: - `search` (boolean): Hide or show search form. - `sidebar` (boolean): Hide or show sidebar. Defaults `false`. -- `pdf` (boolean): Hide or show link to download original PDF. -- `text` (boolean): Hide or show text tab. +- `pdf` (boolean): Hide or show link to download original PDF. Defaults `true`. +- `text` (boolean): Hide or show text tab. Defaults `true`. - `zoom` (boolean): Hide or show zoom slider. - `format` (string): Indicate to the theme that this is a wide asset by setting this to `wide`. Defaults `normal`. From b326d309bcae49779a7d9d5d5b628af35fb92bcb Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Tue, 28 Apr 2015 17:17:25 -0500 Subject: [PATCH 21/27] Update post metadata saving to use new URL parser This started life as a task to include note ID in the post metadata when it was keyed off a note, since the document slug is the same on notes and documents, and thus two resources from the same doc could cause a ID collision. Then I realized that we already only save a single piece of metadata per post anyway (see how `update_post_meta()` is outside the `foreach()`?) and so this was unnecessary. But I'd already done the work to abstract out `parse_dc_url()` and clean up some things, so. Affects #22 --- documentcloud.php | 61 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index fb2287a..c431c91 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -31,7 +31,7 @@ class WP_DocumentCloud { DEFAULT_EMBED_FULL_WIDTH = 940, OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org', OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', - DOCUMENT_PATTERN = '^(?Phttps?)://www\.documentcloud\.org/documents/(?P[0-9]+-[a-z0-9-]+)'; + DOCUMENT_PATTERN = '^(?Phttps?)://www\.documentcloud\.org/documents/(?P[0-9]+-[a-z0-9-]+)'; function __construct() { @@ -153,7 +153,7 @@ function handle_dc_shortcode($atts) { } else { // Some resources (like notes) have multiple possible // user-facing URLs. We recompose them into a single form. - $url = $filtered_atts['url'] = $this->clean_url($atts['url']); + $url = $filtered_atts['url'] = $this->clean_dc_url($atts['url']); } // `height/width` beat `maxheight/maxwidth`; see full precedence list in `get_default_atts()`. @@ -195,7 +195,7 @@ function handle_dc_shortcode($atts) { } - function clean_url($url) { + function parse_dc_url($url) { $patterns = array( // Document '{' . WP_DocumentCloud::DOCUMENT_PATTERN . '\.html$}', @@ -209,10 +209,18 @@ function clean_url($url) { foreach ($patterns as $pattern) { $perfect_match = preg_match($pattern, $url, $elements); if ($perfect_match) { - return "{$elements['protocol']}://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/{$elements['document_id']}" . - ($elements['note_id'] ? "/annotations/{$elements['note_id']}" : '') . '.html'; + break; } } + return $elements; + } + + function clean_dc_url($url) { + $elements = $this->parse_dc_url($url); + if ($elements['document_slug']) { + $url = "{$elements['protocol']}://" . WP_DocumentCloud::OEMBED_RESOURCE_DOMAIN . "/documents/{$elements['document_slug']}" . + ($elements['note_id'] ? "/annotations/{$elements['note_id']}" : '') . '.html'; + } return $url; } @@ -307,7 +315,8 @@ function save($post_id) { )) ) { return; } - $defaults = $this->get_default_atts(); + $default_sizes = $this->get_default_sizes(); + $default_atts = $this->get_default_atts(); $wide_assets = get_post_meta($post_id, 'wide_assets', true); $documents = get_post_meta($post_id, 'documentcloud', true); $matches = array(); @@ -317,30 +326,26 @@ function save($post_id) { $args = $matches[3]; foreach($tags as $i => $tag) { if ($tag == "documentcloud") { - $atts = shortcode_parse_atts($args[$i]); - $atts = shortcode_atts($defaults, $atts); - - // TODO: Reconsider using document ID as array key, - // because we'll be using this same shortcode to - // consume more than just documents in the future. - // Perhaps we can use `url` as key? + $parsed_atts = shortcode_parse_atts($args[$i]); + $atts = shortcode_atts($default_atts, $parsed_atts); // get a doc id to keep array keys consistent - if (isset($atts['url']) && !isset($atts['id']) ) { - $atts['id'] = $this->parse_id_from_url($atts['url']); + if (isset($atts['url'])) { + $elements = $this->parse_dc_url($atts['url']); + $meta_key = $elements['document_slug']; + } else if (isset($atts['id'])) { + $meta_key = $atts['id']; } // if no id, don't bother storing because it's wrong - if ($atts['id'] != null) { - $width = isset($atts['width']) ? $atts['width'] : $atts['maxwidth']; - if ($atts['format'] == "wide" || $width > $defaults['maxwidth']) { - $wide_assets[$atts['id']] = true; + if ($meta_key) { + $width = intval(isset($parsed_atts['width']) ? $parsed_atts['width'] : $atts['maxwidth']); + if ($atts['format'] == "wide" || $width > $default_sizes['width']) { + $wide_assets[$meta_key] = true; } else { - $wide_assets[$atts['id']] = false; + $wide_assets[$meta_key] = false; } - - $documents[$atts['id']] = $atts; - + $documents[$meta_key] = $atts; } } } @@ -348,16 +353,6 @@ function save($post_id) { update_post_meta($post_id, 'wide_assets', $wide_assets); } - function parse_id_from_url($url) { - $regex = '{^https://www\.documentcloud\.org/documents/(?P.+)\.html}'; - $matches = array(); - if (preg_match($regex, $url, $matches)) { - return $matches['id']; - } else { - return null; - } - } - } new WP_DocumentCloud; From 54575e8251a54b125fb12439dff6476641e7b0cf Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Wed, 29 Apr 2015 11:38:07 -0500 Subject: [PATCH 22/27] Enable oEmbed cache See discussion on #20. Closes #20. --- documentcloud.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/documentcloud.php b/documentcloud.php index c431c91..88ed541 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -27,7 +27,7 @@ class WP_DocumentCloud { - const CACHING_ENABLED = false, + const CACHING_ENABLED = true, DEFAULT_EMBED_FULL_WIDTH = 940, OEMBED_RESOURCE_DOMAIN = 'www.documentcloud.org', OEMBED_PROVIDER = 'https://www.documentcloud.org/api/oembed.{format}', @@ -46,9 +46,6 @@ function __construct() { add_action('admin_menu', array(&$this, 'add_options_page')); add_action('admin_init', array(&$this, 'settings_init')); - // Register [documentcloud] shortcode using old embed method - // add_shortcode('documentcloud', array(&$this, 'embed_shortcode')); - // Store metadata upon post save add_action('save_post', array(&$this, 'save')); } From ad2767d315c7d0a8501895655651dcb4c9666743 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Wed, 29 Apr 2015 11:39:34 -0500 Subject: [PATCH 23/27] Update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1cf702a..b6d44d4 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ There are many options you can set using shortcode attributes. Some are specific - `notes` (boolean): Show/hide notes: - `search` (boolean): Hide or show search form. - `sidebar` (boolean): Hide or show sidebar. Defaults `false`. -- `pdf` (boolean): Hide or show link to download original PDF. -- `text` (boolean): Hide or show text tab. +- `pdf` (boolean): Hide or show link to download original PDF. Defaults `true`. +- `text` (boolean): Hide or show text tab. Defaults `true`. - `zoom` (boolean): Hide or show zoom slider. - `format` (string): Indicate to the theme that this is a wide asset by setting this to `wide`. Defaults `normal`. From 98b99597680543e233b17109921c046530efce30 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Wed, 29 Apr 2015 11:59:31 -0500 Subject: [PATCH 24/27] Unify Markdown and WordPress READMEs --- README.md | 54 +++++++++++++++++++++++++++++++++++++----------------- readme.txt | 25 ++++++++++++++----------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index b6d44d4..6653993 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,30 @@ The DocumentCloud WordPress plugin lets you embed [DocumentCloud](https://www.do 1. Upload the contents of the plugin to `wp-content/plugins/documentcloud` 2. Activate the plugin through the "Plugins" menu -3. Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud -4. In your posts, embed documents or notes using the DocumentCloud button or the `[documentcloud]` shortcode +3. In your posts, embed documents or notes using the DocumentCloud button or the `[documentcloud]` shortcode +4. Optional: Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud. (This default width will only be used if you set `responsive="false"` on an embed.) ## Usage -There are many options you can set using shortcode attributes. Some are specific to the type of resource you're embedding. +This plugin allows you embed DocumentCloud resources using a custom shortcode: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html"] + +When you save, WordPress fetches and stores the actual embed code HTML from the DocumentCloud servers using oEmbed. You can freely toggle between visual and HTML mode without mangling embed code, and your embed will always be up to date with the latest embed code. + +By default, documents will have a responsive width (it will narrow and widen as necessary to fill available content area) and use the theme's default height. If you want to override this, you can either set `responsive="false"` or explicitly set a `width`: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" width="600"] + +You can set your own defaults in Settings > DocumentCloud, but default widths will be ignored unless `responsive` is disabled: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" responsive="false"] + +To embed a note, just use any note-specific URL. Notes ignore `width/height` and always act responsively: + + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html#document/p1/a53674"] + +Here's the full list of embed options you can pass via shortcode attributes; some are specific to the type of resource you're embedding. ### All resources (documents and notes): @@ -36,32 +54,34 @@ There are many options you can set using shortcode attributes. Some are specific - `zoom` (boolean): Hide or show zoom slider. - `format` (string): Indicate to the theme that this is a wide asset by setting this to `wide`. Defaults `normal`. -For example, if you want to embed a document at 800px wide, pre-scrolled to page 3: +You can read more about publishing and embedding DocumentCloud resources on https://www.documentcloud.org/help/publishing. - [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" responsive="false" width="800" default_page="3"] +## Caching -To embed a note, use any note-specific URL: +Ideally, when WordPress hits our oEmbed service to fetch the embed code, it would obey the `cache_age` we return. Despite [conversation](https://core.trac.wordpress.org/ticket/14759) around this, it doesn't seem to. - [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html#document/p1/a53674"] +Instead, it lets us choose between no cache at all (so *every pageload* triggers a call to our oEmbed service to get the embed code) or a supposed 24-hour cache stored in the `postmeta` table. Unfortunately, [our tests](https://github.com/documentcloud/wordpress-documentcloud/issues/20) seem to show this cache is never expired, which means we can choose between no cache (thus possibly DDOSing ourselves) or a permanent cache (thus possibly having stale embed codes). We've chosen the latter; hopefully this cache does eventually expire, and our embed codes shouldn't change that often anyway. + +If you find yourself absolutely needing to expire the cache, though, you have two choices: + +1. Delete the appropriate `_oembed_*` rows from your `postmeta` table. +2. Modify the shortcode attributes for the embed, since this is recognized as a new embed by WordPress. ## Changelog ### 0.3 -* Added support for embedding notes. -* Default to responsive +* Add support for embedding notes. +* Default to responsive. +* Enable caching. ### 0.2 * Fetch embed code via oEmbed instead of generating statically. -* Added new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. -* Deprecated `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. +* Add new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. +* Deprecate `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. ### 0.1 * Initial release. -## History - -Initial development of this plugin by Chris Amico (@eyeseast) supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. Development continued by Justin Reese (@reefdog) at [DocumentCloud](https://www.documentcloud.org/). - -## License +## License and History -The DocumentCloud WordPress plugin is [GPLv2](http://www.gnu.org/licenses/gpl-2.0.html). \ No newline at end of file +The DocumentCloud WordPress plugin is [GPLv2](http://www.gnu.org/licenses/gpl-2.0.html). Initial development of this plugin by Chris Amico (@eyeseast) supported by [NPR](http://www.npr.org) as part of [StateImpact](http://stateimpact.npr.org) project. Development continued by Justin Reese (@reefdog) at [DocumentCloud](https://www.documentcloud.org/). diff --git a/readme.txt b/readme.txt index 60fe494..ddd19ea 100644 --- a/readme.txt +++ b/readme.txt @@ -27,16 +27,18 @@ You can set your own defaults in Settings > DocumentCloud, but default widths wi [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html" responsive="false"] -Notes ignore `width/height` and always act responsively. +To embed a note, just use any note-specific URL. Notes ignore `width/height` and always act responsively: -Here's the full list of embed options you can pass via shortcode attributes. + [documentcloud url="https://www.documentcloud.org/documents/282753-lefler-thesis.html#document/p1/a53674"] -All resources (documents and notes): +Here's the full list of embed options you can pass via shortcode attributes; some are specific to the type of resource you're embedding. + +**All resources (documents and notes):** - `url` (**required**, string): Full URL of the DocumentCloud resource. - `container` (string): ID of element to insert the embed into; if excluded, embedder will create its own container. -Documents only: +**Documents only:** - `height` (integer): Height (in pixels) of the embed. - `width` (integer): Width (in pixels) of the embed. If used, will implicitly set `responsive="false"`. @@ -58,19 +60,20 @@ You can read more about publishing and embedding DocumentCloud resources on http 1. Upload the contents of the plugin to `wp-content/plugins/documentcloud` 2. Activate the plugin through the "Plugins" menu -3. Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud -4. In your posts, add documents using the DocumentCloud button or the `[documentcloud]` shortcode +3. In your posts, embed documents or notes using the DocumentCloud button or the `[documentcloud]` shortcode +4. Optional: Set a default width/height for all DocumentCloud embeds (which can be overridden on a per-embed basis with the `height/width` attributes) at Settings > DocumentCloud. (This default width will only be used if you set `responsive="false"` on an embed.) == Changelog == = 0.3 = -* Added support for embedding notes. -* Default to responsive +* Add support for embedding notes. +* Default to responsive. +* Enable caching. = 0.2 = * Fetch embed code via oEmbed instead of generating statically. -* Added new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. -* Deprecated `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. +* Add new options: `container`, `responsive`, `responsive_offset`, `default_page`, `default_note`, `notes`, `search`, and `zoom`. +* Deprecate `id` attribute. It's still usable, but support may drop in the future. Use `url` instead. = 0.1 = * Initial release. @@ -78,7 +81,7 @@ You can read more about publishing and embedding DocumentCloud resources on http == Upgrade Notice == = 0.3 = -Adds support for embedding notes. +Adds support for embedding notes and enables caching. = 0.2 = Adds oEmbed support for future-proofing embed codes. Provides additional embed options like `default_page`. From 7cda2163924905ca518aaad24e31801da9ab743f Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Wed, 29 Apr 2015 14:05:42 -0500 Subject: [PATCH 25/27] Updated most recent tested version Confirmed compatibility with 3.2 and 4.2.1. --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index ddd19ea..555ec3b 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: chrisamico, reefdog Tags: documentcloud, documents, journalism, reporting, research Requires at least: 3.2 -Tested up to: 4.1.1 +Tested up to: 4.2.1 Stable tag: trunk License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html From 986a4db4e1997608f7d9258a249a90f969d54282 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Wed, 29 Apr 2015 14:15:58 -0500 Subject: [PATCH 26/27] Disable toolbar button until resolved Toolbar button has been broken for a while, since at least 3.9.1, because of an update to the version of TinyMCE included in WP. It needs some signifiant fixing, and could stand to have it fleshed out with additional attribute options anyway. Disabling until we have time for the full solution. Affects #23 --- documentcloud.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentcloud.php b/documentcloud.php index 88ed541..f3884f6 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -40,7 +40,7 @@ function __construct() { add_filter('oembed_fetch_url', array(&$this, 'add_dc_arguments'), 10, 3); // Setup TinyMCE shortcode-generation plugin - add_action('init', array(&$this, 'register_tinymce_filters')); + // add_action('init', array(&$this, 'register_tinymce_filters')); // Setup admin settings add_action('admin_menu', array(&$this, 'add_options_page')); From ab7b06a56cfbd8dc05c4c5f1325d19a851783838 Mon Sep 17 00:00:00 2001 From: Justin Reese Date: Wed, 29 Apr 2015 14:27:16 -0500 Subject: [PATCH 27/27] Append note ID to postmeta key for notes Docs and notes have the same document slug, which resulted in the same postmeta key. When you had a wide document followed by a normal note, this resulted in the postmeta not properly reporting a `wide_asset`. Append note ID to its meta key so it can be distinguished from docs. Affects #22 --- documentcloud.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentcloud.php b/documentcloud.php index f3884f6..793d728 100644 --- a/documentcloud.php +++ b/documentcloud.php @@ -330,6 +330,9 @@ function save($post_id) { if (isset($atts['url'])) { $elements = $this->parse_dc_url($atts['url']); $meta_key = $elements['document_slug']; + if ($elements['note_id']) { + $meta_key .= "-{$elements['note_id']}"; + } } else if (isset($atts['id'])) { $meta_key = $atts['id']; }