Changeset 3002715
- Timestamp:
- 11/28/2023 12:25:19 PM (2 years ago)
- Location:
- indieblocks
- Files:
-
- 26 edited
- 1 copied
-
tags/0.10.0 (copied) (copied from indieblocks/trunk)
-
tags/0.10.0/blocks/facepile/block.json (modified) (1 diff)
-
tags/0.10.0/blocks/link-preview/class-link-preview-block.php (modified) (1 diff)
-
tags/0.10.0/includes/class-parser.php (modified) (2 diffs)
-
tags/0.10.0/includes/class-plugin.php (modified) (1 diff)
-
tags/0.10.0/includes/class-theme-mf2.php (modified) (2 diffs)
-
tags/0.10.0/includes/class-webmention-parser.php (modified) (1 diff)
-
tags/0.10.0/includes/class-webmention-receiver.php (modified) (6 diffs)
-
tags/0.10.0/includes/class-webmention-sender.php (modified) (9 diffs)
-
tags/0.10.0/includes/class-webmention.php (modified) (1 diff)
-
tags/0.10.0/includes/functions.php (modified) (3 diffs)
-
tags/0.10.0/indieblocks.php (modified) (1 diff)
-
tags/0.10.0/languages/indieblocks.pot (modified) (4 diffs)
-
tags/0.10.0/readme.txt (modified) (4 diffs)
-
trunk/blocks/facepile/block.json (modified) (1 diff)
-
trunk/blocks/link-preview/class-link-preview-block.php (modified) (1 diff)
-
trunk/includes/class-parser.php (modified) (2 diffs)
-
trunk/includes/class-plugin.php (modified) (1 diff)
-
trunk/includes/class-theme-mf2.php (modified) (2 diffs)
-
trunk/includes/class-webmention-parser.php (modified) (1 diff)
-
trunk/includes/class-webmention-receiver.php (modified) (6 diffs)
-
trunk/includes/class-webmention-sender.php (modified) (9 diffs)
-
trunk/includes/class-webmention.php (modified) (1 diff)
-
trunk/includes/functions.php (modified) (3 diffs)
-
trunk/indieblocks.php (modified) (1 diff)
-
trunk/languages/indieblocks.pot (modified) (4 diffs)
-
trunk/readme.txt (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
indieblocks/tags/0.10.0/blocks/facepile/block.json
r2961482 r3002715 29 29 "fontSize": true 30 30 } 31 }, 32 "spacing": { 33 "margin": ["top", "bottom"], 34 "padding": false, 35 "blockGap": false 31 36 } 32 37 } -
indieblocks/tags/0.10.0/blocks/link-preview/class-link-preview-block.php
r2993569 r3002715 68 68 69 69 if ( ! empty( $card['thumbnail'] ) ) : 70 // Check if file still exists. 71 $upload_dir = wp_upload_dir(); 72 $file_path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $card['thumbnail'] ); 73 74 if ( is_file( $file_path ) ) : 75 ?> 76 <img src="<?php echo esc_url_raw( $card['thumbnail'] ); ?>" width="90" height="90" alt=""> 77 <?php 78 endif; 70 ?> 71 <img src="<?php echo esc_url_raw( $card['thumbnail'] ); ?>" width="90" height="90" alt=""> 72 <?php 79 73 endif; 80 74 -
indieblocks/tags/0.10.0/includes/class-parser.php
r2993569 r3002715 84 84 85 85 if ( empty( $mf2 ) ) { 86 $fragment = wp_parse_url( $this->url, PHP_URL_FRAGMENT ); 87 if ( ! empty( $fragment ) ) { 88 // If the URL contains a fragment, parse only the corresponding 89 // page section. 90 // @todo: Do this for `$this->dom`, too? 91 $xpath = new \DOMXPath( $this->dom ); 92 93 foreach ( $xpath->query( "//*[@id='$fragment']" ) as $el ) { 94 $content = $this->dom->saveHTML( $el ); 95 break; 96 } 97 } 98 86 99 $mf2 = Mf2\parse( $content, $this->url ); 87 100 set_transient( 'indieblocks:mf2:' . $hash, $mf2, 3600 ); 88 101 } 89 102 90 $this->mf2 = Mf2\parse( $content, $this->url );103 $this->mf2 = $mf2; 91 104 } 92 105 … … 297 310 if ( ! empty( $this->mf2['items'][0]['properties']['content'][0]['html'] ) ) { 298 311 return $this->mf2['items'][0]['properties']['content'][0]['html']; 312 } elseif ( ! empty( $this->mf2['items'][0]['properties']['content'][0]['text'] ) ) { 313 return $this->mf2['items'][0]['properties']['content'][0]['text']; 314 } elseif ( ! empty( $this->mf2['items'][0]['properties']['content'][0] && is_string( $this->mf2['items'][0]['properties']['content'][0] ) ) ) { 315 return $this->mf2['items'][0]['properties']['content'][0]; 299 316 } 300 317 -
indieblocks/tags/0.10.0/includes/class-plugin.php
r2993569 r3002715 12 12 * Plugin version. 13 13 */ 14 const PLUGIN_VERSION = '0. 9.1';14 const PLUGIN_VERSION = '0.10.0'; 15 15 16 16 /** -
indieblocks/tags/0.10.0/includes/class-theme-mf2.php
r2993569 r3002715 178 178 $processor->add_class( 'h-card u-author' ); 179 179 180 if ( ! empty( $instance->attributes['avatarSize'] ) ) {180 if ( ! empty( $instance->attributes['avatarSize'] ) && ! empty( $instance->attributes['showAvatar'] ) ) { 181 181 $processor->next_tag( 'img' ); 182 182 $processor->add_class( 'u-photo' ); … … 481 481 } 482 482 483 $upload_dir = wp_upload_dir();484 $file_path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $url );485 486 if ( ! is_file( $file_path ) ) {487 return null;488 }489 490 483 $width = (int) ( ! empty( $args['width'] ) ? $args['width'] : 96 ); 491 484 $height = (int) ( ! empty( $args['height'] ) ? $args['height'] : 96 ); -
indieblocks/tags/0.10.0/includes/class-webmention-parser.php
r2961482 r3002715 63 63 if ( ! empty( $published ) ) { 64 64 $commentdata['comment_date'] = get_date_from_gmt( $published, 'Y-m-d H:i:s' ); 65 $commentdata['comment_date_gmt'] = date( 'Y-m-d H:i:s', strtotime( $published ) ); 66 } 67 68 $commentdata['comment_meta']['indieblocks_webmention_source'] = esc_url_raw( $parser->get_url() ?: $source ); // phpcs:ignore WordPress.PHP.DisallowShortTernary.Found65 $commentdata['comment_date_gmt'] = date( 'Y-m-d H:i:s', strtotime( $published ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date 66 } 67 68 $commentdata['comment_meta']['indieblocks_webmention_source'] = esc_url_raw( $parser->get_url() ?: $source ); // phpcs:ignore Universal.Operators.DisallowShortTernary.Found 69 69 70 70 $hentry_kind = $parser->get_type(); -
indieblocks/tags/0.10.0/includes/class-webmention-receiver.php
r2993569 r3002715 103 103 104 104 $table_name = $wpdb->prefix . 'indieblocks_webmentions'; 105 $webmentions = $wpdb->get_results( "SELECT id, source, post_id, ip, created_at FROM $table_name WHERE status = 'draft' LIMIT 5" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared105 $webmentions = $wpdb->get_results( "SELECT id, source, target, post_id, ip, created_at FROM $table_name WHERE status = 'draft' LIMIT 5" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared 106 106 107 107 if ( empty( $webmentions ) || ! is_array( $webmentions ) ) { … … 131 131 'key' => 'indieblocks_webmention_source', 132 132 'compare' => '=', 133 'value' => esc_url( $webmention->source ), 133 'value' => esc_url_raw( $webmention->source ), 134 ), 135 array( 136 'key' => 'indieblocks_webmention_target', 137 'compare' => 'EXISTS', 138 ), 139 array( 140 'key' => 'indieblocks_webmention_target', 141 'compare' => '=', 142 'value' => esc_url_raw( $webmention->target ), 134 143 ), 135 144 ), … … 205 214 $host = wp_parse_url( $webmention->source, PHP_URL_HOST ); 206 215 216 // Look for a target URL fragment (and possible parent comment). 217 $fragment = wp_parse_url( $webmention->target, PHP_URL_FRAGMENT ); 218 if ( ! empty( $fragment ) && preg_match( '~^comment-\d+$~', $fragment ) ) { 219 $parent = get_comment( str_replace( 'comment-', '', str_replace( 'comment-', '', $fragment ) ) ); 220 } 221 207 222 // Some defaults. 208 223 $commentdata = array( … … 213 228 'comment_author_IP' => $webmention->ip, 214 229 'comment_content' => __( '… commented on this.', 'indieblocks' ), 215 'comment_parent' => 0,230 'comment_parent' => ! empty( $parent ) && $webmention->post_id === $parent->comment_post_ID ? $parent->comment_ID : 0, 216 231 'user_id' => 0, 217 232 'comment_date' => $webmention->created_at, … … 220 235 'comment_meta' => array( 221 236 'indieblocks_webmention_source' => esc_url_raw( $webmention->source ), 237 'indieblocks_webmention_target' => esc_url_raw( $webmention->target ), 222 238 ), 223 239 ); … … 371 387 372 388 // Delete file. 373 if ( is_file( $file_path ) ) { 374 wp_delete_file( $file_path ); 375 } 376 377 // Delete reference in database. 378 delete_comment_meta( $comment_id, 'indieblocks_webmention_avatar' ); 389 wp_delete_file( $file_path ); 390 391 // Delete _all_ references to this file (i.e., not just this 392 // comment's meta field). 393 global $wpdb; 394 395 $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 396 $wpdb->prepare( 397 "DELETE FROM $wpdb->commentmeta WHERE meta_key = %s AND meta_value = %s", 398 'indieblocks_webmention_avatar', 399 esc_url_raw( $url ) 400 ) 401 ); 379 402 } 380 403 -
indieblocks/tags/0.10.0/includes/class-webmention-sender.php
r2993569 r3002715 18 18 * callback function queued in the background. 19 19 * 20 * @param string $new_status New post status. 21 * @param string $old_status Old post status. 22 * @param WP_Post $post Post object. 23 */ 24 public static function schedule_webmention( $new_status, $old_status, $post ) { 25 if ( wp_is_post_revision( $post->ID ) || wp_is_post_autosave( $post->ID ) ) { 26 return; 27 } 28 29 /* @see https://github.com/WordPress/gutenberg/issues/15094#issuecomment-1021288811. */ 30 if ( ! empty( $_REQUEST['meta-box-loader'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 31 // Avoid scheduling (or posting, in case of no delay) webmentions 32 // more than once. 33 return; 20 * @param int $obj_id Post or comment ID. 21 * @param \WP_Post|\WP_Comment $obj Post or comment object. 22 * @param mixed $deprecated Used to be the post object, now deprecated. 23 */ 24 public static function schedule_webmention( $obj_id, $obj = null, $deprecated = null ) { 25 if ( null !== $deprecated ) { 26 _deprecated_argument( 'post', '0.10.0', 'Passing a third argument to `\IndieBlocks\Webmention_Sender::schedule_webmention()` is deprecated.' ); 34 27 } 35 28 … … 39 32 } 40 33 41 if ( 'publish' !== $new_status ) { 34 if ( 'comment_post' === current_filter() ) { 35 $obj = get_comment( $obj_id ); 36 } 37 38 if ( $obj instanceof \WP_Post ) { 39 if ( 'publish' !== $obj->post_status ) { 40 // Do not send webmention on delete/unpublish, for now. 41 return; 42 } 43 44 /* @see https://github.com/WordPress/gutenberg/issues/15094#issuecomment-1021288811. */ 45 if ( ! empty( $_REQUEST['meta-box-loader'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 46 // Avoid scheduling (or posting, in case of no delay) webmentions 47 // more than once. 48 return; 49 } 50 51 if ( wp_is_post_revision( $obj->ID ) || wp_is_post_autosave( $obj->ID ) ) { 52 return; 53 } 54 55 if ( ! in_array( $obj->post_type, Webmention::get_supported_post_types(), true ) ) { 56 return; 57 } 58 } elseif ( '1' !== $obj->comment_approved ) { 42 59 // Do not send webmention on delete/unpublish, for now. 43 60 return; 44 61 } 45 62 46 if ( ! in_array( $post->post_type, Webmention::get_supported_post_types(), true ) ) { 47 return; 48 } 49 50 // Fetch our post's HTML. 51 $html = apply_filters( 'the_content', $post->post_content ); 52 53 // Scan it for outgoing links. 54 $urls = static::find_outgoing_links( $html ); 55 56 // Parse in targets that may have been there previously, but don't delete 57 // them, yet. 58 $history = get_post_meta( $post->ID, '_indieblocks_webmention_history', true ); 63 $urls = array(); 64 65 if ( $obj instanceof \WP_Post ) { 66 // Fetch our post's HTML. 67 $html = apply_filters( 'the_content', $obj->post_content ); 68 69 // Scan it for outgoing links. 70 $urls = static::find_outgoing_links( $html ); 71 } elseif ( ! empty( $obj->comment_parent ) ) { 72 // Add in the parent's, if any, Webmention source. 73 $source = get_comment_meta( $obj->comment_parent, 'indieblocks_webmention_source', true ); 74 if ( ! empty( $source ) ) { 75 $urls[] = $source; 76 } 77 } 78 79 // Parse in targets that may have been there previously, but don't 80 // delete them, yet. 81 $history = get_meta( $obj, '_indieblocks_webmention_history' ); 82 59 83 if ( ! empty( $history ) && is_array( $history ) ) { 60 $urls = array_ unique( array_merge( $urls, $history ));61 } 62 63 if ( empty( $urls ) || ! is_array( $urls )) {84 $urls = array_merge( $urls, $history ); 85 } 86 87 if ( empty( $urls ) ) { 64 88 // Nothing to do. Bail. 65 89 return; 66 90 } 67 91 92 $urls = array_unique( $urls ); 68 93 $schedule = false; 69 94 … … 91 116 92 117 // Schedule sending out the actual webmentions. 93 error_log( "[Indieblocks/Webmention] Scheduling webmention for post {$post->ID}." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 94 wp_schedule_single_event( time() + $delay, 'indieblocks_webmention_send', array( $post->ID ) ); 95 96 add_post_meta( $post->ID, '_indieblocks_webmention', 'scheduled', true ); // Does not affect existing values. 118 if ( $obj instanceof \WP_Post ) { 119 error_log( "[Indieblocks/Webmention] Scheduling webmention for post {$obj->ID}." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 120 } else { 121 error_log( "[Indieblocks/Webmention] Scheduling webmention for comment {$obj->comment_ID}." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 122 } 123 124 add_meta( $obj, '_indieblocks_webmention', 'scheduled' ); 125 wp_schedule_single_event( time() + $delay, 'indieblocks_webmention_send', array( $obj ) ); 97 126 } else { 98 127 // Send inline (although retries will be scheduled as always). 99 static::send_webmention( $ post->ID);128 static::send_webmention( $obj ); 100 129 } 101 130 } … … 106 135 * a post. 107 136 * 108 * @param int $post_id Post ID. 109 */ 110 public static function send_webmention( $post_id ) { 111 $post = get_post( $post_id ); 112 113 if ( 'publish' !== $post->post_status ) { 114 // Do not send webmentions on delete/unpublish, for now. 115 return; 116 } 117 118 if ( ! in_array( $post->post_type, Webmention::get_supported_post_types(), true ) ) { 119 // This post type doesn't support Webmention. 120 return; 121 } 122 123 // Fetch our post's HTML. 124 $html = apply_filters( 'the_content', $post->post_content ); 125 126 // Scan it for outgoing links, again, as things might have changed. 127 $urls = static::find_outgoing_links( $html ); 128 129 // Parse in (and then forget) targets that may have been there before. 137 * @param \WP_Post|\WP_Comment $obj Post or comment object. 138 */ 139 public static function send_webmention( $obj ) { 140 if ( $obj instanceof \WP_Post ) { 141 if ( 'publish' !== $obj->post_status ) { 142 // Do not send webmention on delete/unpublish, for now. 143 return; 144 } 145 146 if ( ! in_array( $obj->post_type, Webmention::get_supported_post_types(), true ) ) { 147 // This post type doesn't support Webmention. 148 return; 149 } 150 } elseif ( '1' !== $obj->comment_approved ) { 151 return; 152 } 153 154 $urls = array(); 155 156 if ( $obj instanceof \WP_Post ) { 157 // Fetch our post's HTML. 158 $html = apply_filters( 'the_content', $obj->post_content ); 159 160 // Scan it for outgoing links. 161 $urls = static::find_outgoing_links( $html ); 162 } elseif ( ! empty( $obj->comment_parent ) ) { 163 // Add in the parent's, if any, Webmention source. 164 $source = get_comment_meta( $obj->comment_parent, 'indieblocks_webmention_source', true ); 165 if ( ! empty( $source ) ) { 166 $urls[] = $source; 167 } 168 } 169 170 // Parse in (_and_ then forget) targets that may have been there before. 130 171 // This also means that "historic" targets are excluded from retries! 131 172 // Note that we _also_ retarget pages that threw an error or we 132 173 // otherwise failed to reach previously. Both are probably acceptable. 133 $history = get_post_meta( $post->ID, '_indieblocks_webmention_history', true ); 134 delete_post_meta( $post->ID, '_indieblocks_webmention_history' ); 174 $history = get_meta( $obj, '_indieblocks_webmention_history' ); 175 delete_meta( $obj, '_indieblocks_webmention_history' ); 176 135 177 if ( ! empty( $history ) && is_array( $history ) ) { 136 $urls = array_ unique( array_merge( $urls, $history ));137 } 138 139 if ( empty( $urls ) || ! is_array( $urls )) {178 $urls = array_merge( $urls, $history ); 179 } 180 181 if ( empty( $urls ) ) { 140 182 // One or more links must've been removed. Nothing to do. Bail. 141 183 return; 142 184 } 143 185 186 $urls = array_unique( $urls ); 187 144 188 // Fetch whatever Webmention-related stats we've got for this post. 145 $webmention = get_ post_meta( $post->ID, '_indieblocks_webmention', true);189 $webmention = get_meta( $obj, '_indieblocks_webmention' ); 146 190 147 191 if ( empty( $webmention ) || ! is_array( $webmention ) ) { … … 157 201 if ( empty( $endpoint ) || false === wp_http_validate_url( $endpoint ) ) { 158 202 // Skip. 203 error_log( '[Indieblocks/Webmention] Could not find a Webmention endpoint for target ' . esc_url_raw( $url ) . '.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 159 204 continue; 160 205 } … … 190 235 array( 191 236 'body' => array( 192 'source' => get_permalink( $post->ID ),237 'source' => $obj instanceof \WP_Post ? get_permalink( $obj->ID ) : get_comment_link( $obj->comment_ID ), 193 238 'target' => $url, 194 239 ), … … 196 241 ); 197 242 198 if ( is_wp_error( $response ) ) {243 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) >= 500 ) { 199 244 // Something went wrong. 200 245 error_log( '[Indieblocks/Webmention] Error trying to send a webmention to ' . esc_url_raw( $endpoint ) . ': ' . $response->get_error_message() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 246 error_log( print_r( $response, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r 201 247 202 248 $webmention[ $hash ]['retries'] = $retries + 1; 203 update_post_meta( $post->ID, '_indieblocks_webmention', $webmention ); 249 250 update_meta( $obj, '_indieblocks_webmention', $webmention ); 204 251 205 252 // Schedule a retry in 5 to 15 minutes. 206 wp_schedule_single_event( time() + wp_rand( 300, 900 ), 'indieblocks_webmention_send', array( $post->ID ) ); 207 208 continue; 209 } elseif ( wp_remote_retrieve_response_code( $response ) >= 500 ) { 210 // Something went wrong. 211 error_log( '[Indieblocks/Webmention] Error trying to send a webmention to ' . esc_url_raw( $endpoint ) . '.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 212 error_log( print_r( $response, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r 213 214 $webmention[ $hash ]['retries'] = $retries + 1; 215 update_post_meta( $post->ID, '_indieblocks_webmention', $webmention ); 216 217 // Schedule a retry in 5 to 15 minutes. 218 wp_schedule_single_event( time() + wp_rand( 300, 900 ), 'indieblocks_webmention_send', array( $post->ID ) ); 253 wp_schedule_single_event( time() + wp_rand( 300, 900 ), 'indieblocks_webmention_send', array( $obj ) ); 219 254 220 255 continue; … … 228 263 } 229 264 230 update_ post_meta( $post->ID, '_indieblocks_webmention', $webmention );265 update_meta( $obj, '_indieblocks_webmention', $webmention ); 231 266 } 232 267 … … 463 498 464 499 $post = get_post( $post_id ); 465 static::schedule_webmention( $post ->post_status, $post->post_status, $post );500 static::schedule_webmention( $post_id, $post ); 466 501 467 502 wp_die(); -
indieblocks/tags/0.10.0/includes/class-webmention.php
r2993569 r3002715 24 24 25 25 add_action( 'add_meta_boxes', array( Webmention_Sender::class, 'add_meta_box' ) ); 26 add_action( 'transition_post_status', array( Webmention_Sender::class, 'schedule_webmention' ), 10, 3 ); 26 27 foreach ( static::get_supported_post_types() as $post_type ) { 28 add_action( "publish_{$post_type}", array( Webmention_Sender::class, 'schedule_webmention' ), 10, 2 ); 29 } 30 31 // When a comment is first inserted into the database. 32 add_action( 'comment_post', array( Webmention_Sender::class, 'schedule_webmention' ) ); // Pass only one argument (the comment ID) to `Webmention_Sender::schedule_webmention()`! 33 // When a comment is approved. Or a previously approved comment updated. 34 add_action( 'comment_approved_comment', array( Webmention_Sender::class, 'schedule_webmention' ), 10, 2 ); 35 27 36 add_action( 'indieblocks_webmention_send', array( Webmention_Sender::class, 'send_webmention' ) ); 28 37 -
indieblocks/tags/0.10.0/includes/functions.php
r2993569 r3002715 39 39 */ 40 40 function debug_log( $item ) { 41 error_log( print_r( $item, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r41 error_log( is_string( $item ) ? $item : print_r( $item, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r 42 42 } 43 43 … … 283 283 } 284 284 } else { 285 debug_log( '[IndieBlocks] Could not re isize ' . $file_path . ': ' . $image->get_error_message() . '.' );285 debug_log( '[IndieBlocks] Could not resize ' . $file_path . ': ' . $image->get_error_message() . '.' ); 286 286 } 287 287 … … 376 376 return $facepile_comments; 377 377 } 378 379 /** 380 * Get post or comment meta. 381 * 382 * @param \WP_Post|\WP_Comment $obj Post or comment. 383 * @param string $meta_key The meta key. 384 * @return string The meta value (or an empty) string. 385 */ 386 function get_meta( $obj, $meta_key ) { 387 if ( $obj instanceof \WP_Post ) { 388 return get_post_meta( $obj->ID, $meta_key, true ); 389 } 390 391 if ( $obj instanceof \WP_Comment ) { 392 return get_comment_meta( $obj->comment_ID, $meta_key, true ); 393 } 394 395 return ''; 396 } 397 398 /** 399 * Update post or comment meta. 400 * 401 * @param \WP_Post|\WP_Comment $obj Post or comment. 402 * @param string $meta_key The meta key. 403 * @param mixed $meta_value The value. 404 */ 405 function add_meta( $obj, $meta_key, $meta_value ) { 406 if ( $obj instanceof \WP_Post ) { 407 add_post_meta( $obj->ID, $meta_key, $meta_value ); 408 } 409 410 if ( $obj instanceof \WP_Comment ) { 411 add_comment_meta( $obj->comment_ID, $meta_key, $meta_value ); 412 } 413 } 414 415 /** 416 * Update post or comment meta. 417 * 418 * @param \WP_Post|\WP_Comment $obj Post or comment. 419 * @param string $meta_key The meta key. 420 * @param mixed $meta_value The value. 421 */ 422 function update_meta( $obj, $meta_key, $meta_value ) { 423 if ( $obj instanceof \WP_Post ) { 424 update_post_meta( $obj->ID, $meta_key, $meta_value ); 425 } 426 427 if ( $obj instanceof \WP_Comment ) { 428 update_comment_meta( $obj->comment_ID, $meta_key, $meta_value ); 429 } 430 } 431 432 /** 433 * Delete post or comment meta. 434 * 435 * @param \WP_Post|\WP_Comment $obj Post or comment. 436 * @param string $meta_key The meta key. 437 */ 438 function delete_meta( $obj, $meta_key ) { 439 if ( $obj instanceof \WP_Post ) { 440 delete_post_meta( $obj->ID, $meta_key ); 441 } 442 443 if ( $obj instanceof \WP_Comment ) { 444 delete_comment_meta( $obj->comment_ID, $meta_key ); 445 } 446 } -
indieblocks/tags/0.10.0/indieblocks.php
r2993569 r3002715 9 9 * License URI: http://www.gnu.org/licenses/gpl-3.0.html 10 10 * Text Domain: indieblocks 11 * Version: 0. 9.111 * Version: 0.10.0 12 12 * Requires at least: 6.2 13 13 * GitHub Plugin URI: https://github.com/janboddez/indieblocks -
indieblocks/tags/0.10.0/languages/indieblocks.pot
r2993569 r3002715 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: IndieBlocks 0. 9.1\n"5 "Project-Id-Version: IndieBlocks 0.10.0\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/indieblocks\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2023-11- 08T20:41:32+00:00\n"12 "POT-Creation-Date: 2023-11-26T22:12:55+01:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 "X-Generator: WP-CLI 2. 6.0\n"14 "X-Generator: WP-CLI 2.9.0\n" 15 15 "X-Domain: indieblocks\n" 16 16 … … 165 165 #: includes/class-options-handler.php:376 166 166 #: includes/class-options-handler.php:479 167 #: includes/class-webmention-receiver.php: 288168 #: includes/class-webmention-sender.php: 372167 #: includes/class-webmention-receiver.php:304 168 #: includes/class-webmention-sender.php:416 169 169 msgid "Webmention" 170 170 msgstr "" … … 548 548 msgstr "" 549 549 550 #: includes/class-webmention-receiver.php:2 14550 #: includes/class-webmention-receiver.php:229 551 551 msgid "… commented on this." 552 552 msgstr "" 553 553 554 #: includes/class-webmention-receiver.php:3 07554 #: includes/class-webmention-receiver.php:323 555 555 msgid "Source" 556 556 msgstr "" 557 557 558 #: includes/class-webmention-receiver.php:3 10558 #: includes/class-webmention-receiver.php:326 559 559 #: blocks/context/block.js:67 560 560 msgid "Type" 561 561 msgstr "" 562 562 563 #: includes/class-webmention-receiver.php:3 14563 #: includes/class-webmention-receiver.php:330 564 564 msgid "Avatar" 565 565 msgstr "" 566 566 567 #: includes/class-webmention-receiver.php:3 18567 #: includes/class-webmention-receiver.php:334 568 568 msgid "Delete" 569 569 msgstr "" 570 570 571 #: includes/class-webmention-receiver.php:3 48572 #: includes/class-webmention-sender.php:4 39571 #: includes/class-webmention-receiver.php:364 572 #: includes/class-webmention-sender.php:483 573 573 msgid "Missing or invalid nonce." 574 574 msgstr "" 575 575 576 #: includes/class-webmention-receiver.php:3 54576 #: includes/class-webmention-receiver.php:370 577 577 msgid "Invalid comment ID." 578 578 msgstr "" 579 579 580 #: includes/class-webmention-receiver.php:3 62581 #: includes/class-webmention-sender.php:4 53580 #: includes/class-webmention-receiver.php:378 581 #: includes/class-webmention-sender.php:497 582 582 msgid "Insufficient rights." 583 583 msgstr "" 584 584 585 585 #. translators: 1: Webmention endpoint 2: Date sent 586 #: includes/class-webmention-sender.php:4 04586 #: includes/class-webmention-sender.php:448 587 587 msgid "Sent to %1$s on %2$s. Response code: %3$d." 588 588 msgstr "" 589 589 590 590 #. translators: 1: Webmention endpoint 2: Date sent 591 #: includes/class-webmention-sender.php:4 04591 #: includes/class-webmention-sender.php:448 592 592 msgid "M j, Y \\a\\t H:i" 593 593 msgstr "" 594 594 595 595 #. translators: Webmention endpoint 596 #: includes/class-webmention-sender.php:4 07596 #: includes/class-webmention-sender.php:451 597 597 msgid "Could not send webmention to %s." 598 598 msgstr "" 599 599 600 600 #. translators: Webmention endpoint 601 #: includes/class-webmention-sender.php:4 10601 #: includes/class-webmention-sender.php:454 602 602 msgid "Could not send webmention to %s. Trying again soon." 603 603 msgstr "" 604 604 605 #: includes/class-webmention-sender.php:4 20605 #: includes/class-webmention-sender.php:464 606 606 msgid "Resend" 607 607 msgstr "" 608 608 609 #: includes/class-webmention-sender.php:4 24610 #: includes/class-webmention.php:1 43609 #: includes/class-webmention-sender.php:468 610 #: includes/class-webmention.php:152 611 611 msgid "Webmention scheduled." 612 612 msgstr "" 613 613 614 #: includes/class-webmention-sender.php:4 26614 #: includes/class-webmention-sender.php:470 615 615 msgid "No endpoints found." 616 616 msgstr "" 617 617 618 #: includes/class-webmention-sender.php:4 45618 #: includes/class-webmention-sender.php:489 619 619 msgid "Invalid post ID." 620 620 msgstr "" -
indieblocks/tags/0.10.0/readme.txt
r2993569 r3002715 3 3 Tags: blocks, gutenberg, indieweb, notes, likes, microblog, microblogging, micropub, fse, site editor, webmention, syndication 4 4 Tested up to: 6.4 5 Stable tag: 0. 9.15 Stable tag: 0.10.0 6 6 License: GNU General Public License v3.0 7 7 License URI: https://www.gnu.org/licenses/gpl-3.0.html … … 10 10 11 11 == Description == 12 Use blocks, and, optionally, "short-form" post types to easily "IndieWebify" your WordPress site. 13 12 14 IndieBlocks registers several blocks (Bookmark, Like, Reply, and Repost, as well as the older Context block) that take a URL and output corresponding _microformatted_ HTML. 13 15 … … 18 20 These microformats, in combination with the Webmention protocol, allow for rich _cross-site_ conversations. IndieBlocks comes with its own Webmention implementation, but a separate plugin can be used, too. 19 21 20 IndieBlocks also registers several "theme" blocks (Facepile, Location, Syndication, and Link Preview), to be used in (block) themetemplates.22 IndieBlocks also registers several "theme" blocks (Facepile, Location, Syndication, and Link Preview), to be used in "block theme" templates. 21 23 22 24 == Installation == … … 27 29 More details can be found on [https://indieblocks.xyz/](https://indieblocks.xyz/). Issues may be filed at [https://github.com/janboddez/indieblocks](https://github.com/janboddez/indieblocks). 28 30 31 == Frequently Asked Questions == 32 = How does this plugin interact with the various other IndieWeb plugins? = 33 While IndieBlocks does not depend on _any_ other plugin, it is compatible with, and extends, the Micropub plugin for WordPress. See [https://indieblocks.xyz/documentation/micropub-and-indieauth/](https://indieblocks.xyz/documentation/micropub-and-indieauth/) for some more information. 34 35 IndieBlocks’ Facepile and Syndication blocks also aim to be compatible with, respectively, the Webmention and Syndication Links plugins. 36 29 37 == Changelog == 38 = 0.10.0 = 39 Send webmentions also for comments, to mentioned sites and the comment parent, if it exists and itself originated as a webmention. 40 30 41 = 0.9.1 = 31 42 Fix Webmention backlinks in Facepile block, add avatar background and icon color pickers. 43 32 44 = 0.9.0 = 33 45 Overhaul theme microformats functionality. 46 34 47 = 0.8.1 = 35 48 Fix issue with saving meta from block editor. Fix Markdown in Micropub notes. 49 36 50 = 0.8.0 = 37 51 Various bug fixes. Add Link Preview block. Also, webmentions are now closed when comments are, although this behavior is filterable. 52 38 53 = 0.7.1 = 39 54 Add Location block. The Facepile block now supports v5.0 and up of the Webmention plugin. 55 40 56 = 0.7.0 = 41 57 Store temperatures in Kelvin rather than degrees Celsius. Update `masterminds/html5` to version 2.8.0. Add Location block. 58 42 59 = 0.6.0 = 43 60 "Facepile" likes, bookmarks, and reposts. 61 44 62 = 0.5.0 = 45 63 Add Bookmark, Like, Reply and Repost blocks. Additional title options. 64 46 65 = 0.4.0 = 47 66 Add `indieblocks/syndication-links` block. 67 48 68 = 0.3.6 = 49 69 Minor bug fix, new plugin URL. 70 50 71 = 0.3.5 = 51 72 Fix rescheduling of webmentions from the classic editor. 73 52 74 = 0.3.4 = 53 75 Webmention tweaks. 54 76 = 0.3.3 = 55 77 Slight block changes. Bug fixes, and basic Webmention support. 78 56 79 = 0.2.0 = 57 80 Slightly improved "empty" URL handling, and permalink flushing. Additional CPT, feed and Micropub options. Date-based CPT archives, and basic location functions. 81 58 82 = 0.1.0 = 59 83 Very first version. -
indieblocks/trunk/blocks/facepile/block.json
r2961482 r3002715 29 29 "fontSize": true 30 30 } 31 }, 32 "spacing": { 33 "margin": ["top", "bottom"], 34 "padding": false, 35 "blockGap": false 31 36 } 32 37 } -
indieblocks/trunk/blocks/link-preview/class-link-preview-block.php
r2993569 r3002715 68 68 69 69 if ( ! empty( $card['thumbnail'] ) ) : 70 // Check if file still exists. 71 $upload_dir = wp_upload_dir(); 72 $file_path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $card['thumbnail'] ); 73 74 if ( is_file( $file_path ) ) : 75 ?> 76 <img src="<?php echo esc_url_raw( $card['thumbnail'] ); ?>" width="90" height="90" alt=""> 77 <?php 78 endif; 70 ?> 71 <img src="<?php echo esc_url_raw( $card['thumbnail'] ); ?>" width="90" height="90" alt=""> 72 <?php 79 73 endif; 80 74 -
indieblocks/trunk/includes/class-parser.php
r2993569 r3002715 84 84 85 85 if ( empty( $mf2 ) ) { 86 $fragment = wp_parse_url( $this->url, PHP_URL_FRAGMENT ); 87 if ( ! empty( $fragment ) ) { 88 // If the URL contains a fragment, parse only the corresponding 89 // page section. 90 // @todo: Do this for `$this->dom`, too? 91 $xpath = new \DOMXPath( $this->dom ); 92 93 foreach ( $xpath->query( "//*[@id='$fragment']" ) as $el ) { 94 $content = $this->dom->saveHTML( $el ); 95 break; 96 } 97 } 98 86 99 $mf2 = Mf2\parse( $content, $this->url ); 87 100 set_transient( 'indieblocks:mf2:' . $hash, $mf2, 3600 ); 88 101 } 89 102 90 $this->mf2 = Mf2\parse( $content, $this->url );103 $this->mf2 = $mf2; 91 104 } 92 105 … … 297 310 if ( ! empty( $this->mf2['items'][0]['properties']['content'][0]['html'] ) ) { 298 311 return $this->mf2['items'][0]['properties']['content'][0]['html']; 312 } elseif ( ! empty( $this->mf2['items'][0]['properties']['content'][0]['text'] ) ) { 313 return $this->mf2['items'][0]['properties']['content'][0]['text']; 314 } elseif ( ! empty( $this->mf2['items'][0]['properties']['content'][0] && is_string( $this->mf2['items'][0]['properties']['content'][0] ) ) ) { 315 return $this->mf2['items'][0]['properties']['content'][0]; 299 316 } 300 317 -
indieblocks/trunk/includes/class-plugin.php
r2993569 r3002715 12 12 * Plugin version. 13 13 */ 14 const PLUGIN_VERSION = '0. 9.1';14 const PLUGIN_VERSION = '0.10.0'; 15 15 16 16 /** -
indieblocks/trunk/includes/class-theme-mf2.php
r2993569 r3002715 178 178 $processor->add_class( 'h-card u-author' ); 179 179 180 if ( ! empty( $instance->attributes['avatarSize'] ) ) {180 if ( ! empty( $instance->attributes['avatarSize'] ) && ! empty( $instance->attributes['showAvatar'] ) ) { 181 181 $processor->next_tag( 'img' ); 182 182 $processor->add_class( 'u-photo' ); … … 481 481 } 482 482 483 $upload_dir = wp_upload_dir();484 $file_path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $url );485 486 if ( ! is_file( $file_path ) ) {487 return null;488 }489 490 483 $width = (int) ( ! empty( $args['width'] ) ? $args['width'] : 96 ); 491 484 $height = (int) ( ! empty( $args['height'] ) ? $args['height'] : 96 ); -
indieblocks/trunk/includes/class-webmention-parser.php
r2961482 r3002715 63 63 if ( ! empty( $published ) ) { 64 64 $commentdata['comment_date'] = get_date_from_gmt( $published, 'Y-m-d H:i:s' ); 65 $commentdata['comment_date_gmt'] = date( 'Y-m-d H:i:s', strtotime( $published ) ); 66 } 67 68 $commentdata['comment_meta']['indieblocks_webmention_source'] = esc_url_raw( $parser->get_url() ?: $source ); // phpcs:ignore WordPress.PHP.DisallowShortTernary.Found65 $commentdata['comment_date_gmt'] = date( 'Y-m-d H:i:s', strtotime( $published ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date 66 } 67 68 $commentdata['comment_meta']['indieblocks_webmention_source'] = esc_url_raw( $parser->get_url() ?: $source ); // phpcs:ignore Universal.Operators.DisallowShortTernary.Found 69 69 70 70 $hentry_kind = $parser->get_type(); -
indieblocks/trunk/includes/class-webmention-receiver.php
r2993569 r3002715 103 103 104 104 $table_name = $wpdb->prefix . 'indieblocks_webmentions'; 105 $webmentions = $wpdb->get_results( "SELECT id, source, post_id, ip, created_at FROM $table_name WHERE status = 'draft' LIMIT 5" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared105 $webmentions = $wpdb->get_results( "SELECT id, source, target, post_id, ip, created_at FROM $table_name WHERE status = 'draft' LIMIT 5" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared 106 106 107 107 if ( empty( $webmentions ) || ! is_array( $webmentions ) ) { … … 131 131 'key' => 'indieblocks_webmention_source', 132 132 'compare' => '=', 133 'value' => esc_url( $webmention->source ), 133 'value' => esc_url_raw( $webmention->source ), 134 ), 135 array( 136 'key' => 'indieblocks_webmention_target', 137 'compare' => 'EXISTS', 138 ), 139 array( 140 'key' => 'indieblocks_webmention_target', 141 'compare' => '=', 142 'value' => esc_url_raw( $webmention->target ), 134 143 ), 135 144 ), … … 205 214 $host = wp_parse_url( $webmention->source, PHP_URL_HOST ); 206 215 216 // Look for a target URL fragment (and possible parent comment). 217 $fragment = wp_parse_url( $webmention->target, PHP_URL_FRAGMENT ); 218 if ( ! empty( $fragment ) && preg_match( '~^comment-\d+$~', $fragment ) ) { 219 $parent = get_comment( str_replace( 'comment-', '', str_replace( 'comment-', '', $fragment ) ) ); 220 } 221 207 222 // Some defaults. 208 223 $commentdata = array( … … 213 228 'comment_author_IP' => $webmention->ip, 214 229 'comment_content' => __( '… commented on this.', 'indieblocks' ), 215 'comment_parent' => 0,230 'comment_parent' => ! empty( $parent ) && $webmention->post_id === $parent->comment_post_ID ? $parent->comment_ID : 0, 216 231 'user_id' => 0, 217 232 'comment_date' => $webmention->created_at, … … 220 235 'comment_meta' => array( 221 236 'indieblocks_webmention_source' => esc_url_raw( $webmention->source ), 237 'indieblocks_webmention_target' => esc_url_raw( $webmention->target ), 222 238 ), 223 239 ); … … 371 387 372 388 // Delete file. 373 if ( is_file( $file_path ) ) { 374 wp_delete_file( $file_path ); 375 } 376 377 // Delete reference in database. 378 delete_comment_meta( $comment_id, 'indieblocks_webmention_avatar' ); 389 wp_delete_file( $file_path ); 390 391 // Delete _all_ references to this file (i.e., not just this 392 // comment's meta field). 393 global $wpdb; 394 395 $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 396 $wpdb->prepare( 397 "DELETE FROM $wpdb->commentmeta WHERE meta_key = %s AND meta_value = %s", 398 'indieblocks_webmention_avatar', 399 esc_url_raw( $url ) 400 ) 401 ); 379 402 } 380 403 -
indieblocks/trunk/includes/class-webmention-sender.php
r2993569 r3002715 18 18 * callback function queued in the background. 19 19 * 20 * @param string $new_status New post status. 21 * @param string $old_status Old post status. 22 * @param WP_Post $post Post object. 23 */ 24 public static function schedule_webmention( $new_status, $old_status, $post ) { 25 if ( wp_is_post_revision( $post->ID ) || wp_is_post_autosave( $post->ID ) ) { 26 return; 27 } 28 29 /* @see https://github.com/WordPress/gutenberg/issues/15094#issuecomment-1021288811. */ 30 if ( ! empty( $_REQUEST['meta-box-loader'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 31 // Avoid scheduling (or posting, in case of no delay) webmentions 32 // more than once. 33 return; 20 * @param int $obj_id Post or comment ID. 21 * @param \WP_Post|\WP_Comment $obj Post or comment object. 22 * @param mixed $deprecated Used to be the post object, now deprecated. 23 */ 24 public static function schedule_webmention( $obj_id, $obj = null, $deprecated = null ) { 25 if ( null !== $deprecated ) { 26 _deprecated_argument( 'post', '0.10.0', 'Passing a third argument to `\IndieBlocks\Webmention_Sender::schedule_webmention()` is deprecated.' ); 34 27 } 35 28 … … 39 32 } 40 33 41 if ( 'publish' !== $new_status ) { 34 if ( 'comment_post' === current_filter() ) { 35 $obj = get_comment( $obj_id ); 36 } 37 38 if ( $obj instanceof \WP_Post ) { 39 if ( 'publish' !== $obj->post_status ) { 40 // Do not send webmention on delete/unpublish, for now. 41 return; 42 } 43 44 /* @see https://github.com/WordPress/gutenberg/issues/15094#issuecomment-1021288811. */ 45 if ( ! empty( $_REQUEST['meta-box-loader'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 46 // Avoid scheduling (or posting, in case of no delay) webmentions 47 // more than once. 48 return; 49 } 50 51 if ( wp_is_post_revision( $obj->ID ) || wp_is_post_autosave( $obj->ID ) ) { 52 return; 53 } 54 55 if ( ! in_array( $obj->post_type, Webmention::get_supported_post_types(), true ) ) { 56 return; 57 } 58 } elseif ( '1' !== $obj->comment_approved ) { 42 59 // Do not send webmention on delete/unpublish, for now. 43 60 return; 44 61 } 45 62 46 if ( ! in_array( $post->post_type, Webmention::get_supported_post_types(), true ) ) { 47 return; 48 } 49 50 // Fetch our post's HTML. 51 $html = apply_filters( 'the_content', $post->post_content ); 52 53 // Scan it for outgoing links. 54 $urls = static::find_outgoing_links( $html ); 55 56 // Parse in targets that may have been there previously, but don't delete 57 // them, yet. 58 $history = get_post_meta( $post->ID, '_indieblocks_webmention_history', true ); 63 $urls = array(); 64 65 if ( $obj instanceof \WP_Post ) { 66 // Fetch our post's HTML. 67 $html = apply_filters( 'the_content', $obj->post_content ); 68 69 // Scan it for outgoing links. 70 $urls = static::find_outgoing_links( $html ); 71 } elseif ( ! empty( $obj->comment_parent ) ) { 72 // Add in the parent's, if any, Webmention source. 73 $source = get_comment_meta( $obj->comment_parent, 'indieblocks_webmention_source', true ); 74 if ( ! empty( $source ) ) { 75 $urls[] = $source; 76 } 77 } 78 79 // Parse in targets that may have been there previously, but don't 80 // delete them, yet. 81 $history = get_meta( $obj, '_indieblocks_webmention_history' ); 82 59 83 if ( ! empty( $history ) && is_array( $history ) ) { 60 $urls = array_ unique( array_merge( $urls, $history ));61 } 62 63 if ( empty( $urls ) || ! is_array( $urls )) {84 $urls = array_merge( $urls, $history ); 85 } 86 87 if ( empty( $urls ) ) { 64 88 // Nothing to do. Bail. 65 89 return; 66 90 } 67 91 92 $urls = array_unique( $urls ); 68 93 $schedule = false; 69 94 … … 91 116 92 117 // Schedule sending out the actual webmentions. 93 error_log( "[Indieblocks/Webmention] Scheduling webmention for post {$post->ID}." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 94 wp_schedule_single_event( time() + $delay, 'indieblocks_webmention_send', array( $post->ID ) ); 95 96 add_post_meta( $post->ID, '_indieblocks_webmention', 'scheduled', true ); // Does not affect existing values. 118 if ( $obj instanceof \WP_Post ) { 119 error_log( "[Indieblocks/Webmention] Scheduling webmention for post {$obj->ID}." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 120 } else { 121 error_log( "[Indieblocks/Webmention] Scheduling webmention for comment {$obj->comment_ID}." ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 122 } 123 124 add_meta( $obj, '_indieblocks_webmention', 'scheduled' ); 125 wp_schedule_single_event( time() + $delay, 'indieblocks_webmention_send', array( $obj ) ); 97 126 } else { 98 127 // Send inline (although retries will be scheduled as always). 99 static::send_webmention( $ post->ID);128 static::send_webmention( $obj ); 100 129 } 101 130 } … … 106 135 * a post. 107 136 * 108 * @param int $post_id Post ID. 109 */ 110 public static function send_webmention( $post_id ) { 111 $post = get_post( $post_id ); 112 113 if ( 'publish' !== $post->post_status ) { 114 // Do not send webmentions on delete/unpublish, for now. 115 return; 116 } 117 118 if ( ! in_array( $post->post_type, Webmention::get_supported_post_types(), true ) ) { 119 // This post type doesn't support Webmention. 120 return; 121 } 122 123 // Fetch our post's HTML. 124 $html = apply_filters( 'the_content', $post->post_content ); 125 126 // Scan it for outgoing links, again, as things might have changed. 127 $urls = static::find_outgoing_links( $html ); 128 129 // Parse in (and then forget) targets that may have been there before. 137 * @param \WP_Post|\WP_Comment $obj Post or comment object. 138 */ 139 public static function send_webmention( $obj ) { 140 if ( $obj instanceof \WP_Post ) { 141 if ( 'publish' !== $obj->post_status ) { 142 // Do not send webmention on delete/unpublish, for now. 143 return; 144 } 145 146 if ( ! in_array( $obj->post_type, Webmention::get_supported_post_types(), true ) ) { 147 // This post type doesn't support Webmention. 148 return; 149 } 150 } elseif ( '1' !== $obj->comment_approved ) { 151 return; 152 } 153 154 $urls = array(); 155 156 if ( $obj instanceof \WP_Post ) { 157 // Fetch our post's HTML. 158 $html = apply_filters( 'the_content', $obj->post_content ); 159 160 // Scan it for outgoing links. 161 $urls = static::find_outgoing_links( $html ); 162 } elseif ( ! empty( $obj->comment_parent ) ) { 163 // Add in the parent's, if any, Webmention source. 164 $source = get_comment_meta( $obj->comment_parent, 'indieblocks_webmention_source', true ); 165 if ( ! empty( $source ) ) { 166 $urls[] = $source; 167 } 168 } 169 170 // Parse in (_and_ then forget) targets that may have been there before. 130 171 // This also means that "historic" targets are excluded from retries! 131 172 // Note that we _also_ retarget pages that threw an error or we 132 173 // otherwise failed to reach previously. Both are probably acceptable. 133 $history = get_post_meta( $post->ID, '_indieblocks_webmention_history', true ); 134 delete_post_meta( $post->ID, '_indieblocks_webmention_history' ); 174 $history = get_meta( $obj, '_indieblocks_webmention_history' ); 175 delete_meta( $obj, '_indieblocks_webmention_history' ); 176 135 177 if ( ! empty( $history ) && is_array( $history ) ) { 136 $urls = array_ unique( array_merge( $urls, $history ));137 } 138 139 if ( empty( $urls ) || ! is_array( $urls )) {178 $urls = array_merge( $urls, $history ); 179 } 180 181 if ( empty( $urls ) ) { 140 182 // One or more links must've been removed. Nothing to do. Bail. 141 183 return; 142 184 } 143 185 186 $urls = array_unique( $urls ); 187 144 188 // Fetch whatever Webmention-related stats we've got for this post. 145 $webmention = get_ post_meta( $post->ID, '_indieblocks_webmention', true);189 $webmention = get_meta( $obj, '_indieblocks_webmention' ); 146 190 147 191 if ( empty( $webmention ) || ! is_array( $webmention ) ) { … … 157 201 if ( empty( $endpoint ) || false === wp_http_validate_url( $endpoint ) ) { 158 202 // Skip. 203 error_log( '[Indieblocks/Webmention] Could not find a Webmention endpoint for target ' . esc_url_raw( $url ) . '.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 159 204 continue; 160 205 } … … 190 235 array( 191 236 'body' => array( 192 'source' => get_permalink( $post->ID ),237 'source' => $obj instanceof \WP_Post ? get_permalink( $obj->ID ) : get_comment_link( $obj->comment_ID ), 193 238 'target' => $url, 194 239 ), … … 196 241 ); 197 242 198 if ( is_wp_error( $response ) ) {243 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) >= 500 ) { 199 244 // Something went wrong. 200 245 error_log( '[Indieblocks/Webmention] Error trying to send a webmention to ' . esc_url_raw( $endpoint ) . ': ' . $response->get_error_message() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 246 error_log( print_r( $response, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r 201 247 202 248 $webmention[ $hash ]['retries'] = $retries + 1; 203 update_post_meta( $post->ID, '_indieblocks_webmention', $webmention ); 249 250 update_meta( $obj, '_indieblocks_webmention', $webmention ); 204 251 205 252 // Schedule a retry in 5 to 15 minutes. 206 wp_schedule_single_event( time() + wp_rand( 300, 900 ), 'indieblocks_webmention_send', array( $post->ID ) ); 207 208 continue; 209 } elseif ( wp_remote_retrieve_response_code( $response ) >= 500 ) { 210 // Something went wrong. 211 error_log( '[Indieblocks/Webmention] Error trying to send a webmention to ' . esc_url_raw( $endpoint ) . '.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 212 error_log( print_r( $response, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r 213 214 $webmention[ $hash ]['retries'] = $retries + 1; 215 update_post_meta( $post->ID, '_indieblocks_webmention', $webmention ); 216 217 // Schedule a retry in 5 to 15 minutes. 218 wp_schedule_single_event( time() + wp_rand( 300, 900 ), 'indieblocks_webmention_send', array( $post->ID ) ); 253 wp_schedule_single_event( time() + wp_rand( 300, 900 ), 'indieblocks_webmention_send', array( $obj ) ); 219 254 220 255 continue; … … 228 263 } 229 264 230 update_ post_meta( $post->ID, '_indieblocks_webmention', $webmention );265 update_meta( $obj, '_indieblocks_webmention', $webmention ); 231 266 } 232 267 … … 463 498 464 499 $post = get_post( $post_id ); 465 static::schedule_webmention( $post ->post_status, $post->post_status, $post );500 static::schedule_webmention( $post_id, $post ); 466 501 467 502 wp_die(); -
indieblocks/trunk/includes/class-webmention.php
r2993569 r3002715 24 24 25 25 add_action( 'add_meta_boxes', array( Webmention_Sender::class, 'add_meta_box' ) ); 26 add_action( 'transition_post_status', array( Webmention_Sender::class, 'schedule_webmention' ), 10, 3 ); 26 27 foreach ( static::get_supported_post_types() as $post_type ) { 28 add_action( "publish_{$post_type}", array( Webmention_Sender::class, 'schedule_webmention' ), 10, 2 ); 29 } 30 31 // When a comment is first inserted into the database. 32 add_action( 'comment_post', array( Webmention_Sender::class, 'schedule_webmention' ) ); // Pass only one argument (the comment ID) to `Webmention_Sender::schedule_webmention()`! 33 // When a comment is approved. Or a previously approved comment updated. 34 add_action( 'comment_approved_comment', array( Webmention_Sender::class, 'schedule_webmention' ), 10, 2 ); 35 27 36 add_action( 'indieblocks_webmention_send', array( Webmention_Sender::class, 'send_webmention' ) ); 28 37 -
indieblocks/trunk/includes/functions.php
r2993569 r3002715 39 39 */ 40 40 function debug_log( $item ) { 41 error_log( print_r( $item, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r41 error_log( is_string( $item ) ? $item : print_r( $item, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r 42 42 } 43 43 … … 283 283 } 284 284 } else { 285 debug_log( '[IndieBlocks] Could not re isize ' . $file_path . ': ' . $image->get_error_message() . '.' );285 debug_log( '[IndieBlocks] Could not resize ' . $file_path . ': ' . $image->get_error_message() . '.' ); 286 286 } 287 287 … … 376 376 return $facepile_comments; 377 377 } 378 379 /** 380 * Get post or comment meta. 381 * 382 * @param \WP_Post|\WP_Comment $obj Post or comment. 383 * @param string $meta_key The meta key. 384 * @return string The meta value (or an empty) string. 385 */ 386 function get_meta( $obj, $meta_key ) { 387 if ( $obj instanceof \WP_Post ) { 388 return get_post_meta( $obj->ID, $meta_key, true ); 389 } 390 391 if ( $obj instanceof \WP_Comment ) { 392 return get_comment_meta( $obj->comment_ID, $meta_key, true ); 393 } 394 395 return ''; 396 } 397 398 /** 399 * Update post or comment meta. 400 * 401 * @param \WP_Post|\WP_Comment $obj Post or comment. 402 * @param string $meta_key The meta key. 403 * @param mixed $meta_value The value. 404 */ 405 function add_meta( $obj, $meta_key, $meta_value ) { 406 if ( $obj instanceof \WP_Post ) { 407 add_post_meta( $obj->ID, $meta_key, $meta_value ); 408 } 409 410 if ( $obj instanceof \WP_Comment ) { 411 add_comment_meta( $obj->comment_ID, $meta_key, $meta_value ); 412 } 413 } 414 415 /** 416 * Update post or comment meta. 417 * 418 * @param \WP_Post|\WP_Comment $obj Post or comment. 419 * @param string $meta_key The meta key. 420 * @param mixed $meta_value The value. 421 */ 422 function update_meta( $obj, $meta_key, $meta_value ) { 423 if ( $obj instanceof \WP_Post ) { 424 update_post_meta( $obj->ID, $meta_key, $meta_value ); 425 } 426 427 if ( $obj instanceof \WP_Comment ) { 428 update_comment_meta( $obj->comment_ID, $meta_key, $meta_value ); 429 } 430 } 431 432 /** 433 * Delete post or comment meta. 434 * 435 * @param \WP_Post|\WP_Comment $obj Post or comment. 436 * @param string $meta_key The meta key. 437 */ 438 function delete_meta( $obj, $meta_key ) { 439 if ( $obj instanceof \WP_Post ) { 440 delete_post_meta( $obj->ID, $meta_key ); 441 } 442 443 if ( $obj instanceof \WP_Comment ) { 444 delete_comment_meta( $obj->comment_ID, $meta_key ); 445 } 446 } -
indieblocks/trunk/indieblocks.php
r2993569 r3002715 9 9 * License URI: http://www.gnu.org/licenses/gpl-3.0.html 10 10 * Text Domain: indieblocks 11 * Version: 0. 9.111 * Version: 0.10.0 12 12 * Requires at least: 6.2 13 13 * GitHub Plugin URI: https://github.com/janboddez/indieblocks -
indieblocks/trunk/languages/indieblocks.pot
r2993569 r3002715 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: IndieBlocks 0. 9.1\n"5 "Project-Id-Version: IndieBlocks 0.10.0\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/indieblocks\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2023-11- 08T20:41:32+00:00\n"12 "POT-Creation-Date: 2023-11-26T22:12:55+01:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 "X-Generator: WP-CLI 2. 6.0\n"14 "X-Generator: WP-CLI 2.9.0\n" 15 15 "X-Domain: indieblocks\n" 16 16 … … 165 165 #: includes/class-options-handler.php:376 166 166 #: includes/class-options-handler.php:479 167 #: includes/class-webmention-receiver.php: 288168 #: includes/class-webmention-sender.php: 372167 #: includes/class-webmention-receiver.php:304 168 #: includes/class-webmention-sender.php:416 169 169 msgid "Webmention" 170 170 msgstr "" … … 548 548 msgstr "" 549 549 550 #: includes/class-webmention-receiver.php:2 14550 #: includes/class-webmention-receiver.php:229 551 551 msgid "… commented on this." 552 552 msgstr "" 553 553 554 #: includes/class-webmention-receiver.php:3 07554 #: includes/class-webmention-receiver.php:323 555 555 msgid "Source" 556 556 msgstr "" 557 557 558 #: includes/class-webmention-receiver.php:3 10558 #: includes/class-webmention-receiver.php:326 559 559 #: blocks/context/block.js:67 560 560 msgid "Type" 561 561 msgstr "" 562 562 563 #: includes/class-webmention-receiver.php:3 14563 #: includes/class-webmention-receiver.php:330 564 564 msgid "Avatar" 565 565 msgstr "" 566 566 567 #: includes/class-webmention-receiver.php:3 18567 #: includes/class-webmention-receiver.php:334 568 568 msgid "Delete" 569 569 msgstr "" 570 570 571 #: includes/class-webmention-receiver.php:3 48572 #: includes/class-webmention-sender.php:4 39571 #: includes/class-webmention-receiver.php:364 572 #: includes/class-webmention-sender.php:483 573 573 msgid "Missing or invalid nonce." 574 574 msgstr "" 575 575 576 #: includes/class-webmention-receiver.php:3 54576 #: includes/class-webmention-receiver.php:370 577 577 msgid "Invalid comment ID." 578 578 msgstr "" 579 579 580 #: includes/class-webmention-receiver.php:3 62581 #: includes/class-webmention-sender.php:4 53580 #: includes/class-webmention-receiver.php:378 581 #: includes/class-webmention-sender.php:497 582 582 msgid "Insufficient rights." 583 583 msgstr "" 584 584 585 585 #. translators: 1: Webmention endpoint 2: Date sent 586 #: includes/class-webmention-sender.php:4 04586 #: includes/class-webmention-sender.php:448 587 587 msgid "Sent to %1$s on %2$s. Response code: %3$d." 588 588 msgstr "" 589 589 590 590 #. translators: 1: Webmention endpoint 2: Date sent 591 #: includes/class-webmention-sender.php:4 04591 #: includes/class-webmention-sender.php:448 592 592 msgid "M j, Y \\a\\t H:i" 593 593 msgstr "" 594 594 595 595 #. translators: Webmention endpoint 596 #: includes/class-webmention-sender.php:4 07596 #: includes/class-webmention-sender.php:451 597 597 msgid "Could not send webmention to %s." 598 598 msgstr "" 599 599 600 600 #. translators: Webmention endpoint 601 #: includes/class-webmention-sender.php:4 10601 #: includes/class-webmention-sender.php:454 602 602 msgid "Could not send webmention to %s. Trying again soon." 603 603 msgstr "" 604 604 605 #: includes/class-webmention-sender.php:4 20605 #: includes/class-webmention-sender.php:464 606 606 msgid "Resend" 607 607 msgstr "" 608 608 609 #: includes/class-webmention-sender.php:4 24610 #: includes/class-webmention.php:1 43609 #: includes/class-webmention-sender.php:468 610 #: includes/class-webmention.php:152 611 611 msgid "Webmention scheduled." 612 612 msgstr "" 613 613 614 #: includes/class-webmention-sender.php:4 26614 #: includes/class-webmention-sender.php:470 615 615 msgid "No endpoints found." 616 616 msgstr "" 617 617 618 #: includes/class-webmention-sender.php:4 45618 #: includes/class-webmention-sender.php:489 619 619 msgid "Invalid post ID." 620 620 msgstr "" -
indieblocks/trunk/readme.txt
r2993569 r3002715 3 3 Tags: blocks, gutenberg, indieweb, notes, likes, microblog, microblogging, micropub, fse, site editor, webmention, syndication 4 4 Tested up to: 6.4 5 Stable tag: 0. 9.15 Stable tag: 0.10.0 6 6 License: GNU General Public License v3.0 7 7 License URI: https://www.gnu.org/licenses/gpl-3.0.html … … 10 10 11 11 == Description == 12 Use blocks, and, optionally, "short-form" post types to easily "IndieWebify" your WordPress site. 13 12 14 IndieBlocks registers several blocks (Bookmark, Like, Reply, and Repost, as well as the older Context block) that take a URL and output corresponding _microformatted_ HTML. 13 15 … … 18 20 These microformats, in combination with the Webmention protocol, allow for rich _cross-site_ conversations. IndieBlocks comes with its own Webmention implementation, but a separate plugin can be used, too. 19 21 20 IndieBlocks also registers several "theme" blocks (Facepile, Location, Syndication, and Link Preview), to be used in (block) themetemplates.22 IndieBlocks also registers several "theme" blocks (Facepile, Location, Syndication, and Link Preview), to be used in "block theme" templates. 21 23 22 24 == Installation == … … 27 29 More details can be found on [https://indieblocks.xyz/](https://indieblocks.xyz/). Issues may be filed at [https://github.com/janboddez/indieblocks](https://github.com/janboddez/indieblocks). 28 30 31 == Frequently Asked Questions == 32 = How does this plugin interact with the various other IndieWeb plugins? = 33 While IndieBlocks does not depend on _any_ other plugin, it is compatible with, and extends, the Micropub plugin for WordPress. See [https://indieblocks.xyz/documentation/micropub-and-indieauth/](https://indieblocks.xyz/documentation/micropub-and-indieauth/) for some more information. 34 35 IndieBlocks’ Facepile and Syndication blocks also aim to be compatible with, respectively, the Webmention and Syndication Links plugins. 36 29 37 == Changelog == 38 = 0.10.0 = 39 Send webmentions also for comments, to mentioned sites and the comment parent, if it exists and itself originated as a webmention. 40 30 41 = 0.9.1 = 31 42 Fix Webmention backlinks in Facepile block, add avatar background and icon color pickers. 43 32 44 = 0.9.0 = 33 45 Overhaul theme microformats functionality. 46 34 47 = 0.8.1 = 35 48 Fix issue with saving meta from block editor. Fix Markdown in Micropub notes. 49 36 50 = 0.8.0 = 37 51 Various bug fixes. Add Link Preview block. Also, webmentions are now closed when comments are, although this behavior is filterable. 52 38 53 = 0.7.1 = 39 54 Add Location block. The Facepile block now supports v5.0 and up of the Webmention plugin. 55 40 56 = 0.7.0 = 41 57 Store temperatures in Kelvin rather than degrees Celsius. Update `masterminds/html5` to version 2.8.0. Add Location block. 58 42 59 = 0.6.0 = 43 60 "Facepile" likes, bookmarks, and reposts. 61 44 62 = 0.5.0 = 45 63 Add Bookmark, Like, Reply and Repost blocks. Additional title options. 64 46 65 = 0.4.0 = 47 66 Add `indieblocks/syndication-links` block. 67 48 68 = 0.3.6 = 49 69 Minor bug fix, new plugin URL. 70 50 71 = 0.3.5 = 51 72 Fix rescheduling of webmentions from the classic editor. 73 52 74 = 0.3.4 = 53 75 Webmention tweaks. 54 76 = 0.3.3 = 55 77 Slight block changes. Bug fixes, and basic Webmention support. 78 56 79 = 0.2.0 = 57 80 Slightly improved "empty" URL handling, and permalink flushing. Additional CPT, feed and Micropub options. Date-based CPT archives, and basic location functions. 81 58 82 = 0.1.0 = 59 83 Very first version.
Note: See TracChangeset
for help on using the changeset viewer.