├── LICENSE ├── build ├── index.asset.php └── index.js ├── hum.php └── readme.md /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Google and contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /build/index.asset.php: -------------------------------------------------------------------------------- 1 | array('react-jsx-runtime', 'wp-components', 'wp-editor', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '616645f563721e226fea'); 2 | -------------------------------------------------------------------------------- /build/index.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";const n=window.wp.plugins,e=window.wp.editor,i=window.wp.components,t=window.wp.element,o=window.wp.i18n,l=window.ReactJSXRuntime;(0,n.registerPlugin)("hum-gutenberg-shortlink-panel",{render:()=>{const{shortlink:n}=window._humEditorObject,[r,s]=(0,t.useState)(!1);return(0,l.jsxs)(e.PluginDocumentSettingPanel,{name:"shortlink-panel",title:"Shortlink",className:"shortlink-panel",children:[(0,l.jsx)(i.TextControl,{label:(0,o.__)("Shortlink","hum"),hideLabelFromVision:"true",value:n,disabled:!0}),(0,l.jsx)(i.ClipboardButton,{isPrimary:!0,text:n,onCopy:()=>s(!0),onFinishCopy:()=>s(!1),children:r?(0,o.__)("Copied!","hum"):(0,o.__)("Copy link","hum")})]})}})})(); -------------------------------------------------------------------------------- /hum.php: -------------------------------------------------------------------------------- 1 | wp_get_shortlink(), 75 | ) 76 | ); 77 | } 78 | 79 | /** 80 | * Accept hum query variables. 81 | */ 82 | public function query_vars( $vars ) { 83 | $vars[] = 'hum'; 84 | return $vars; 85 | } 86 | 87 | /** 88 | * Parse request for shortlink. This is the main entry point for handling 89 | * short URLs. 90 | * 91 | * @uses apply_filters() Calls 'hum_redirect' filter 92 | * @uses apply_filters() Calls 'hum_process_redirect' filter 93 | * 94 | * @param WP $wp the WordPress environment for the request 95 | */ 96 | public function parse_request( $wp ) { 97 | if ( array_key_exists( 'hum', $wp->query_vars ) ) { 98 | $hum_path = $wp->query_vars['hum']; 99 | if ( strpos( $hum_path, '/' ) !== false ) { 100 | list($type, $id) = explode( '/', $hum_path, 2 ); 101 | } else { 102 | $type = $hum_path; 103 | $id = null; 104 | } 105 | 106 | $url = apply_filters( 'hum_redirect', null, $type, $id ); 107 | 108 | // hum hasn't handled the request yet, so try again but strip common 109 | // punctuation that might appear after a URL in written text: . , ) 110 | if ( ! $url ) { 111 | $clean_id = preg_replace( '/[\.,\)]+$/', '', $id ); 112 | if ( $id !== $clean_id ) { 113 | $url = apply_filters( 'hum_redirect', null, $type, $clean_id ); 114 | } 115 | } 116 | 117 | if ( $url ) { 118 | do_action( 'hum_process_redirect', $url, $id ); 119 | } 120 | 121 | // hum didn't handle request, so issue 404. 122 | // manually setting query vars like this feels very fragile, but 123 | // $wp_query->set_404() doesn't do what we need here. 124 | $wp->query_vars['error'] = '404'; 125 | } 126 | } 127 | 128 | /** 129 | * Process the redirect. 130 | * 131 | * @param string $url the permalink of the post 132 | * @param string $id the requested post ID 133 | */ 134 | public function process_redirect( $url, $id ) { 135 | wp_redirect( $url, 301 ); 136 | exit; 137 | } 138 | 139 | /** 140 | * Get the short URL types that are handled locally by WordPress. 141 | * 142 | * @uses apply_filters() Calls 'hum_local_types' with array of local types 143 | * 144 | * @return array local types 145 | */ 146 | public function local_types() { 147 | $local_types = array( 'b', 't', 'a', 'p' ); 148 | return apply_filters( 'hum_local_types', $local_types ); 149 | } 150 | 151 | /** 152 | * Get the short URL types that shoud be redirected (types can be the same as local types). 153 | * 154 | * @uses apply_filters() Calls 'hum_redirect_types' with array of redirect types 155 | * 156 | * @return array redirect types 157 | */ 158 | public function redirect_types() { 159 | $redirect_types = array( 'i' ); 160 | return apply_filters( 'hum_redirect_types', $redirect_types ); 161 | } 162 | 163 | /** 164 | * Attempt to handle redirect for the current shortlink. 165 | * 166 | * This redirects shortlinks that are for content hosted directly within 167 | * WordPress. The 'id' portion of these URLs is expected to be the 168 | * sexagesimal post ID. 169 | * 170 | * This also allows for simple redirect rules for shortlink prefixes. Users 171 | * can provide a filter to perform simple URL redirect for a given type 172 | * prefix. For example, to redirect all /w/ shortlinks to your personal 173 | * PBworks wiki, you could use: 174 | * 175 | * add_filter('hum_redirect_base_w', fn() => "http://willnorris.pbworks.com/"); 176 | * 177 | * @uses apply_filters() Calls 'hum_redirect_{$type}' action 178 | * @uses apply_filters() Calls 'hum_redirect_base_{$type}' filter on redirect base URL 179 | * 180 | * @param string $url the short URL 181 | * @param string $type the content-type prefix 182 | * @param string $id the requested post ID 183 | */ 184 | public function redirect_request( $url, $type, $id ) { 185 | // locally hosted content 186 | $local_types = $this->local_types(); 187 | if ( in_array( $type, $local_types, true ) ) { 188 | $p = sxg_to_num( $id ); 189 | if ( $p ) { 190 | $url = get_permalink( $p ); 191 | } 192 | } 193 | 194 | // simple redirects for entire base type 195 | if ( ! $url ) { 196 | $url = apply_filters( "hum_redirect_base_{$type}", false ); 197 | if ( $url ) { 198 | $url = trailingslashit( $url ) . $id; 199 | } 200 | } 201 | 202 | $url = apply_filters( "hum_redirect_{$type}", $url, $id ); 203 | return $url; 204 | } 205 | 206 | /** 207 | * Handles /i/ URLs that have ISBN or ASIN subpaths by redirecting to Amazon. 208 | * 209 | * @uses apply_filters() Calls 'hum_redirect_i_{$subtype}' action 210 | * @uses apply_filters() Calls 'amazon_domain' filter 211 | * @uses apply_filters() Calls 'amazon_affiliate_id' filter 212 | * 213 | * @param string $url the short URL 214 | * @param string $path subpath of URL (after /i/) 215 | */ 216 | public function redirect_request_i( $url, $path ) { 217 | list( $subtype, $id ) = explode( '/', $path, 2 ); 218 | 219 | if ( $subtype ) { 220 | switch ( $subtype ) { 221 | case 'a': 222 | case 'asin': 223 | case 'i': 224 | case 'isbn': 225 | $amazon_domain = apply_filters( 'amazon_domain', 'www.amazon.com' ); 226 | $amazon_id = apply_filters( 'amazon_affiliate_id', false ); 227 | if ( $amazon_id ) { 228 | // valid partner shortlink, checked by 229 | // https://partnernet.amazon.de/gp/associates/network/tools/link-checker/main.html 230 | $url = 'http://' . $amazon_domain . '/dp/product/' . $id . '?tag=' . $amazon_id; 231 | } else { 232 | $url = 'http://' . $amazon_domain . '/dp/product/' . $id; 233 | } 234 | break; 235 | } 236 | $url = apply_filters( "hum_redirect_i_{$subtype}", $url, $id ); 237 | } 238 | return $url; 239 | } 240 | 241 | /** 242 | * Add rewrite rules for hum shortlinks. 243 | */ 244 | public function rewrite_rules() { 245 | $local_types = $this->local_types(); 246 | $redirect_types = $this->redirect_types(); 247 | 248 | $types = array_merge( $local_types, $redirect_types ); 249 | $types = implode( '', array_unique( $types ) ); 250 | 251 | add_rewrite_rule( "([{$types}](\/.*)?$)", 'index.php?hum=$matches[1]', 'top' ); 252 | } 253 | 254 | /** 255 | * Add rewrite rules for hum shortlinks. 256 | */ 257 | public function flush_rewrite_rules() { 258 | $this->rewrite_rules(); 259 | flush_rewrite_rules(); 260 | } 261 | 262 | /** 263 | * Get the base URL for hum shortlinks. Defaults to the WordPress home url. 264 | * Users can define HUM_SHORTLINK_BASE or provide a filter to use a custom 265 | * domain for shortlinks. 266 | * 267 | * @uses apply_filters() Calls 'hum_shortlink_base' filter on base URL. 268 | * 269 | * @return string 270 | */ 271 | public function shortlink_base() { 272 | $base = get_option( 'hum_shortlink_base' ); 273 | if ( empty( $base ) ) { 274 | $base = home_url(); 275 | } 276 | return apply_filters( 'hum_shortlink_base', $base ); 277 | } 278 | 279 | /** 280 | * Allow the constant named 'HUM_SHORTLINK_BASE' to override the base URL for shortlinks. 281 | * 282 | * @param string $url The short URL. 283 | */ 284 | public function config_shortlink_base( $url = '' ) { 285 | if ( defined( 'HUM_SHORTLINK_BASE' ) ) { 286 | return untrailingslashit( HUM_SHORTLINK_BASE ); 287 | } 288 | return $url; 289 | } 290 | 291 | /** 292 | * Get the shortlink for a post, page, attachment, or blog. 293 | * 294 | * @param int $id A post or site ID. Default is 0, which means the current post or site. 295 | * @param string $context Whether the ID is a 'site' ID, 'post' ID, or 'media' ID. If 'post', 296 | * the post_type of the post is consulted. If 'query', the current query is consulted 297 | * to determine the ID and context. Default 'post'. 298 | * @param bool $allow_slugs Whether to allow post slugs in the shortlink. It is up to the plugin how 299 | * and whether to honor this. Default true. 300 | * @return string 301 | */ 302 | public function get_shortlink( $link, $id, $context, $allow_slugs ) { 303 | $post_id = 0; 304 | if ( 'query' === $context && is_singular() ) { 305 | $post_id = get_queried_object_id(); 306 | $post = get_post( $post_id ); 307 | } elseif ( 'post' === $context ) { 308 | $post = get_post( $id ); 309 | if ( ! empty( $post->ID ) ) { 310 | $post_id = $post->ID; 311 | } 312 | } 313 | 314 | if ( ! empty( $post_id ) ) { 315 | $type = $this->type_prefix( $post_id ); 316 | $sxg_id = num_to_sxg( $post_id ); 317 | $link = trailingslashit( $this->shortlink_base() ) . $type . '/' . $sxg_id; 318 | } 319 | 320 | return $link; 321 | } 322 | 323 | /** 324 | * Get the content-type prefix for the specified post. 325 | * 326 | * @see http://ttk.me/w/Whistle#design 327 | * @uses apply_filters() Calls 'hum_type_prefix' on the content type prefix. 328 | * 329 | * @param int|object $post A post 330 | * @return string The content type prefix for the post. 331 | */ 332 | public function type_prefix( $post ) { 333 | $prefix = 'b'; 334 | 335 | $post_type = get_post_type( $post ); 336 | 337 | if ( 'attachment' === $post_type ) { 338 | // check if $post is a WP_Post or an ID 339 | if ( is_numeric( $post ) ) { 340 | $post_id = $post; 341 | } else { 342 | $post_id = $post->ID; 343 | } 344 | 345 | $mime_type = get_post_mime_type( $post_id ); 346 | $media_type = preg_replace( '/(\/[a-zA-Z]+)/i', '', $mime_type ); 347 | 348 | switch ( $media_type ) { 349 | case 'audio': 350 | case 'video': 351 | $prefix = 'a'; 352 | break; 353 | case 'image': 354 | $prefix = 'p'; 355 | break; 356 | } 357 | 358 | // @todo add support for slides 359 | } else { 360 | $post_format = get_post_format( $post ); 361 | switch ( $post_format ) { 362 | case 'aside': 363 | case 'status': 364 | case 'link': 365 | $prefix = 't'; 366 | break; 367 | case 'audio': 368 | case 'video': 369 | $prefix = 'a'; 370 | break; 371 | case 'photo': 372 | case 'gallery': 373 | case 'image': 374 | $prefix = 'p'; 375 | break; 376 | } 377 | } 378 | 379 | return apply_filters( 'hum_type_prefix', $prefix, $post ); 380 | } 381 | 382 | /** 383 | * Support redirects from legacy short URL schemes. This allows users to migrate from other 384 | * shortlink generaters, but still have hum support the old URLs. 385 | * 386 | * @uses do_action() Calls 'hum_legacy_id' with the post ID and shortlink path. 387 | */ 388 | public function legacy_redirect() { 389 | if ( is_404() ) { 390 | global $wp; 391 | $post_id = apply_filters( 'hum_legacy_id', 0, $wp->request ); 392 | if ( $post_id ) { 393 | $url = get_permalink( $post_id ); 394 | if ( $url ) { 395 | $url = apply_filters( 'hum_legacy_redirect', $url ); 396 | wp_redirect( $url, 301 ); 397 | exit; 398 | } 399 | } 400 | } 401 | } 402 | 403 | /** 404 | * Handle shortlinks generated by Friendly Twitter Links, which take the form 405 | * /{id}, where {id} can be the base10 or base32 post ID. 406 | * 407 | * @param int $id post ID to filter on. 408 | * @param string $path URL path (without preceding slash) of the request. 409 | * 410 | * @return string ID of post to redirect to. 411 | */ 412 | public function legacy_ftl_id( $id, $path ) { 413 | if ( is_numeric( $path ) ) { 414 | $post = get_post( $path ); 415 | } else { 416 | $post_id = base_convert( preg_replace( '/[^0-9a-fA-F]/', '', $path ), 32, 10 ); 417 | $post = get_post( $post_id ); 418 | } 419 | 420 | if ( $post ) { 421 | $id = $post->ID; 422 | } 423 | 424 | return $id; 425 | } 426 | 427 | 428 | // Admin Settings 429 | 430 | /** 431 | * Register admin settings for Hum. 432 | */ 433 | public function admin_init() { 434 | register_setting( 'general', 'hum_shortlink_base' ); 435 | } 436 | 437 | /** 438 | * Add admin settings fields for Hum. 439 | */ 440 | public function admin_menu() { 441 | add_settings_field( 'hum_shortlink_base', __( 'Shortlink Base (URL)', 'hum' ), array( $this, 'admin_shortlink_base' ), 'general' ); 442 | } 443 | 444 | /** 445 | * Admin UI for setting the shortlink base URL. 446 | */ 447 | public function admin_shortlink_base() { 448 | ?> 449 | 452 | class="regular-text code" /> 453 |

