PluginProbe
Document Embedder – let visitors read files without downloading / 2.1.2
Document Embedder – let visitors read files without downloading v2.1.2
2.3.1 2.3.0 2.2.1 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.3 1.7.4 1.7.6 1.7.9 1.8.1 1.8.2 1.8.3 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 2.0.0 2.0.1 2.0.2 All 30 releases
document-emberdder / includes / features / class-bplde-shortcode.php

class-bplde-shortcode.php in Document Embedder – let visitors read files without downloading 2.1.2, at includes/features/class-bplde-shortcode.php

346 lines 17.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * BPLDE Shortcode Controller.
4 *
5 * @package DocumentEmbedder
6 */
7
8 namespace BPLDE\Model;
9
10 use BPLDE\Helper\Functions;
11 use BPLDE\Helper\DefaultArgs;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Shortcode' ) ) {
18 class Shortcode {
19 protected static $_instance = null;
20
21 public function __construct() {
22 add_shortcode( 'doc', [$this, 'doc'] );
23 }
24
25 public static function instance() {
26 if ( self::$_instance === null ) {
27 self::$_instance = new self();
28 }
29 return self::$_instance;
30 }
31
32 public function doc( $atts ) {
33 $post_type = get_post_type( $atts['id'] );
34
35 if ( $post_type != 'ppt_viewer' ) {
36 return false;
37 }
38
39 $post_id = $atts['id'];
40 $post = get_post( $post_id );
41 if ( post_password_required( $post ) ) {
42 return get_the_password_form( $post );
43 }
44
45 switch ( $post->post_status ) {
46 case 'publish':
47 return $this->html( $atts['id'], $atts );
48
49 case 'private':
50 if ( current_user_can( 'read_private_posts' ) ) {
51 return $this->html( $atts['id'], $atts );
52 }
53 return '';
54
55 case 'draft':
56 case 'pending':
57 case 'future':
58 if ( current_user_can( 'edit_post', $post_id ) ) {
59 return $this->html( $atts['id'], $atts );
60 }
61 return '';
62
63 default:
64 return '';
65 }
66 }
67
68 public function html( $id, $atts = [] ) {
69 $data = $this->doc_data( $id, $atts );
70 $data = DefaultArgs::parseArgs( $data );
71 return $this->render_template( $data );
72 }
73
74 public function doc_data( $id, $atts = [] ) {
75 $width = Functions::meta( $id, 'width', ['width' => '100', 'unit' => '%'] );
76 $height = Functions::meta( $id, 'height', ['height' => 600, 'unit' => 'px'] );
77
78 $result = [
79 'doc' => Functions::meta( $id, 'doc', '' ),
80 'width' => $width['width'] . $width['unit'],
81 'height' => $height['height'] . $height['unit'],
82 'width_tablet' => Functions::meta( $id, 'width_tablet', '' ),
83 'width_mobile' => Functions::meta( $id, 'width_mobile', '' ),
84 'height_tablet' => Functions::meta( $id, 'height_tablet', '' ),
85 'height_mobile' => Functions::meta( $id, 'height_mobile', '' ),
86 'showName' => Functions::meta( $id, 'showName' ),
87 'download' => Functions::meta( $id, 'download', '0' ),
88 'downloadButtonText' => Functions::meta( $id, 'downloadButtonText', Functions::meta( $id, '_de_download_label', 'Download' ) ),
89 '_de_download_position' => Functions::meta( $id, '_de_download_position', 'toolbar' ),
90 '_de_download_behavior' => Functions::meta( $id, '_de_download_behavior', 'download' ),
91 '_de_download_filename' => Functions::meta( $id, '_de_download_filename', '' ),
92 '_de_download_show_count' => Functions::meta( $id, '_de_download_show_count', '0' ),
93 '_de_download_limit' => Functions::meta( $id, '_de_download_limit', '0' ),
94 'id' => $id
95 ];
96
97 if ( empty( $result['_de_download_label'] ) ) {
98 $result['_de_download_label'] = $result['downloadButtonText'] ? $result['downloadButtonText'] : 'Download';
99 }
100
101 $override_map = [
102 'download' => 'download',
103 'download_label' => '_de_download_label',
104 'download_position' => '_de_download_position',
105 'download_behavior' => '_de_download_behavior',
106 'download_filename' => '_de_download_filename',
107 'download_limit' => '_de_download_limit',
108 'show_count' => '_de_download_show_count',
109 ];
110 foreach ( $override_map as $att_key => $data_key ) {
111 if ( isset( $atts[$att_key] ) ) {
112 if ( in_array( $atts[$att_key], ['yes', 'true', '1'], true ) ) {
113 $result[$data_key] = '1';
114 } elseif ( in_array( $atts[$att_key], ['no', 'false', '0'], true ) ) {
115 $result[$data_key] = '0';
116 } else {
117 $result[$data_key] = $atts[$att_key];
118 }
119 }
120 }
121
122 // Check Limit per IP
123 $limit = (int) $result['_de_download_limit'];
124 $result['limit_reached'] = false;
125 if ( $limit > 0 ) {
126 global $wpdb;
127 $ip = Functions::get_client_ip();
128 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- querying custom table
129 $downloaded_count = $wpdb->get_var( $wpdb->prepare(
130 "SELECT COUNT(*) FROM {$wpdb->prefix}docembedder_leads WHERE document_id = %d AND ip_address = %s",
131 $id,
132 $ip
133 ) );
134
135 if ( (int) $downloaded_count >= $limit ) {
136 $result['limit_reached'] = true;
137 }
138 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
139 error_log( "DE DEBUG: Limit Check for ID $id. IP: $ip, Count: $downloaded_count, Limit: $limit, Reached: " . ( $result['limit_reached'] ? 'YES' : 'NO' ) );
140 } else {
141 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
142 error_log( "DE DEBUG: Limit Check for ID $id SKIPPED (Limit is 0)" );
143 }
144
145 $result = apply_filters( 'bplde_doc_data', $result, $id );
146 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- backward compatibility hook
147 return apply_filters( 'ppv_doc_data', $result, $id );
148 }
149
150 public function render_template( $data ) {
151 $parse_dim = function ( $prop, $default, $type = 'width' ) {
152 if ( is_array( $prop ) ) {
153 if ( isset( $prop[$type] ) && $prop[$type] !== '' ) {
154 return $prop[$type] . ( isset( $prop['unit'] ) ? $prop['unit'] : 'px' );
155 }
156 return $default;
157 }
158 $val = ! empty( $prop ) ? $prop : $default;
159 return is_numeric( $val ) ? $val . 'px' : $val;
160 };
161
162 $w_d = $parse_dim( isset( $data['width'] ) ? $data['width'] : '', '100%', 'width' );
163 $w_t = $parse_dim( isset( $data['width_tablet'] ) ? $data['width_tablet'] : '', $w_d, 'width' );
164 $w_m = $parse_dim( isset( $data['width_mobile'] ) ? $data['width_mobile'] : '', $w_t, 'width' );
165
166 $h_d = $parse_dim( isset( $data['height'] ) ? $data['height'] : '', '600px', 'height' );
167 $h_t = $parse_dim( isset( $data['height_tablet'] ) ? $data['height_tablet'] : '', $h_d, 'height' );
168 $h_m = $parse_dim( isset( $data['height_mobile'] ) ? $data['height_mobile'] : '', $h_t, 'height' );
169
170 $unique_id = 'de_' . uniqid();
171
172 ob_start();
173 ?>
174 <style>
175 .ppv_container.<?php echo esc_attr( $unique_id ); ?> {
176 width: <?php echo esc_attr( $w_d ); ?>;
177 height: <?php echo esc_attr( $h_d ); ?>;
178 display: flex;
179 flex-direction: column;
180 position: relative;
181 }
182
183 @media (max-width: 991px) {
184 .ppv_container.<?php echo esc_attr( $unique_id ); ?> {
185 width: <?php echo esc_attr( $w_t ); ?>;
186 height: <?php echo esc_attr( $h_t ); ?>;
187 }
188 }
189
190 @media (max-width: 767px) {
191 .ppv_container.<?php echo esc_attr( $unique_id ); ?> {
192 width: <?php echo esc_attr( $w_m ); ?>;
193 height: <?php echo esc_attr( $h_m ); ?>;
194 }
195 }
196
197 .<?php echo esc_attr( $unique_id ); ?>.document-preview {
198 width: 100%;
199 flex: 1;
200 display: flex;
201 flex-direction: column;
202 }
203
204 .<?php echo esc_attr( $unique_id ); ?>iframe {
205 width: 100%;
206 height: 100%;
207 flex: 1;
208 border: none;
209 }
210
211 .ppv-loading {
212 width: inherit;
213 position: absolute;
214 top: 50%;
215 left: 0;
216 font-family: sans-serif;
217 color: #666;
218 z-index: 1;
219 display: flex;
220 justify-content: center;
221 }
222 </style>
223 <?php
224 $base_url = '//docs.google.com/gview?embedded=true&url=';
225
226 if ( $data['doc'] == '' ) {
227 echo '<h2>Ooops... You forgot to Select a document. Please select a file or paste a external document link to show here. </h2>';
228 } else {
229 $is_download_allowed = false;
230 $dl_flag = isset( $data['download'] ) ? $data['download'] : false;
231 if ( in_array( $dl_flag, ['1', 1, 'true', true, 'yes'], true ) ) {
232 $is_download_allowed = true;
233
234 // Check IP limit
235 if ( isset( $data['limit_reached'] ) && $data['limit_reached'] ) {
236 $is_download_allowed = false;
237 }
238 }
239
240 // Prepare download button HTML
241 $download_btn_html = '';
242 if ( isset( $data['limit_reached'] ) && $data['limit_reached'] && in_array( $dl_flag, ['1', 1, 'true', true, 'yes'], true ) ) {
243 $download_btn_html = '<button disabled style="background: transparent; padding: 4px 10px; border-radius: 4px; border: 1px solid #ff4d4d; color: #ff4d4d; cursor: not-allowed;" title="Download limit reached for your IP.">Limit Reached</button>';
244 $is_download_allowed = false; // Ensure logic below respects this
245 } elseif ( $is_download_allowed ) {
246 // Count HTML
247 $download_count_html = '';
248 $show_count_flag = isset( $data['_de_download_show_count'] ) ? $data['_de_download_show_count'] : false;
249 if ( in_array( $show_count_flag, ['1', 1, 'true', true, 'yes'], true ) ) {
250 $count = get_post_meta( $data['id'], '_de_download_count', true );
251 if ( ! $count ) {
252 $count = 0;
253 }
254 $download_count_html = '<span class="ppv-download-count" style="font-size: 12px; color: #cececf; border: 1px solid #cececf; padding: 3px 10px; border-radius: 4px;">' . esc_html( $count ) . ' downloads</span>';
255 }
256
257 $btn_label = isset( $data['downloadButtonText'] ) && ! empty( $data['downloadButtonText'] ) ? esc_html( $data['downloadButtonText'] ) : 'Download';
258
259 $dl_attr = '';
260 $target_attr = '';
261 $href = esc_url( $data['doc'] );
262 $behavior = isset( $data['_de_download_behavior'] ) ? $data['_de_download_behavior'] : 'download';
263 if ( $behavior === 'newtab' ) {
264 $target_attr = ' target="_blank"';
265 } else {
266 if ( ! empty( $data['_de_download_filename'] ) ) {
267 $dl_attr = ' download="' . esc_attr( $data['_de_download_filename'] ) . '"';
268 } else {
269 $dl_attr = ' download';
270 }
271 }
272 $download_btn_html = '<a class="s_pdf_download_link" style="display: flex;" href="' . $href . '"' . $target_attr . $dl_attr . '><button style="background: transparent; padding: 4px 10px; border-radius: 4px; border: 1px solid #cececf; color: #cececf; cursor: pointer;" class="ppv_download_bttn ppv-direct-download" data-behavior="' . esc_attr( $behavior ) . '" data-doc-id="' . esc_attr( $data['id'] ) . '">' . $btn_label . '</button></a>';
273 $download_btn_html .= $download_count_html;
274 }
275
276 $has_download_ui = ! empty( $download_btn_html );
277 // Handle Position logic
278 $position = isset( $data['_de_download_position'] ) ? $data['_de_download_position'] : 'above';
279
280 $frame_url = $base_url . $data['doc'];
281 $is_google = isset( $data['googleDrive'] ) && in_array( $data['googleDrive'], ['1', 1, 'true', true, 'yes'], true );
282 if ( $is_google ) {
283 $frame_url = str_replace( "view", "preview", $data['doc'] );
284 }
285 ?>
286 <div class="ppv_container <?php echo esc_attr( $unique_id ); ?>">
287
288 <?php
289 $filename = basename( $data['doc'] );
290 $show_filename_in_toolbar = isset( $data['showName'] ) && $data['showName'];
291
292 // Toolbar rendering
293 if ( $position === 'toolbar' && ( $show_filename_in_toolbar || $has_download_ui ) ) {
294 $justify_content = ! $show_filename_in_toolbar ? 'end' : 'space-between';
295 echo '<div class="ppv-toolbar" style="justify-content: ' . esc_attr( $justify_content ) . '">';
296 if ( $show_filename_in_toolbar ) {
297 echo '<span class="ppv-filename">' . esc_html( $filename ) . '</span>';
298 }
299 if ( $has_download_ui ) {
300 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is pre-built with escaped values
301 echo '<div class="ppv-toolbar-right">' . $download_btn_html . '</div>';
302 }
303 echo '</div>';
304 } elseif ( $has_download_ui && ( $position === 'above' || empty( $position ) ) ) {
305 // If showName is true but not in toolbar position, we still need to show it somewhere if it was removed from above
306 if ( isset( $data['showName'] ) && $data['showName'] ) {
307 echo '<p style="padding-left:10px;">' . esc_html( $filename ) . '</p>';
308 }
309 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is pre-built with escaped values
310 echo '<p style="padding-left:10px;">' . $download_btn_html . '</p>';
311 } elseif ( isset( $data['showName'] ) && $data['showName'] && ( $position === 'above' || empty( $position ) ) ) {
312 echo '<p style="padding-left:10px;">' . esc_html( $filename ) . '</p>';
313 }
314 ?>
315 <div class="ppv-loading">PDF Loading...</div>
316 <div class="document-preview" style="height: inherit; width: inherit;">
317 <iframe style="width: 100%; height: 100%;" src="<?php echo esc_url( $frame_url ); ?>" frameborder="0"></iframe>
318 </div>
319 <?php
320 // Below element
321 if ( $position === 'below' && ( $show_filename_in_toolbar || $has_download_ui ) ) {
322 $justify_content = ! $show_filename_in_toolbar ? 'end' : 'space-between';
323 echo '<div class="ppv-toolbar" style="justify-content: ' . esc_attr( $justify_content ) . '">';
324 if ( $show_filename_in_toolbar ) {
325 echo '<span class="ppv-filename">' . esc_html( $filename ) . '</span>';
326 }
327 if ( $has_download_ui ) {
328 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is pre-built with escaped values
329 echo '<div class="ppv-toolbar-right">' . $download_btn_html . '</div>';
330 }
331 echo '</div>';
332 }
333 ?>
334 </div>
335 <?php
336 }
337 $output = ob_get_clean();
338 $output = apply_filters( 'bplde_shortcode_html', $output, $data );
339 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- backward compatibility hook
340 return apply_filters( 'ppv_shortcode_html', $output, $data );
341 }
342 }
343
344 Shortcode::instance();
345 }
346