PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more / trunk
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more vtrunk
4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / EmbedPress / Gutenberg / FallbackHandler.php
embedpress / EmbedPress / Gutenberg Last commit date
BlockManager.php 3 weeks ago EmbedPressBlockRenderer.php 1 week ago FallbackHandler.php 9 months ago InitBlocks.php 9 months ago
FallbackHandler.php
314 lines
1 <?php
2
3 namespace EmbedPress\Gutenberg;
4
5 // Exit if accessed directly
6 if (!defined('ABSPATH')) {
7 exit;
8 }
9
10 /**
11 * EmbedPress Fallback Handler
12 *
13 * Handles edge cases where migration might fail or content cannot be properly migrated.
14 * Provides graceful fallbacks to ensure content remains functional.
15 */
16 class FallbackHandler
17 {
18 /**
19 * Instance of this class
20 */
21 private static $instance = null;
22
23 /**
24 * Get instance
25 */
26 public static function get_instance()
27 {
28 if (null === self::$instance) {
29 self::$instance = new self();
30 }
31 return self::$instance;
32 }
33
34 /**
35 * Constructor
36 */
37 private function __construct()
38 {
39 // Hook into block rendering to provide fallbacks
40 add_filter('render_block', [$this, 'handle_block_fallback'], 10, 2);
41 add_filter('render_block_data', [$this, 'handle_block_data_fallback'], 10, 1);
42 }
43
44 /**
45 * Handle block rendering fallback
46 */
47 public function handle_block_fallback($block_content, $block)
48 {
49 // Only handle EmbedPress blocks
50 if ($block['blockName'] !== 'embedpress/embedpress') {
51 return $block_content;
52 }
53
54 // If block content is empty or invalid, try to generate fallback
55 if (empty($block_content) || $this->is_invalid_content($block_content)) {
56 return $this->generate_fallback_content($block);
57 }
58
59 return $block_content;
60 }
61
62 /**
63 * Handle block data fallback before rendering
64 */
65 public function handle_block_data_fallback($block)
66 {
67 // Only handle EmbedPress blocks
68 if ($block['blockName'] !== 'embedpress/embedpress') {
69 return $block;
70 }
71
72 // Check if block has corrupted or missing attributes
73 if (!isset($block['attrs']) || !is_array($block['attrs'])) {
74 $block['attrs'] = $this->get_default_attributes();
75 }
76
77 // Validate and fix critical attributes
78 $block['attrs'] = $this->validate_and_fix_attributes($block['attrs']);
79
80 return $block;
81 }
82
83 /**
84 * Check if content is invalid
85 */
86 private function is_invalid_content($content)
87 {
88 // Check for common signs of invalid content
89 $invalid_patterns = [
90 'undefined',
91 'null',
92 '[object Object]',
93 'NaN',
94 'Error:',
95 'Fatal error'
96 ];
97
98 foreach ($invalid_patterns as $pattern) {
99 if (strpos($content, $pattern) !== false) {
100 return true;
101 }
102 }
103
104 // Check if content is just whitespace
105 if (trim($content) === '') {
106 return true;
107 }
108
109 return false;
110 }
111
112 /**
113 * Generate fallback content for failed blocks
114 */
115 private function generate_fallback_content($block)
116 {
117 $attrs = $block['attrs'] ?? [];
118 $url = $attrs['url'] ?? '';
119 $embedHTML = $attrs['embedHTML'] ?? '';
120
121 // Try to use existing embedHTML first
122 if (!empty($embedHTML) && !$this->is_invalid_content($embedHTML)) {
123 return $this->wrap_fallback_content($embedHTML, 'Using cached embed content');
124 }
125
126 // Try to generate new embed from URL
127 if (!empty($url)) {
128 $generated_embed = $this->generate_embed_from_url($url);
129 if ($generated_embed) {
130 return $this->wrap_fallback_content($generated_embed, 'Generated from URL');
131 }
132 }
133
134 // Last resort: show error message with URL
135 return $this->generate_error_fallback($url);
136 }
137
138 /**
139 * Generate embed content from URL
140 */
141 private function generate_embed_from_url($url)
142 {
143 // Use WordPress oEmbed to try to generate content
144 $embed = wp_oembed_get($url);
145
146 if ($embed) {
147 return $embed;
148 }
149
150 return false;
151 }
152
153 /**
154 * Wrap fallback content with indicator
155 */
156 private function wrap_fallback_content($content, $reason = '')
157 {
158 $debug_info = '';
159
160 if (defined('WP_DEBUG') && WP_DEBUG && !empty($reason)) {
161 $debug_info = "<!-- EmbedPress Fallback: {$reason} -->";
162 }
163
164 return $debug_info . '<div class="embedpress-fallback-content">' . $content . '</div>';
165 }
166
167 /**
168 * Generate error fallback
169 */
170 private function generate_error_fallback($url = '')
171 {
172 $message = __('EmbedPress: Content could not be loaded.', 'embedpress');
173
174 if (!empty($url)) {
175 $message .= ' ' . sprintf(__('Original URL: %s', 'embedpress'), esc_url($url));
176 }
177
178 $html = '<div class="embedpress-error-fallback" style="padding: 20px; border: 1px solid #ddd; background: #f9f9f9; text-align: center;">';
179 $html .= '<p>' . esc_html($message) . '</p>';
180
181 if (!empty($url)) {
182 $html .= '<p><a href="' . esc_url($url) . '" target="_blank" rel="noopener">' . __('View Original Content', 'embedpress') . '</a></p>';
183 }
184
185 $html .= '</div>';
186
187 return $html;
188 }
189
190 /**
191 * Get default attributes for fallback
192 */
193 private function get_default_attributes()
194 {
195 return [
196 'url' => '',
197 'embedHTML' => '',
198 'height' => '600',
199 'width' => '600',
200 'customPlayer' => [],
201 'sharePosition' => 'bottom',
202 'isFallback' => true
203 ];
204 }
205
206 /**
207 * Validate and fix attributes
208 */
209 private function validate_and_fix_attributes($attrs)
210 {
211 $defaults = $this->get_default_attributes();
212
213 // Ensure all required attributes exist
214 foreach ($defaults as $key => $default_value) {
215 if (!isset($attrs[$key])) {
216 $attrs[$key] = $default_value;
217 }
218 }
219
220 // Validate URL
221 if (!empty($attrs['url']) && !filter_var($attrs['url'], FILTER_VALIDATE_URL)) {
222 // Try to fix common URL issues
223 $fixed_url = $this->fix_url($attrs['url']);
224 if ($fixed_url) {
225 $attrs['url'] = $fixed_url;
226 } else {
227 // If URL is completely invalid, clear it
228 $attrs['url'] = '';
229 }
230 }
231
232 // Validate dimensions
233 $attrs['height'] = $this->validate_dimension($attrs['height'], '600');
234 $attrs['width'] = $this->validate_dimension($attrs['width'], '600');
235
236 // Validate customPlayer object
237 if (!is_array($attrs['customPlayer'])) {
238 $attrs['customPlayer'] = [];
239 }
240
241 return $attrs;
242 }
243
244 /**
245 * Fix common URL issues
246 */
247 private function fix_url($url)
248 {
249 // Add protocol if missing
250 if (!preg_match('/^https?:\/\//', $url)) {
251 $url = 'https://' . $url;
252 }
253
254 // Validate the fixed URL
255 if (filter_var($url, FILTER_VALIDATE_URL)) {
256 return $url;
257 }
258
259 return false;
260 }
261
262 /**
263 * Validate dimension values
264 */
265 private function validate_dimension($value, $default = '600')
266 {
267 // If it's a valid number or number with px/%, return as is
268 if (is_numeric($value) || preg_match('/^\d+(px|%)?$/', $value)) {
269 return $value;
270 }
271
272 return $default;
273 }
274
275 /**
276 * Log fallback usage for debugging
277 */
278 private function log_fallback_usage($type, $details = [])
279 {
280 if (defined('WP_DEBUG') && WP_DEBUG) {
281 $log_message = "EmbedPress Fallback Used: {$type}";
282
283 if (!empty($details)) {
284 $log_message .= ' - ' . json_encode($details);
285 }
286
287 }
288 }
289
290 /**
291 * Check if fallback is needed for a specific block
292 */
293 public function is_fallback_needed($block)
294 {
295 if ($block['blockName'] !== 'embedpress/embedpress') {
296 return false;
297 }
298
299 $attrs = $block['attrs'] ?? [];
300
301 // Check for missing critical data
302 if (empty($attrs['url']) && empty($attrs['embedHTML'])) {
303 return true;
304 }
305
306 // Check for corrupted attributes
307 if (!is_array($attrs)) {
308 return true;
309 }
310
311 return false;
312 }
313 }
314