454 | 455 |

456 | 457 | 461 | to Atom-Entry. 466 | */ 467 | public function shortlink_atom_entry() { 468 | $shortlink = wp_get_shortlink(); 469 | if ( $shortlink ) { 470 | echo "\t\t" . '' . PHP_EOL; 471 | } 472 | } 473 | 474 | /** 475 | * Show shortlink column. 476 | * 477 | * @param array $columns The list of columns. 478 | */ 479 | public function add_post_column( $columns ) { 480 | $reorderes_columns = array(); 481 | foreach ( $columns as $key => $value ) { 482 | if ( 'date' === $key ) { 483 | $reorderes_columns['shortlink'] = esc_html__( 'Shortlink', 'hum' ); 484 | } 485 | $reorderes_columns[ $key ] = $value; 486 | } 487 | 488 | return $reorderes_columns; 489 | } 490 | 491 | /** 492 | * Generate shortlink column. 493 | * 494 | * @param string $column_name The culumn name. 495 | * @param string $post_id The post id. 496 | */ 497 | public function add_posts_custom_column( $column_name, $post_id ) { 498 | if ( 'shortlink' === $column_name ) { 499 | printf( '%s', wp_get_shortlink( $post_id ) ); 500 | } 501 | } 502 | } 503 | 504 | new Hum(); 505 | 506 | 507 | // New Base 60 - see http://ttk.me/w/NewBase60 508 | // 509 | // slightly modified from Cassis Project (http://cassisproject.com/) 510 | // Copyright 2010 Tantek Çelik, used with permission under CC0 license (http://git.io/tZ8fjw) 511 | // 512 | // @codingStandardsIgnoreStart 513 | if ( ! function_exists( 'num_to_sxg' ) ) : 514 | /** 515 | * Convert base-10 number to sexagesimal. 516 | */ 517 | function num_to_sxg($n) { 518 | $s = ""; 519 | $m = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz"; 520 | if ($n===null || $n===0) { return 0; } 521 | while ($n>0) { 522 | $d = $n % 60; 523 | $s = $m[$d] . $s; 524 | $n = ($n-$d)/60; 525 | } 526 | return $s; 527 | } 528 | endif; 529 | 530 | 531 | if ( ! function_exists( 'sxg_to_num' ) ) : 532 | /** 533 | * Convert sexagesimal to base-10 number. 534 | */ 535 | function sxg_to_num( $s ) { 536 | $n = 0; 537 | $j = strlen($s); 538 | for ($i=0;$i<$j;$i++) { // iterate from first to last char of $s 539 | $c = ord($s[$i]); // put current ASCII of char into $c 540 | if ($c>=48 && $c<=57) { $c=$c-48; } 541 | else if ($c>=65 && $c<=72) { $c-=55; } 542 | else if ($c==73 || $c==108) { $c=1; } // typo capital I, lowercase l to 1 543 | else if ($c>=74 && $c<=78) { $c-=56; } 544 | else if ($c==79) { $c=0; } // error correct typo capital O to 0 545 | else if ($c>=80 && $c<=90) { $c-=57; } 546 | else if ($c==95) { $c=34; } // underscore 547 | else if ($c>=97 && $c<=107) { $c-=62; } 548 | else if ($c>=109 && $c<=122) { $c-=63; } 549 | else { $c = 0; } // treat all other noise as 0 550 | $n = 60*$n + $c; 551 | } 552 | return $n; 553 | } 554 | endif; 555 | // @codingStandardsIgnoreEnd 556 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Hum 2 | 3 | - Contributors: willnorris, pfefferle 4 | - Tags: shortlink, whistle, diso 5 | - Requires at least: 3.0 6 | - Tested up to: 6.7 7 | - Stable tag: 1.3.6 8 | - Requires PHP: 5.6 9 | - License: MIT 10 | - License URI: http://opensource.org/licenses/MIT 11 | 12 | Personal URL shortener for WordPress 13 | 14 | 15 | ## Description 16 | 17 | Hum is a personal URL shortener for WordPress, designed to provide short URLs to your personal content, both hosted on WordPress and elsewhere. For example, rather than a long URL for a WordPress post such as , you could have a short URL like . Additionally, if you have a custom domain for short URLs, you can shorten things further like . Once the plugin is enabled, the shortlink for a page or post can be found in the "Shortlink" item in the WordPress Admin Bar. 18 | 19 | 20 | WordPress post IDs are shortened using the [NewBase60][] encoding scheme which is specifically optimized for brevity and readability, with built-in error correction for commonly confused characters like '1', 'l', and 'I'. 21 | 22 | Hum is not designed as a general purpose URL shortener along the lines of or . Rather, it is specifically intended as a personal shortener for your own content. 23 | 24 | Read more about the reasoning for a personal URL shortener at [Tantek Celik][]'s page for [Whistle][], which served as the inspiration for Hum. 25 | 26 | [NewBase60]: http://ttk.me/w/NewBase60 27 | [Tantek Celik]: http://tantek.com/ 28 | [Whistle]: http://ttk.me/w/Whistle 29 | 30 | 31 | ## Installation 32 | 33 | Follow the normal instructions for [installing WordPress plugins][install]. 34 | 35 | [install]: http://codex.wordpress.org/Managing_Plugins#Installing_Plugins 36 | 37 | ### Using a custom domain 38 | 39 | If you have a custom domain you'd like to use with Hum, add it as the 'Shortlink Base (URL)' on the 'General Settings' WordPress admin page or define the `HUM_SHORTLINK_BASE` constant in your `wp-config.php`: 40 | 41 | define('HUM_SHORTLINK_BASE', 'http://wjn.me'); 42 | 43 | You will also need to setup your short domain to redirect to your normal domain. Many domain registrars provide free redirection services that work well for this, so you don't need to setup a new domain with your web host. Just make sure that you are **not** using an iframe style redirect. 44 | 45 | 46 | ## Frequently Asked Questions 47 | 48 | ### What types of content does Hum support? 49 | 50 | Out of the box, Hum will provide shortlinks for any content locally hosted on WordPress. Most shortlinks will use the `b` type prefix, with the exception of posts with a 'status' [post format][], which have shortlinks using the `t` type prefix. For example: 51 | 52 | - 53 | - 54 | 55 | Additionally, the `i` type prefix, along with one of four subtypes, is supported as follows: 56 | 57 | - `asin` or `a` for Amazon ASIN numbers 58 | - `isbn` or `i` for ISBN numbers 59 | 60 | All `i` URLs are redirected to Amazon.com. For example: 61 | 62 | - 63 | 64 | Additional type prefixes can be registered to serve WordPress hosted content or to redirect to an external service. See more in the developer documentation. 65 | 66 | [post format]: http://codex.wordpress.org/Post_Formats 67 | 68 | ### Redirects are not working and result in a 404. 69 | 70 | This can happen if the rewrite rules were not flushed. This most likely happens if you are using Hum on a Multisite. This can be fixed by flushing the rewrite rules, just go to Settings->Permalinks and hit `Save Changes` on each instance where Hum does not work as intended. 71 | 72 | 73 | ## Developer Documentation 74 | 75 | ### Adding your Amazon Affiliate ID 76 | 77 | If you'd like to include your Amazone Affiliate ID in the `/i/` redirect URLs, implement the `amazon_affiliate_id` filter. For example: 78 | 79 | add_filter('amazon_affiliate_id', fn() => "willnorris-20"); 80 | 81 | ### Additional Local Types 82 | 83 | Out of the box, Hum only registers the `b`, `t`, `a` and `p` prefix to be served locally by WordPress. If you would like to register additional prefixes, implement the `hum_local_types` filter. For example, to include 'p' as well for photos: 84 | 85 | function myplugin_hum_local_types( $types ) { 86 | $types[] = 'p'; 87 | return $types; 88 | } 89 | add_filter('hum_local_types', 'myplugin_hum_local_types'); 90 | 91 | This will tell Hum to serve any `/p/{id}` URLs from WordPress. Additionally, you'll want to instruct Hum to use your prefix for that particular content type. Here, we're registering 'p' which is normally used for photos. 92 | 93 | function myplugin_hum_type_prefix( $prefix, $post_id ) { 94 | $post = get_post( $post_id ); 95 | 96 | if ( $post->post_type ## 'attachment' && 97 | strpos($post->post_mime_type, 'image') =## 0 ) { 98 | $prefix = 'p'; 99 | } 100 | 101 | return $prefix; 102 | } 103 | add_filter('hum_type_prefix', 'myplugin_hum_type_prefix', 10, 2); 104 | 105 | ### Simple Redirect 106 | 107 | You can redirect all traffic for a prefix using a single line of PHP my implementing the `hum_redirect_base_{type}` filter where `{type}` is the prefix to redirect. For example, I redirect all `/w/` URLs to wiki.willnorris.com using: 108 | 109 | add_filter('hum_redirect_base_w', fn() => "http://wiki.willnorris.com/"); 110 | 111 | 112 | ## Changelog 113 | 114 | Project maintined on github at [willnorris/wordpress-hum](https://github.com/willnorris/wordpress-hum). 115 | 116 | ### 1.3.6 117 | 118 | - optimized Block Editor integration 119 | 120 | ### 1.3.5 121 | 122 | - update JS dependencies and code 123 | 124 | ### 1.3.4 125 | 126 | - fix broken `wp_get_shortlink` hook, when loaded in the frontend 127 | 128 | ### 1.3.3 129 | 130 | - fix PHP warning in combination with widgets 131 | 132 | ### 1.3.2 133 | 134 | - update documentation 135 | 136 | ### 1.3.1 137 | 138 | - change the priority of the rewrite rules action 139 | 140 | ### 1.3.0 141 | 142 | - redirect types are now also filterable 143 | 144 | ### 1.2.8 145 | 146 | - add shortlink panel to block editor (props [@florianbrinkmann][]) 147 | 148 | ### 1.2.7 149 | 150 | - redirect only known types (see [#wp180868][]) 151 | 152 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2.6...1.2.7) 153 | 154 | ### 1.2.6 155 | 156 | - fix PHP 7.4 deprecation warning 157 | - WordPress coding style changes 158 | 159 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2.5...1.2.6) 160 | 161 | ### 1.2.5 162 | 163 | - add shortlink to post/page overview pages 164 | 165 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2.4...1.2.5) 166 | 167 | ### 1.2.4 168 | 169 | - finally fixed "flush rewrite rules" 170 | 171 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2.3...1.2.4) 172 | 173 | ### 1.2.3 174 | 175 | - fixed "flush rewrite rules" 176 | 177 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2.2...1.2.3) 178 | 179 | ### 1.2.2 180 | 181 | - version bump 182 | 183 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2.1...1.2.2) 184 | 185 | ### 1.2.1 186 | 187 | - add `amazon_domain` filter, to support different countries 188 | - add `hum_process_redirect` action, to overwrite default rewrite method (see [#17][]) 189 | 190 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.2...1.2.1) 191 | 192 | ### 1.2 193 | 194 | - move link post format to use 't' prefix instead of 'h' and add support for 195 | image post format 196 | - add support for WordPress media attachments 197 | - add shortlinks to Atom feeds 198 | - add support for legacy short url schemes (see [#6][]) 199 | - switch to using WordPress filters instead of actions for hum extensions (see 200 | [#3][]) 201 | 202 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.1...1.2) 203 | 204 | ### 1.1 205 | 206 | - allow custom domain to be configured using `HUM_SHORTLINK_BASE` constant or 207 | via the General Settings admin page. 208 | - strip some punctuation at the end of URLs (see [#4][]) 209 | - smarter URL matching (see [#1][] and [#2][]) 210 | - add support for `/i/` URLs (redirects to Amazon for ASIN or ISBN 211 | identifiers, optionally including an Amazon affiliate ID) 212 | - standard 404 handling if hum can't find a proper redirect 213 | - add new `hum_local_types` filter for registering other prefixes thatt are 214 | served locally by WordPress 215 | - reduce extra redirect for local content 216 | 217 | [full changelog](https://github.com/willnorris/wordpress-hum/compare/1.0...1.1) 218 | 219 | [#1]: https://github.com/willnorris/wordpress-hum/issues/1 220 | [#2]: https://github.com/willnorris/wordpress-hum/issues/2 221 | [#3]: https://github.com/willnorris/wordpress-hum/issues/3 222 | [#4]: https://github.com/willnorris/wordpress-hum/issues/4 223 | [#6]: https://github.com/willnorris/wordpress-hum/issues/6 224 | [#17]: https://github.com/willnorris/wordpress-hum/pull/17 225 | [#wp180868]: https://wordpress.org/support/topic/causing-404-on-category-tag-pages/ 226 | [@florianbrinkmann]: https://profiles.wordpress.org/florianbrinkmann/ 227 | 228 | ### 1.0 229 | 230 | - initial public release 231 | 232 | 233 | ## Upgrade Notice 234 | 235 | ### 1.1 236 | 237 | Adds a new admin UI for setting a custom domain for shortlinks, includes 238 | smarter URL matching, and adds various small improvements and bug fixes. 239 | --------------------------------------------------------------------------------