eth-simple-shortlinks.php 5.53 KB
Newer Older
Erick Hitter's avatar
Erick Hitter committed
1
2
3
4
5
6
<?php
/*
Plugin Name: ETH Simple Shortlinks
Plugin URI: https://ethitter.com/plugins/
Description: Simple non-GET shortlinks using post IDs
Author: Erick Hitter
7
Version: 0.3
Erick Hitter's avatar
Erick Hitter committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Author URI: https://ethitter.com/

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

class ETH_Simple_Shortlinks {
	/**
	 * PLUGIN SETUP
	 */

	/**
	 * Singleton
	 */
	private static $instance = null;

	/**
	 * Instantiate singleton
	 */
	public static function get_instance() {
		if ( ! is_a( self::$instance, __CLASS__ ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}

	/**
	 * Dummy magic methods
	 */
	public function __clone() {_doing_it_wrong( __FUNCTION__, 'Cheatin&#8217; huh?', '0.1' ); }
	public function __wakeup() { _doing_it_wrong( __FUNCTION__, 'Cheatin&#8217; huh?', '0.1' ); }
	public function __call( $name = '', $args = array() ) { unset( $name, $args ); return null; }

Erick Hitter's avatar
Erick Hitter committed
53
54
55
	/**
	 * Class properties
	 */
56
	private $slug = 'p';
57
	private $qv   = 'eth-shortlink';
Erick Hitter's avatar
Erick Hitter committed
58

59
60
61
	private $supported_post_types    = array();
	private $supported_post_statuses = array();

Erick Hitter's avatar
Erick Hitter committed
62
	/**
63
	 * Register actions and filters
Erick Hitter's avatar
Erick Hitter committed
64
	 */
Erick Hitter's avatar
Erick Hitter committed
65
	private function __construct() {
66
		// Request
Erick Hitter's avatar
Erick Hitter committed
67
		add_action( 'init', array( $this, 'add_rewrite_rule' ) );
68
		add_action( 'wp_loaded', array( $this, 'filter_support' ) );
Erick Hitter's avatar
Erick Hitter committed
69
70
		add_filter( 'query_vars', array( $this, 'filter_query_vars' ) );
		add_action( 'parse_request', array( $this, 'action_parse_request' ) );
71
72
73

		// Shortlink
		add_filter( 'get_shortlink', array( $this, 'filter_get_shortlink' ), 10, 2 );
74
		add_action( 'admin_head-edit.php', array( $this, 'add_admin_header_assets' ) );
75
76
		add_filter( 'post_row_actions', array( $this, 'filter_row_actions' ), 10, 2 );
		add_filter( 'page_row_actions', array( $this, 'filter_row_actions' ), 10, 2 );
Erick Hitter's avatar
Erick Hitter committed
77
78
79
80
81
82
	}

	/**
	 * Register rewrite rule
	 */
	public function add_rewrite_rule() {
83
		add_rewrite_rule( '^' . $this->slug . '/([\d]+)/?$', 'index.php?p=$matches[1]&' . $this->qv . '=1', 'top' );
Erick Hitter's avatar
Erick Hitter committed
84
85
	}

86
87
88
89
90
91
92
93
	/**
	 * Allow filtering of supported statuses and types
	 */
	public function filter_support() {
		$this->supported_post_statuses = apply_filters( 'eth_simple_shortlinks_allowed_post_statuses', array( 'publish', 'future' ) );
		$this->supported_post_types    = apply_filters( 'eth_simple_shortlinks_allowed_post_types',    array( 'post', 'page' ) );
	}

Erick Hitter's avatar
Erick Hitter committed
94
95
96
97
98
99
100
101
102
103
104
	/**
	 * Add custom query var to those permitted, so it can be detected at `parse_request`
	 */
	public function filter_query_vars( $qv ) {
		$qv[] = $this->qv;

		return $qv;
	}

	/**
	 * Catch this plugin's requests and issue redirects, otherwise WP will serve content at duplicate URLs
105
106
107
108
	 *
	 * Let's invalid post IDs fall through to WP's 404 handler, or anything else that might intercede
	 *
	 * URLs aren't validated in case plugins filter permalinks to point to external URLs
Erick Hitter's avatar
Erick Hitter committed
109
110
111
	 */
	public function action_parse_request( $request ) {
		if ( isset( $request->query_vars[ $this->qv ] ) ) {
112
			$dest = get_permalink( $request->query_vars[ 'p' ] );
Erick Hitter's avatar
Erick Hitter committed
113
114

			if ( $dest ) {
115
116
				wp_redirect( $dest, 301 );
				exit;
Erick Hitter's avatar
Erick Hitter committed
117
118
119
			}
		}
	}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

	/**
	 * Override shortlinks with this plugin's format
	 */
	public function filter_get_shortlink( $shortlink, $id ) {
		if ( empty( $id ) ) {
			$_p = get_post();

			if ( ! empty( $_p->ID ) ) {
				$id = $_p->ID;
			}
		}

		if ( empty( $id ) ) {
			return $shortlink;
		}

137
		if ( ! in_array( get_post_status( $id ), $this->supported_post_statuses ) ) {
138
139
140
			return $shortlink;
		}

141
		if ( ! in_array( get_post_type( $id ), $this->supported_post_types ) ) {
142
143
144
			return $shortlink;
		}

145
146
147
		return $this->get_shortlink( $id );
	}

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	/**
	 * Header assets for shortlink in row actions
	 */
	public function add_admin_header_assets() {
		global $typenow;
		if ( ! in_array( $typenow, $this->supported_post_types ) ) {
			return;
		}

		?>
		<script type="text/javascript">

			jQuery( document ) .ready( function( $ ) {
				$( '.row-actions .shortlink a' ).click( function( e ) {
					e.preventDefault();

					prompt( 'URL:', $( this ).attr('href') );
				} );
			} );
		</script>
		<?php
	}

171
172
173
174
175
176
177
178
	/**
	 * Provide the shortlink in row actions for easy access
	 */
	public function filter_row_actions( $actions, $post ) {
		if ( ! in_array( get_post_type( $post ), $this->supported_post_types ) ) {
			return $actions;
		}

179
		$actions['shortlink'] = '<a href="' . esc_js( $this->get_shortlink( $post->ID ) ) . '">Shortlink</a>';
180
181
182
183
184
185
186
187
188

		return $actions;
	}

	/**
	 * Utility method for building permlink
	 */
	public function get_shortlink( $post_id ) {
		return user_trailingslashit( home_url( sprintf( '%s/%d', $this->slug, $post_id ) ) );
189
	}
Erick Hitter's avatar
Erick Hitter committed
190
191
192
}

ETH_Simple_Shortlinks::get_instance();
193
194
195
196
197
198
199
200
201
202
203
204

/**
 * Shortcut for using the shortlink outside of this plugin's considerations
 */
function eth_simple_shortlinks_get( $post_id ) {
	if ( ! did_action( 'wp_loaded' ) ) {
		_doing_it_wrong( __FUNCTION__, 'Shortlinks cannot be generated until after <code>wp_loaded</code>; this ensures that all post types are registered.', '0.3' );
		return false;
	}

	return ETH_Simple_Shortlinks::get_instance()->get_shortlink( $post_id );
}