diff --git a/readme.txt b/readme.txt index 339db77..fb98382 100755 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Contributors: cmanon, jrfoell, lancewillett, dlintott, sebastianerb Tags: strava, activity, bicycle, cycling, biking, running, run, swimming, swim, paddle, kayak, gps, shortcode, widget, plugin Requires at least: 4.6 Tested up to: 5.6 -Stable tag: 2.5.1 +Stable tag: 2.6.0 Requires PHP: 5.3 License: GPLv2 or later @@ -22,10 +22,16 @@ Using WP-Strava 2.0+ requires a working WordPress cron configuration. By default = Blocks = +*Available in WordPress 5.0 and up.* + Strava Activity - embed an activity in any page or post. Shows a summary of the activity plus a map if a google maps key has been added. Paste in the full activity URL from Strava, such as https://www.strava.com/activities/1793155844 and click "Embed." A preview map will be shown in the editor, similar to what will be displayed on the front-end. In the side-panel you can selection options to show the image only (without the details table), display markers at the start & finish points, and override the system of measure from your default selection under Settings -> Strava. +Strava Route - embed a route in any page or post. Shows a summary of the route plus a map if a google maps key has been added. + +Paste in the full route URL from Strava, such as hhttps://www.strava.com/routes/2326567 and click "Embed." A preview map will be shown in the editor, similar to what will be displayed on the front-end. In the side-panel you can selection options to show the image only (without the details table), display markers at the start & finish points, and override the system of measure from your default selection under Settings -> Strava. + = Shortcodes = [activity id=NUMBER] - add to any page or post. Shows a summary of the activity plus a map if a google maps key has been added. @@ -112,6 +118,9 @@ On the WP-Strava settings page you cannot currently remove and add another athle == Changelog == += 2.6.0 = +Make reusable components for embed screens and SOMOverride +Add Route Block = 2.5.1 = diff --git a/src/WPStrava.php b/src/WPStrava.php index 94252f4..dddde35 100644 --- a/src/WPStrava.php +++ b/src/WPStrava.php @@ -62,6 +62,17 @@ public static function get_instance() { return self::$instance; } + /** + * Check if rest request to skip link rendering in block editor. + * + * @return boolean + * @author Justin Foell + * @since 2.6.0 + */ + public static function is_rest_request() { + return defined( 'REST_REQUEST' ) && REST_REQUEST; + } + /** * Function to install hooks at WP runtime. * @@ -188,7 +199,10 @@ public function register_shortcodes() { * @see https://wordpress.org/gutenberg/handbook/blocks/writing-your-first-block-type/#enqueuing-block-scripts */ public function register_blocks() { - static $blocks = array( 'WPStrava_Blocks_Activity' ); + static $blocks = array( + 'WPStrava_Blocks_Activity', + 'WPStrava_Blocks_Route', + ); // automatically load dependencies and version $asset_file = include WPSTRAVA_PLUGIN_DIR . 'build/index.asset.php'; diff --git a/src/WPStrava/Activity.php b/src/WPStrava/Activity.php index 242792f..66e8d41 100755 --- a/src/WPStrava/Activity.php +++ b/src/WPStrava/Activity.php @@ -109,22 +109,11 @@ public function get_activities_longer_than( $activities, $dist ) { * @since 2.3.2 */ public function get_activity_link( $activity_id, $text, $title = '' ) { - if ( $this->is_rest_request() || WPStrava::get_instance()->settings->no_link ) { + if ( WPStrava::is_rest_request() || WPStrava::get_instance()->settings->no_link ) { return $text; } $url = esc_url( self::ACTIVITIES_URL . $activity_id ); $title_attr = $title ? " title='" . esc_attr( $title ) . "'" : ''; return "{$text}"; } - - /** - * Check if rest request to skip link rendering in block editor. - * - * @return boolean - * @author Justin Foell - * @since 2.5.1 - */ - private function is_rest_request() { - return defined( 'REST_REQUEST' ) && REST_REQUEST; - } } diff --git a/src/WPStrava/Blocks/Activity.php b/src/WPStrava/Blocks/Activity.php index 20d4a47..37a6439 100644 --- a/src/WPStrava/Blocks/Activity.php +++ b/src/WPStrava/Blocks/Activity.php @@ -85,7 +85,7 @@ public function render_block( $attributes, $content ) { } /** - * Enqueue style if shortcode is being used. + * Enqueue style if block is being used. * * @author Justin Foell * @since 2.5.0 diff --git a/src/WPStrava/Blocks/Route.php b/src/WPStrava/Blocks/Route.php new file mode 100644 index 0000000..eba2306 --- /dev/null +++ b/src/WPStrava/Blocks/Route.php @@ -0,0 +1,98 @@ + + * @since 2.6.0 + */ + private $add_script = false; + + /** + * Register the wp-strava/route block. + * + * @author Justin Foell + * @since 2.6.0 + */ + public function register_block() { + register_block_type( + 'wp-strava/route', + array( + 'style' => 'wp-strava-block', + 'editor_style' => 'wp-strava-block-editor', + 'editor_script' => 'wp-strava-block', + 'render_callback' => array( $this, 'render_block' ), + 'attributes' => array( + 'url' => array( + 'type' => 'string', + 'default' => '', + ), + 'imageOnly' => array( + 'type' => 'boolean', + 'default' => false, + ), + 'displayMarkers' => array( + 'type' => 'boolean', + 'default' => false, + ), + 'som' => array( + 'type' => 'string', + 'default' => null, + ), + ), + ) + ); + add_action( 'wp_footer', array( $this, 'print_scripts' ) ); + } + + /** + * Render for this block. + * + * @param array $attributes JSON attributes saved in the HTML comment for this block. + * @param string $content The content from JS save() for this block. + * @return string HTML for this block. + * @author Justin Foell + * @since 2.6.0 + */ + public function render_block( $attributes, $content ) { + if ( empty( $attributes['url'] ) ) { + return $content; + } + + $this->add_script = true; + + $matches = []; + preg_match( '/\/routes\/([0-9].*)$/', $attributes['url'], $matches ); + if ( $matches[1] ) { + // Transform from block attributes to shortcode standard. + $attributes = array( + 'id' => $matches[1], + 'image_only' => isset( $attributes['imageOnly'] ) ? $attributes['imageOnly'] : false, + 'markers' => isset( $attributes['displayMarkers'] ) ? $attributes['displayMarkers'] : false, + 'som' => ! empty( $attributes['som'] ) ? $attributes['som'] : null, + ); + + $renderer = new WPStrava_RouteRenderer(); + return $renderer->get_html( $attributes ); + } + return $content; + } + + /** + * Enqueue style if block is being used. + * + * @author Justin Foell + * @since 2.6.0 + */ + public function print_scripts() { + if ( $this->add_script ) { + wp_enqueue_style( 'wp-strava-style' ); + } + } +} diff --git a/src/WPStrava/RouteRenderer.php b/src/WPStrava/RouteRenderer.php new file mode 100644 index 0000000..0d13a3a --- /dev/null +++ b/src/WPStrava/RouteRenderer.php @@ -0,0 +1,117 @@ + + * @since 2.6.0 + */ + public function get_html( $atts ) { + $defaults = array( + 'id' => 0, + 'som' => WPStrava::get_instance()->settings->som, + 'map_width' => '480', + 'map_height' => '320', + 'client_id' => WPStrava::get_instance()->settings->get_default_id(), + 'markers' => false, + 'image_only' => false, + ); + + $atts = wp_parse_args( $atts, $defaults ); + + /* Make sure boolean values are actually boolean + * @see https://wordpress.stackexchange.com/a/119299 + */ + $atts['markers'] = filter_var( $atts['markers'], FILTER_VALIDATE_BOOLEAN ); + $atts['image_only'] = filter_var( $atts['image_only'], FILTER_VALIDATE_BOOLEAN ); + + $route = WPStrava::get_instance()->routes; + $route_details = null; + + try { + $route_details = $route->get_route( $atts['client_id'], $atts['id'] ); + } catch ( WPStrava_Exception $e ) { + return $e->to_html(); + } + + $route_output = ''; + if ( $route_details ) { + $route_output = '
'; + if ( ! $atts['image_only'] ) { + $route_output .= $this->get_table( $route_details, $atts['som'] ); + } + + // Sanitize width & height. + $map_width = str_replace( '%', '', $atts['map_width'] ); + $map_height = str_replace( '%', '', $atts['map_height'] ); + $map_width = str_replace( 'px', '', $map_width ); + $map_height = str_replace( 'px', '', $map_height ); + + $route_output .= $route->get_route_link( + $route_details->id, + WPStrava_StaticMap::get_image_tag( $route_details, $map_height, $map_width, $atts['markers'], $route_details->name ), + $route_details->name + ); + + if ( ! empty( $route_details->description ) ) { + $route_output .= '
' . esc_html( $route_details->description ) . '
'; + } + + $route_output .= '
'; + } // End if( $route_details ). + return $route_output; + } + + /** + * The the route details in in HTML table. + * + * @param stdClass $route_details route details from the route class. + * @param string $som System of measure (english/metric). + * @return string HTML Table of route details. + * @author Justin Foell + * @since 1.7.0 + */ + private function get_table( $route_details, $som ) { + $strava_som = WPStrava_SOM::get_som( $som ); + + $elevation_title = '' . __( 'Elevation Gain', 'wp-strava' ) . ''; + $elevation = '' . $strava_som->elevation( $route_details->elevation_gain ) . ''; + $elevation_label = '' . $strava_som->get_elevation_label() . ''; + + if ( WPStrava::get_instance()->settings->hide_elevation ) { + $elevation = ''; + $elevation_title = ''; + $elevation_label = ''; + } + + return ' + + + + + + ' . $elevation_title . ' + + + + + + + ' . $elevation . ' + + + + + ' . $elevation_label . ' + + +
' . __( 'Est. Moving Time', 'wp-strava' ) . '' . __( 'Distance', 'wp-strava' ) . '
' . $strava_som->time( $route_details->estimated_moving_time ) . '' . $strava_som->distance( $route_details->distance ) . '
' . $strava_som->get_time_label() . '' . $strava_som->get_distance_label() . '
+ '; + } +} diff --git a/src/WPStrava/RouteShortcode.php b/src/WPStrava/RouteShortcode.php index f56f6d3..4a9aa54 100644 --- a/src/WPStrava/RouteShortcode.php +++ b/src/WPStrava/RouteShortcode.php @@ -51,99 +51,8 @@ public function handler( $atts ) { $this->add_script = true; - $defaults = array( - 'id' => 0, - 'som' => WPStrava::get_instance()->settings->som, - 'map_width' => '480', - 'map_height' => '320', - 'client_id' => WPStrava::get_instance()->settings->get_default_id(), - 'markers' => false, - 'image_only' => false, - ); - - $atts = shortcode_atts( $defaults, $atts, 'route' ); - - /* Make sure boolean values are actually boolean - * @see https://wordpress.stackexchange.com/a/119299 - */ - $atts['markers'] = filter_var( $atts['markers'], FILTER_VALIDATE_BOOLEAN ); - $atts['image_only'] = filter_var( $atts['image_only'], FILTER_VALIDATE_BOOLEAN ); - - $route = WPStrava::get_instance()->routes; - $route_details = null; - - try { - $route_details = $route->get_route( $atts['id'] ); - } catch ( WPStrava_Exception $e ) { - return $e->to_html(); - } - - $route_output = ''; - if ( $route_details ) { - $route_output = '
'; - if ( ! $atts['image_only'] ) { - $route_output .= $this->get_table( $route_details, $atts['som'] ); - } - - // Sanitize width & height. - $map_width = str_replace( '%', '', $atts['map_width'] ); - $map_height = str_replace( '%', '', $atts['map_height'] ); - $map_width = str_replace( 'px', '', $map_width ); - $map_height = str_replace( 'px', '', $map_height ); - - $route_output .= '' . - WPStrava_StaticMap::get_image_tag( $route_details, $map_height, $map_width, $atts['markers'] ) . - ' -
'; - } // End if( $route_details ). - return $route_output; - } - - /** - * The the route details in in HTML table. - * - * @param stdClass $route_details route details from the route class. - * @param string $som System of measure (english/metric). - * @return string HTML Table of route details. - * @author Justin Foell - * @since 1.7.0 - */ - private function get_table( $route_details, $som ) { - $strava_som = WPStrava_SOM::get_som( $som ); - - $elevation_title = '' . __( 'Elevation Gain', 'wp-strava' ) . ''; - $elevation = '' . $strava_som->elevation( $route_details->elevation_gain ) . ''; - $elevation_label = '' . $strava_som->get_elevation_label() . ''; - - if ( WPStrava::get_instance()->settings->hide_elevation ) { - $elevation = ''; - $elevation_title = ''; - $elevation_label = ''; - } - - return ' - - - - - - ' . $elevation_title . ' - - - - - - - ' . $elevation . ' - - - - - ' . $elevation_label . ' - - -
' . __( 'Est. Moving Time', 'wp-strava' ) . '' . __( 'Distance', 'wp-strava' ) . '
' . $strava_som->time( $route_details->estimated_moving_time ) . '' . $strava_som->distance( $route_details->distance ) . '
' . $strava_som->get_time_label() . '' . $strava_som->get_distance_label() . '
- '; + $renderer = new WPStrava_RouteRenderer(); + return $renderer->get_html( $atts ); } /** diff --git a/src/WPStrava/Routes.php b/src/WPStrava/Routes.php index 7329084..6129493 100644 --- a/src/WPStrava/Routes.php +++ b/src/WPStrava/Routes.php @@ -12,11 +12,34 @@ class WPStrava_Routes { /** * Get single route by ID. * - * @param int $route_id ID of activity to retrieve. - * @return object stdClass representing this route. + * @param string $client_id Client ID of athlete to retrieve for + * @param int $route_id ID of route to retrieve. + * @return object stdClass representing this route. * @author Daniel Lintott + * + * @since 1.3.0 */ - public function get_route( $route_id ) { - return WPStrava::get_instance()->get_api()->get( "routes/{$route_id}" ); + public function get_route( $client_id, $route_id ) { + return WPStrava::get_instance()->get_api( $client_id )->get( "routes/{$route_id}" ); } + + /** + * Conditionally display a link based on settings. + * + * @param int $route_id Strava Route ID + * @param string $text Text (or HTML) that is the content of link. + * @param string $title Title attribute (default empty). + * @return void + * @author Justin Foell + * @since 2.6.0 + */ + public function get_route_link( $route_id, $text, $title = '' ) { + if ( WPStrava::is_rest_request() || WPStrava::get_instance()->settings->no_link ) { + return $text; + } + $url = esc_url( self::ROUTES_URL . $route_id ); + $title_attr = $title ? " title='" . esc_attr( $title ) . "'" : ''; + return "{$text}"; + } + } diff --git a/src/blocks/activity/edit.js b/src/blocks/activity/edit.js index 1a34ac9..aac558a 100644 --- a/src/blocks/activity/edit.js +++ b/src/blocks/activity/edit.js @@ -1,6 +1,6 @@ /* global wp, wpStrava */ -import EmbedPlaceholder from './embed-placeholder'; -import EmbedControls from './embed-controls'; +import EmbedPlaceholder from '../components/embed-placeholder'; +import EmbedControls from '../components/embed-controls'; import SOMOverride from '../components/som-override'; const { __ } = wp.i18n; @@ -69,7 +69,12 @@ class Edit extends Component { return ( @@ -95,15 +100,15 @@ class Edit extends Component { /> this.toggleImageOnly( checked ) } /> this.toggleDisplayMarkers( checked ) } /> diff --git a/src/blocks/activity/embed-controls.js b/src/blocks/components/embed-controls.js similarity index 80% rename from src/blocks/activity/embed-controls.js rename to src/blocks/components/embed-controls.js index f03b9f6..21d13ad 100644 --- a/src/blocks/activity/embed-controls.js +++ b/src/blocks/components/embed-controls.js @@ -18,9 +18,11 @@ const EmbedControls = ( props ) => { return ( <> - + diff --git a/src/blocks/route/edit.js b/src/blocks/route/edit.js new file mode 100644 index 0000000..39a9973 --- /dev/null +++ b/src/blocks/route/edit.js @@ -0,0 +1,125 @@ +/* global wp, wpStrava */ +import EmbedPlaceholder from '../components/embed-placeholder'; +import EmbedControls from '../components/embed-controls'; +import SOMOverride from '../components/som-override'; + +const { __ } = wp.i18n; +const { Component } = wp.element; +const { InspectorControls } = wp.editor; +const { PanelBody, ToggleControl, ServerSideRender } = wp.components; +const { isEmpty } = lodash; + +class Edit extends Component { + + constructor() { + super( ...arguments ); + this.setUrl = this.setUrl.bind( this ); + this.switchBackToURLInput = this.switchBackToURLInput.bind( this ); + this.toggleImageOnly = this.toggleImageOnly.bind( this ); + this.toggleDisplayMarkers = this.toggleDisplayMarkers.bind( this ); + this.overrideSOM = this.overrideSOM.bind( this ); + + this.state = { + url: this.props.attributes.url, + imageOnly: this.props.attributes.imageOnly, + displayMarkers: this.props.attributes.displayMarkers, + som: this.props.attributes.som, + editingURL: isEmpty( this.props.attributes.url ) ? true : false, + }; + } + + setUrl( event ) { + if ( event ) { + event.preventDefault(); + } + this.setState( { editingURL: false } ); + this.props.setAttributes( { url: this.state.url } ); + } + + switchBackToURLInput() { + this.setState( { editingURL: true } ); + } + + toggleImageOnly( checked ) { + this.setState( { imageOnly: checked } ); + this.props.setAttributes( { imageOnly: checked } ); + } + + toggleDisplayMarkers( checked ) { + this.setState( { displayMarkers: checked } ); + this.props.setAttributes( { displayMarkers: checked } ); + } + + overrideSOM( newSOM ) { + this.setState( { som: newSOM } ); + this.props.setAttributes( { som: newSOM } ); + } + + render() { + const { + url, + editingURL, + imageOnly, + displayMarkers, + som + } = this.state; + + // Newly inserted block or we've clicked the edit button. + if ( editingURL ) { + return ( + + this.setState( { url: event.target.value } ) + } + /> + ); + } + + return ( + <> + + + + + this.toggleImageOnly( checked ) } + /> + this.toggleDisplayMarkers( checked ) } + /> + + + + + ); + } +} + +export default Edit; diff --git a/src/blocks/route/index.js b/src/blocks/route/index.js new file mode 100644 index 0000000..3a6a155 --- /dev/null +++ b/src/blocks/route/index.js @@ -0,0 +1,29 @@ +/* global wp, wpStrava */ +import { registerBlockType } from '@wordpress/blocks'; +import edit from './edit'; + +registerBlockType( 'wp-strava/route', { + title: 'Strava Route', + icon: 'location-alt', + category: 'embed', + attributes: { + url: { + type: 'string', + default: '', + }, + imageOnly: { + type: 'boolean', + default: false, + }, + displayMarkers: { + type: 'boolean', + default: false, + }, + som: { + type: 'string', + default: null, + }, + }, + edit, + save: () => null, +} ); diff --git a/src/index.js b/src/index.js index 2214244..ab46a48 100644 --- a/src/index.js +++ b/src/index.js @@ -1 +1,2 @@ import './blocks/activity'; +import './blocks/route'; diff --git a/wp-strava.php b/wp-strava.php index dd94dff..1aae0fe 100755 --- a/wp-strava.php +++ b/wp-strava.php @@ -3,7 +3,7 @@ * Plugin Name: WP Strava * Plugin URI: https://wordpress.org/plugins/wp-strava/ * Description: Show your strava.com activity on your WordPress site. Some Icons are Copyright © Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 license. - * Version: 2.5.1 + * Version: 2.6.0 * Author: Carlos Santa Cruz, Justin Foell, Lance Willett, Daniel Lintott, Sebastian Erb * License: GPL2 * Text Domain: wp-strava @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -define( 'WPSTRAVA_PLUGIN_VERSION', '2.5.1' ); +define( 'WPSTRAVA_PLUGIN_VERSION', '2.6.0' ); define( 'WPSTRAVA_PLUGIN_FILE', __FILE__ ); define( 'WPSTRAVA_PLUGIN_DIR', trailingslashit( dirname( __FILE__ ) ) ); define( 'WPSTRAVA_PLUGIN_URL', plugins_url( '/', __FILE__ ) );