1 | <?php |
---|
2 | /** |
---|
3 | * Embed PDF Viewer |
---|
4 | * |
---|
5 | * @author Andy Fragen |
---|
6 | * @license GPL-2.0+ |
---|
7 | * @link https://github.com/afragen/embed-pdf-viewer |
---|
8 | * @package embed-pdf-viewer |
---|
9 | */ |
---|
10 | |
---|
11 | /** |
---|
12 | * Plugin Name: Embed PDF Viewer |
---|
13 | * Plugin URI: https://github.com/afragen/embed-pdf-viewer |
---|
14 | * Description: Embed a PDF from the Media Library or elsewhere via oEmbed or as a block into an `iframe` tag. |
---|
15 | * Author: Andy Fragen |
---|
16 | * Author URI: https://github.com/afragen |
---|
17 | * Version: 2.4.2 |
---|
18 | * License: GPLv2+ |
---|
19 | * Domain Path: /languages |
---|
20 | * Text Domain: embed-pdf-viewer |
---|
21 | * License URI: http://www.gnu.org/licenses/gpl-2.0.html |
---|
22 | * GitHub Plugin URI: https://github.com/afragen/embed-pdf-viewer |
---|
23 | * Requires PHP: 5.6 |
---|
24 | * Requires at least: 4.6 |
---|
25 | */ |
---|
26 | |
---|
27 | /** |
---|
28 | * Exit if called directly. |
---|
29 | */ |
---|
30 | if ( ! defined( 'WPINC' ) ) { |
---|
31 | die; |
---|
32 | } |
---|
33 | |
---|
34 | $epd_version = get_file_data( __FILE__, [ 'Version' => 'version' ] )['Version']; |
---|
35 | add_filter( 'media_send_to_editor', [ Embed_PDF_Viewer::instance( $epd_version ), 'embed_pdf_media_editor' ], 20, 2 ); |
---|
36 | wp_embed_register_handler( |
---|
37 | 'oembed_pdf_viewer', |
---|
38 | '#(^(https?)\:\/\/.+\.pdf$)#i', |
---|
39 | [ |
---|
40 | Embed_PDF_Viewer::instance( $epd_version ), |
---|
41 | 'oembed_pdf_viewer', |
---|
42 | ] |
---|
43 | ); |
---|
44 | add_action( |
---|
45 | 'init', |
---|
46 | function () use ( $epd_version ) { |
---|
47 | load_plugin_textdomain( 'embed-pdf-viewer' ); |
---|
48 | wp_set_script_translations( 'embed-pdf-viewer-scripts', 'embed-pdf-viewer' ); |
---|
49 | |
---|
50 | // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NoExplicitVersion |
---|
51 | wp_enqueue_style( |
---|
52 | 'embed-pdf-viewer', |
---|
53 | plugins_url( 'css/embed-pdf-viewer.css', __FILE__ ), |
---|
54 | [], |
---|
55 | $epd_version, |
---|
56 | 'screen' |
---|
57 | ); |
---|
58 | } |
---|
59 | ); |
---|
60 | add_action( 'init', [ Embed_PDF_Viewer::instance( $epd_version ), 'register_block' ] ); |
---|
61 | |
---|
62 | /** |
---|
63 | * Class Embed_PDF_Viewer |
---|
64 | */ |
---|
65 | class Embed_PDF_Viewer { |
---|
66 | /** |
---|
67 | * For singleton. |
---|
68 | * |
---|
69 | * @var bool |
---|
70 | */ |
---|
71 | private static $instance = false; |
---|
72 | |
---|
73 | /** |
---|
74 | * Plugin version number. |
---|
75 | * |
---|
76 | * @var string |
---|
77 | */ |
---|
78 | private static $version = ''; |
---|
79 | |
---|
80 | /** |
---|
81 | * Create singleton. |
---|
82 | * |
---|
83 | * @param string $version Plugin version number. |
---|
84 | * @return bool |
---|
85 | */ |
---|
86 | public static function instance( $version ) { |
---|
87 | static::$version = $version; |
---|
88 | if ( false === static::$instance ) { |
---|
89 | static::$instance = new self( $version ); |
---|
90 | } |
---|
91 | |
---|
92 | return static::$instance; |
---|
93 | } |
---|
94 | |
---|
95 | /** |
---|
96 | * Register block. |
---|
97 | * |
---|
98 | * @return void |
---|
99 | */ |
---|
100 | public function register_block() { |
---|
101 | if ( ! function_exists( 'register_block_type' ) ) { |
---|
102 | return; |
---|
103 | } |
---|
104 | |
---|
105 | // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NoExplicitVersion |
---|
106 | wp_register_script( |
---|
107 | 'embed-pdf-viewer', |
---|
108 | plugins_url( 'blocks/build/index.js', __FILE__ ), |
---|
109 | [ 'wp-i18n', 'wp-blocks', 'wp-block-editor', 'wp-element', 'wp-components', 'wp-compose', 'wp-blob' ], |
---|
110 | static::$version, |
---|
111 | true |
---|
112 | ); |
---|
113 | |
---|
114 | register_block_type( |
---|
115 | 'embed-pdf-viewer/pdf', |
---|
116 | [ |
---|
117 | 'editor_script' => 'embed-pdf-viewer', |
---|
118 | 'render_callback' => [ static::$instance, 'dynamic_render_callback' ], |
---|
119 | ] |
---|
120 | ); |
---|
121 | } |
---|
122 | |
---|
123 | /** |
---|
124 | * Dynamically render callback based on browser. |
---|
125 | * |
---|
126 | * @global bool $is_chrome Tests for Chrome browser. |
---|
127 | * |
---|
128 | * @param array $attributes Array of attributes. |
---|
129 | * |
---|
130 | * @return string |
---|
131 | */ |
---|
132 | public function dynamic_render_callback( $attributes ) { |
---|
133 | global $is_chrome; |
---|
134 | |
---|
135 | $url = $attributes['url'] ?? null; |
---|
136 | if ( ! $url ) { |
---|
137 | �� return ''; |
---|
138 | } |
---|
139 | |
---|
140 | $classes = 'embed-pdf-viewer'; |
---|
141 | $src = $is_chrome || wp_is_mobile() ? 'https://docs.google.com/viewer?url=' . rawurlencode( $url ) . '&embedded=true' : $url; |
---|
142 | return sprintf( |
---|
143 | '<iframe class="%1$s" src="%2$s" height="%3$s" width="%4$s" title="%5$s"%6$s></iframe>', |
---|
144 | $classes, |
---|
145 | sanitize_url( $src ), |
---|
146 | $attributes['width'] ?? '600', |
---|
147 | $attributes['height'] ?? '600', |
---|
148 | $attributes['description'] ?? $attributes['title'], |
---|
149 | $is_chrome || wp_is_mobile() ? ' frameborder="0"' : '' |
---|
150 | ); |
---|
151 | } |
---|
152 | |
---|
153 | /** |
---|
154 | * Insert URL to PDF from Media Library, then render as oEmbed. |
---|
155 | * |
---|
156 | * @param string $html an href link to the media. |
---|
157 | * @param integer $id post_id. |
---|
158 | * |
---|
159 | * @return string |
---|
160 | */ |
---|
161 | public function embed_pdf_media_editor( $html, $id ) { |
---|
162 | $post = get_post( $id ); |
---|
163 | if ( 'application/pdf' !== $post->post_mime_type ) { |
---|
164 | return $html; |
---|
165 | } |
---|
166 | |
---|
167 | return $post->guid . "\n\n"; |
---|
168 | } |
---|
169 | |
---|
170 | /** |
---|
171 | * Create oEmbed code. |
---|
172 | * |
---|
173 | * @param array $matches Regex matches. |
---|
174 | * @param array $atts array of media height/width. |
---|
175 | * @param string $url URI for media file. |
---|
176 | * |
---|
177 | * @return string|WP_Error |
---|
178 | */ |
---|
179 | public function oembed_pdf_viewer( $matches, $atts, $url ) { |
---|
180 | $attachment_id = $this->get_attachment_id_by_url( $url ); |
---|
181 | if ( ! empty( $attachment_id ) ) { |
---|
182 | $post = get_post( $this->get_attachment_id_by_url( $url ) ); |
---|
183 | } else { |
---|
184 | /* |
---|
185 | * URL is from outside of the Media Library. |
---|
186 | */ |
---|
187 | $response = wp_remote_get( $url ); |
---|
188 | if ( is_wp_error( $response ) ) { |
---|
189 | return $response; |
---|
190 | } |
---|
191 | $post = new WP_Post( new stdClass() ); |
---|
192 | $post->guid = $matches[0]; |
---|
193 | $post->post_mime_type = wp_remote_retrieve_header( $response, 'content-type' ); |
---|
194 | $post->post_name = preg_replace( '/\.pdf$/', '', basename( $matches[0] ) ); |
---|
195 | } |
---|
196 | |
---|
197 | return $this->create_output( $post, $atts ); |
---|
198 | } |
---|
199 | |
---|
200 | /** |
---|
201 | * Create output for iframe and/or Google Doc Viewer and href link to file. |
---|
202 | * |
---|
203 | * @param \WP_Post $post Current post. |
---|
204 | * @param array|string $atts array of media height/width or |
---|
205 | * href to media library asset. |
---|
206 | * |
---|
207 | * @return bool|string |
---|
208 | */ |
---|
209 | private function create_output( WP_Post $post, $atts = [] ) { |
---|
210 | global $is_chrome; |
---|
211 | |
---|
212 | if ( 'application/pdf' !== $post->post_mime_type ) { |
---|
213 | return $atts; |
---|
214 | } |
---|
215 | |
---|
216 | $default = [ |
---|
217 | 'height' => 500, |
---|
218 | 'width' => 800, |
---|
219 | 'title' => $post->post_title, |
---|
220 | 'description' => $post->post_content, |
---|
221 | ]; |
---|
222 | |
---|
223 | /* |
---|
224 | * Ensure $atts isn't the href. |
---|
225 | */ |
---|
226 | $atts = is_array( $atts ) ? $atts : []; |
---|
227 | |
---|
228 | if ( isset( $atts['width'] ) ) { |
---|
229 | $atts['width'] = '100%'; |
---|
230 | } |
---|
231 | $atts = array_merge( $default, $atts ); |
---|
232 | |
---|
233 | /** |
---|
234 | * Filter PDF attributes. |
---|
235 | * |
---|
236 | * @since 1.6.0 |
---|
237 | * @param array $atts Array of PDF attributes. |
---|
238 | * @return array $atts |
---|
239 | */ |
---|
240 | $atts = apply_filters( 'embed_pdf_viewer_pdf_attributes', $atts ); |
---|
241 | |
---|
242 | // Fix title or create from filename. |
---|
243 | $atts['title'] = empty( $atts['title'] ) |
---|
244 | ? ucwords( preg_replace( '/(-|_)/', ' ', $post->post_name ) ) |
---|
245 | : ucwords( preg_replace( '/(-|_)/', ' ', $atts['title'] ) ); |
---|
246 | |
---|
247 | $description = ! empty( $atts['description'] ) ? $atts['description'] : $atts['title']; |
---|
248 | $sanitized_url = sanitize_url( $post->guid ); |
---|
249 | |
---|
250 | if ( $is_chrome || wp_is_mobile() ) { |
---|
251 | $iframe = '<iframe class="embed-pdf-viewer" src="https://docs.google.com/viewer?url=' . rawurlencode( $sanitized_url ); |
---|
252 | $iframe .= '&embedded=true" frameborder="0" '; |
---|
253 | } else { |
---|
254 | $iframe = '<iframe class="embed-pdf-viewer" src="' . $sanitized_url . '" '; |
---|
255 | } |
---|
256 | $iframe .= 'height="' . $atts['height'] . '" width="' . $atts['width'] . '" '; |
---|
257 | $iframe .= 'title="' . $description . '"></iframe>' . "\n"; |
---|
258 | |
---|
259 | $embed = '<div>'; |
---|
260 | $embed .= $iframe; |
---|
261 | $embed .= '<p><a href="' . $sanitized_url . '" title="' . $description . '">' . $description . '</a></p>'; |
---|
262 | $embed .= '</div>'; |
---|
263 | |
---|
264 | return $embed; |
---|
265 | } |
---|
266 | |
---|
267 | /** |
---|
268 | * Get attachment id by url. Thanks Pippin. |
---|
269 | * |
---|
270 | * @link https://pippinsplugins.com/retrieve-attachment-id-from-image-url/ |
---|
271 | * |
---|
272 | * @param string $url URI of attachment. |
---|
273 | * |
---|
274 | * @return mixed |
---|
275 | */ |
---|
276 | private function get_attachment_id_by_url( $url ) { |
---|
277 | global $wpdb; |
---|
278 | // phpcs:ignore WordPress.DB |
---|
279 | $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid='%s';", $url ) ); |
---|
280 | |
---|
281 | if ( empty( $attachment ) ) { |
---|
282 | return null; |
---|
283 | } |
---|
284 | |
---|
285 | return $attachment[0]; |
---|
286 | } |
---|
287 | } |
---|