PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more / 2.4.0
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more v2.4.0
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 / Shortcode.php
embedpress / EmbedPress Last commit date
AMP 7 years ago Ends 6 years ago Includes 6 years ago Plugins 6 years ago Providers 7 years ago ThirdParty 7 years ago AutoLoader.php 7 years ago Compatibility.php 7 years ago Core.php 6 years ago CoreLegacy.php 6 years ago DisablerLegacy.php 7 years ago Loader.php 7 years ago RestAPI.php 6 years ago Shortcode.php 6 years ago index.html 7 years ago
Shortcode.php
608 lines
1 <?php
2
3 namespace EmbedPress;
4
5 use Embera\Embera;
6 use Embera\Formatter;
7
8 (defined('ABSPATH') && defined('EMBEDPRESS_IS_LOADED')) or die("No direct script access allowed.");
9
10 /**
11 * Entity responsible to handle the plugin's shortcode events and behaviors.
12 *
13 * @package EmbedPress
14 * @author EmbedPress <help@embedpress.com>
15 * @copyright Copyright (C) 2018 EmbedPress. All rights reserved.
16 * @license GPLv2 or later
17 * @since 1.0.0
18 */
19 class Shortcode
20 {
21 /**
22 * The WP_oEmbed class instance.
23 *
24 * @since 1.0.0
25 * @access private
26 * @static
27 *
28 * @var string $oEmbedInstance
29 */
30 private static $oEmbedInstance = null;
31
32 /**
33 * Register the plugin's shortcode into WordPress.
34 *
35 * @since 1.0.0
36 * @static
37 *
38 * @return void
39 */
40 public static function register()
41 {
42 // Register the new shortcode for embeds.
43 add_shortcode(EMBEDPRESS_SHORTCODE, ['\\EmbedPress\\Shortcode', 'do_shortcode']);
44 add_shortcode('embed_oembed_html', ['\\EmbedPress\\Shortcode', 'do_shortcode']);
45 }
46
47 /**
48 * Method that converts the plugin shortcoded-string into its complex content.
49 *
50 * @since 1.0.0
51 * @static
52 *
53 * @param array $attributes Array of attributes
54 * @param string $subject The given string
55 *
56 * @return string
57 */
58
59 public static function do_shortcode($attributes = [], $subject = null)
60 {
61 $plgSettings = Core::getSettings();
62 $attributes = wp_parse_args($attributes,[
63 'width' => $plgSettings->enableEmbedResizeWidth,
64 'height' => $plgSettings->enableEmbedResizeHeight
65 ]);
66 $embed = self::parseContent($subject, true, $attributes);
67
68 return is_object($embed) ? $embed->embed : $embed;
69 }
70
71 /**
72 * Replace a given content with its embeded HTML code.
73 *
74 * @since 1.0.0
75 * @static
76 *
77 * @param string The raw content that will be replaced.
78 * @param boolean Optional. If true, new lines at the end of the embeded code are stripped.
79 *
80 * @return string
81 */
82 public static function parseContent($subject, $stripNewLine = false, $customAttributes = [])
83 {
84 if ( ! empty($subject)) {
85 if (empty($customAttributes)) {
86 $customAttributes = self::parseContentAttributesFromString($subject);
87 }
88
89 $content = preg_replace('/(\[' . EMBEDPRESS_SHORTCODE . '(?:\]|.+?\])|\[\/' . EMBEDPRESS_SHORTCODE . '\])/i',
90 "", $subject);
91
92 // Converts any special HTML entities back to characters.
93 $content = htmlspecialchars_decode($content);
94
95 // Check if the WP_oEmbed class is loaded
96 if ( ! self::$oEmbedInstance) {
97 require_once ABSPATH . 'wp-includes/class-wp-oembed.php';
98
99 self::$oEmbedInstance = _wp_oembed_get_object();
100 }
101
102 $emberaInstanceSettings = [
103 'params' => [],
104 ];
105
106 $content_uid = md5($content);
107
108 $attributes = self::parseContentAttributes($customAttributes, $content_uid);
109 if (isset($attributes['width']) || isset($attributes['height'])) {
110 if (isset($attributes['width'])) {
111 $emberaInstanceSettings['params']['width'] = $attributes['width'];
112 unset($attributes['width']);
113 }
114
115 if (isset($attributes['height'])) {
116 $emberaInstanceSettings['params']['height'] = $attributes['height'];
117 unset($attributes['height']);
118 }
119 }
120
121 // Identify what service provider the shortcode's link belongs to
122 $serviceProvider = self::$oEmbedInstance->get_provider($content);
123
124
125 // Check if OEmbed was unable to detect the url service provider.
126 if (empty($serviceProvider)) {
127 // Attempt to do the same using Embera.
128 $emberaInstance = new Embera($emberaInstanceSettings);
129 // Add support to the user's custom service providers
130 $additionalServiceProviders = Core::getAdditionalServiceProviders();
131 if ( ! empty($additionalServiceProviders)) {
132 foreach ($additionalServiceProviders as $serviceProviderClassName => $serviceProviderUrls) {
133 self::addServiceProvider($serviceProviderClassName, $serviceProviderUrls, $emberaInstance);
134 }
135
136 unset($serviceProviderUrls, $serviceProviderClassName);
137 }
138
139 // Attempt to fetch more info about the url-embed.
140 $urlData = $emberaInstance->getUrlInfo($content);
141 } else {
142 // Attempt to fetch more info about the url-embed.
143 $urlData = self::$oEmbedInstance->fetch($serviceProvider, $content, $attributes);
144 }
145
146 // Sanitize the data
147 $urlData = self::sanitizeUrlData($urlData);
148
149 // Stores the original content
150 if (is_object($urlData)) {
151 $urlData->originalContent = $content;
152 }
153
154 $eventResults = apply_filters('embedpress:onBeforeEmbed', $urlData);
155 if (empty($eventResults)) {
156 // EmbedPress seems unable to embed the url.
157 return $subject;
158 }
159
160 // Transform all shortcode attributes into html form. I.e.: {foo: "joe"} -> foo="joe"
161 $attributesHtml = [];
162 foreach ($attributes as $attrName => $attrValue) {
163 $attributesHtml[] = $attrName . '="' . $attrValue . '"';
164 }
165
166 // Define the EmbedPress html template where the generated embed will be injected in
167 $embedTemplate = '<div ' . implode(' ', $attributesHtml) . '>{html}</div>';
168
169 // Check if $content is a google shortened url and tries to extract from it which Google service it refers to.
170 if (preg_match('/http[s]?:\/\/goo\.gl\/(?:([a-z]+)\/)?[a-z0-9]+\/?$/i', $content, $matches)) {
171 // Fetch all headers from the short-url so we can know how to handle its original content depending on the service.
172 $headers = get_headers($content);
173
174 $supportedServicesHeadersPatterns = [
175 'maps' => '/^Location:\s+(http[s]?:\/\/.+)$/i',
176 ];
177
178 $service = isset($matches[1]) ? strtolower($matches[1]) : null;
179 // No specific service was found in the url.
180 if (empty($service)) {
181 // Let's try to guess which service the original url belongs to.
182 foreach ($headers as $header) {
183 // Check if the short-url reffers to a Google Maps url.
184 if (preg_match($supportedServicesHeadersPatterns['maps'], $header, $matches)) {
185 // Replace the shortened url with its original url.
186 $content = $matches[1];
187 break;
188 }
189 }
190 unset($header);
191 } else {
192 // Check if the Google service is supported atm.
193 if (isset($supportedServicesHeadersPatterns[$service])) {
194 // Tries to extract the url based on its headers.
195 $originalUrl = self::extractContentFromHeaderAsArray($supportedServicesHeadersPatterns[$service],
196 $headers);
197 // Replace the shortened url with its original url if the specific header was found.
198 if ( ! empty($originalUrl)) {
199 $content = $originalUrl;
200 }
201 unset($originalUrl);
202 }
203 }
204 unset($service, $supportedServicesHeadersPatterns, $headers, $matches);
205 }
206
207 // Facebook is a special case. WordPress will try to embed them using OEmbed, but they always end up embedding the profile page, regardless
208 // if the url was pointing to a photo, a post, etc. So, since Embera can embed only facebook-media/posts, we'll use it only for that.
209 if (isset($urlData->provider_name) && in_array($urlData->provider_name, ['Facebook'])) {
210 // Check if this is a Facebook profile url.
211 if (preg_match('/facebook\.com\/(?:[^\/]+?)\/?$/', $content, $match)) {
212 // Try to embed the url using WP's OSEmbed.
213 $parsedContent = self::$oEmbedInstance->get_html($content, $attributes);
214 } else {
215 // Try to embed the url using EmbedPress' Embera.
216 $parsedContent = false;
217 }
218 } else {
219 // Try to embed the url using WP's OSEmbed.
220 $parsedContent = self::$oEmbedInstance->get_html($content, $attributes);
221 }
222
223 if ( ! $parsedContent) {
224 if ( ! isset($emberaInstance)) {
225 // If the embed couldn't be generated, we'll try to use Embera's API
226 $emberaInstance = new Embera($emberaInstanceSettings);
227 // Add support to the user's custom service providers
228 $additionalServiceProviders = Core::getAdditionalServiceProviders();
229 if ( ! empty($additionalServiceProviders)) {
230 foreach ($additionalServiceProviders as $serviceProviderClassName => $serviceProviderUrls) {
231 self::addServiceProvider($serviceProviderClassName, $serviceProviderUrls, $emberaInstance);
232 }
233
234 unset($serviceProviderUrls, $serviceProviderClassName);
235 }
236 }
237
238 // Register the html template
239 $emberaFormaterInstance = new Formatter($emberaInstance, true);
240 $emberaFormaterInstance->setTemplate($embedTemplate);
241
242 // Try to generate the embed using Embera API
243 $parsedContent = $emberaFormaterInstance->transform($content);
244
245 unset($emberaFormaterInstance, $additionalServiceProviders, $emberaInstance);
246 } else {
247 // Inject the generated code inside the html template
248 $parsedContent = str_replace('{html}', $parsedContent, $embedTemplate);
249
250 // Replace all single quotes to double quotes. I.e: foo='joe' -> foo="joe"
251 $parsedContent = str_replace("'", '"', $parsedContent);
252
253 // Replace the flag `{provider_alias}` which is used by Embera with the "ose-<serviceProviderAlias>". I.e: YouTube -> "ose-youtube"
254 $parsedContent = preg_replace('/((?:ose-)?\{provider_alias\})/i',
255 "ose-" . strtolower($urlData->provider_name), $parsedContent);
256 }
257
258 if (isset($urlData->provider_name) || (is_array($urlData) && isset($urlData[$content]['provider_name']))) {
259 // NFB seems to always return their embed code with all HTML entities into their applicable characters string.
260 if ((isset($urlData->provider_name) && strtoupper($urlData->provider_name) === "NATIONAL FILM BOARD OF CANADA") || (is_array($urlData) && isset($urlData[$content]['provider_name']) && strtoupper($urlData[$content]['provider_name']) === "NATIONAL FILM BOARD OF CANADA")) {
261 $parsedContent = html_entity_decode($parsedContent);
262 } elseif ((isset($urlData->provider_name) && strtoupper($urlData->provider_name) === "FACEBOOK") || (is_array($urlData) && isset($urlData[$content]['provider_name']) && strtoupper($urlData[$content]['provider_name']) === "FACEBOOK")) {
263 $plgSettings = Core::getSettings();
264
265 // Check if the user wants to force a certain language into Facebook embeds.
266 $locale = isset($plgSettings->fbLanguage) && ! empty($plgSettings->fbLanguage) ? $plgSettings->fbLanguage : false;
267 if ( ! ! $locale) {
268 // Replace the automatically detected language by Facebook's API with the language chosen by the user.
269 $parsedContent = preg_replace('/\/[a-z]{2}\_[a-z]{2}\/sdk\.js/i', "/{$locale}/sdk.js",
270 $parsedContent);
271 }
272
273 // Make sure `adapt_container_width` parameter is set to false. Setting to true, as it is by default, might cause Facebook to render embeds inside editors (in admin) with only 180px wide.
274 if (is_admin()) {
275 $parsedContent = preg_replace('~data\-adapt\-container\-width=\"(?:true|1)\"~i',
276 'data-adapt-container-width="0"', $parsedContent);
277 }
278
279 unset($locale, $plgSettings);
280 }
281 }
282
283 unset($embedTemplate, $serviceProvider);
284
285 // This assure that the iframe has the same dimensions the user wants to
286 if (isset($emberaInstanceSettings['params']['width']) || isset($emberaInstanceSettings['params']['height'])) {
287 if (isset($emberaInstanceSettings['params']['width']) && isset($emberaInstanceSettings['params']['height'])) {
288 $customWidth = (int)$emberaInstanceSettings['params']['width'];
289 $customHeight = (int)$emberaInstanceSettings['params']['height'];
290 } else {
291 if (preg_match('~width="(\d+)"|width\s+:\s+(\d+)~i', $parsedContent, $matches)) {
292 $iframeWidth = (int)$matches[1];
293 }
294
295 if (preg_match('~height="(\d+)"|height\s+:\s+(\d+)~i', $parsedContent, $matches)) {
296 $iframeHeight = (int)$matches[1];
297 }
298
299 if (isset($iframeWidth) && isset($iframeHeight) && $iframeWidth > 0 && $iframeHeight > 0) {
300 $iframeRatio = ceil($iframeWidth / $iframeHeight);
301
302 if (isset($emberaInstanceSettings['params']['width'])) {
303 $customWidth = (int)$emberaInstanceSettings['params']['width'];
304 $customHeight = ceil($customWidth / $iframeRatio);
305 } else {
306 $customHeight = (int)$emberaInstanceSettings['params']['height'];
307 $customWidth = $iframeRatio * $customHeight;
308 }
309 }
310 }
311
312 if (isset($customWidth) && isset($customHeight)) {
313 if (preg_match('~width="(\d+)"~i', $parsedContent)) {
314 $parsedContent = preg_replace('~width="(\d+)"~i', 'width="' . $customWidth . '"',
315 $parsedContent);
316 }
317
318 if (preg_match('~height="(\d+)"~i', $parsedContent)) {
319 $parsedContent = preg_replace('~height="(\d+)"~i', 'height="' . $customHeight . '"',
320 $parsedContent);
321 }
322
323 if (preg_match('~width\s+:\s+(\d+)~i', $parsedContent)) {
324 $parsedContent = preg_replace('~width\s+:\s+(\d+)~i', 'width: ' . $customWidth, $parsedContent);
325 }
326
327 if (preg_match('~height\s+:\s+(\d+)~i', $parsedContent)) {
328 $parsedContent = preg_replace('~height\s+:\s+(\d+)~i', 'height: ' . $customHeight,
329 $parsedContent);
330 }
331 }
332 }
333
334 if ($stripNewLine) {
335 $parsedContent = preg_replace('/\n/', '', $parsedContent);
336 }
337
338 $parsedContent = apply_filters('pp_embed_parsed_content', $parsedContent, $urlData, $attributes);
339
340 if ( ! empty($parsedContent)) {
341 $embed = (object)array_merge((array)$urlData, [
342 'attributes' => (object)$attributes,
343 'embed' => $parsedContent,
344 'url' => $content,
345 ]);
346 $embed = apply_filters('embedpress:onAfterEmbed', $embed);
347 return $embed;
348 }
349 }
350
351 return $subject;
352 }
353
354 /**
355 * Method that adds support to a given new service provider (SP).
356 *
357 * @since 1.0.0
358 * @static
359 *
360 * @param string $className The new SP class name.
361 * @param string $reference The new SP reference name.
362 * @param \Embera\Embera $emberaInstance The embera's instance where the SP will be registered in.
363 *
364 * @return boolean
365 */
366 public static function addServiceProvider($className, $reference, &$emberaInstance)
367 {
368 if (empty($className) || empty($reference)) {
369 return false;
370 }
371
372 if (is_string($reference)) {
373 $emberaInstance->addProvider($reference, EMBEDPRESS_NAMESPACE . "\\Providers\\{$className}");
374 } elseif (is_array($reference)) {
375 foreach ($reference as $serviceProviderUrl) {
376 self::addServiceProvider($className, $serviceProviderUrl, $emberaInstance);
377 }
378 } else {
379 return false;
380 }
381 }
382
383 /**
384 * Method that retrieves all custom parameters from a shortcoded string.
385 *
386 * @since 1.0.0
387 * @static
388 *
389 * @param string $subject The given shortcoded string.
390 *
391 * @return array
392 */
393 public static function parseContentAttributesFromString($subject)
394 {
395 $customAttributes = [];
396 if (preg_match('/\[embed\s*(.*?)\]/i', stripslashes($subject), $m)) {
397 if (preg_match_all('/(\!?\w+-?\w*)(?:="(.+?)")?/i', stripslashes($m[1]), $matches)) {
398 $attributes = $matches[1];
399 $attrValues = $matches[2];
400
401 foreach ($attributes as $attrIndex => $attrName) {
402 $customAttributes[$attrName] = $attrValues[$attrIndex];
403 }
404 }
405 }
406
407 return $customAttributes;
408 }
409
410 /**
411 * Method that parses and adds the "data-" prefix to the given custom shortcode attributes.
412 *
413 * @since 1.0.0
414 * @access private
415 * @static
416 *
417 * @param array $customAttributes The array containing the embed attributes.
418 * @param string $content_uid An optional string specifying a unique ID for the embed
419 *
420 * @return array
421 */
422 private static function parseContentAttributes(array $customAttributes, $content_uid = null)
423 {
424 $attributes = [
425 'class' => ["embedpress-wrapper"],
426 ];
427
428 $embedShouldBeResponsive = true;
429 $embedShouldHaveCustomDimensions = false;
430 if ( ! empty($customAttributes)) {
431 if (isset($customAttributes['class'])) {
432 if ( ! empty($customAttributes['class'])) {
433 $customAttributes['class'] = explode(' ', $customAttributes['class']);
434
435 $attributes['class'] = array_merge($attributes['class'], $customAttributes['class']);
436 }
437
438 unset($customAttributes['class']);
439 }
440
441 if (isset($customAttributes['width'])) {
442 if ( ! empty($customAttributes['width'])) {
443 $attributes['width'] = (int)$customAttributes['width'];
444 $embedShouldHaveCustomDimensions = true;
445 }
446 }
447
448 if (isset($customAttributes['height'])) {
449 if ( ! empty($customAttributes['height'])) {
450 $attributes['height'] = (int)$customAttributes['height'];
451 $embedShouldHaveCustomDimensions = true;
452 }
453 }
454
455 if ( ! empty($customAttributes)) {
456 $attrNameDefaultPrefix = "data-";
457 foreach ($customAttributes as $attrName => $attrValue) {
458 if (is_numeric($attrName)) {
459 $attrName = $attrValue;
460 $attrValue = "";
461 }
462
463 $attrName = str_replace($attrNameDefaultPrefix, "", $attrName);
464
465 if ( ! strlen($attrValue)) {
466 if ($attrName[0] === "!") {
467 $attrValue = "false";
468 $attrName = substr($attrName, 1);
469 } else {
470 $attrValue = "true";
471 }
472 }
473
474 $attributes[$attrNameDefaultPrefix . $attrName] = $attrValue;
475 }
476 }
477
478 // Check if there's any "responsive" parameter
479 $responsiveAttributes = ["responsive", "data-responsive"];
480 foreach ($responsiveAttributes as $responsiveAttr) {
481 if (isset($attributes[$responsiveAttr])) {
482 if ( ! strlen($attributes[$responsiveAttr])) { // If the parameter is passed but have no value, it will be true by default
483 $embedShouldBeResponsive = true;
484 } else {
485 $embedShouldBeResponsive = ! self::valueIsFalse($attributes[$responsiveAttr]);
486 }
487
488 break;
489 }
490 }
491 unset($responsiveAttr, $responsiveAttributes);
492 }
493
494 $attributes['class'][] = 'ose-{provider_alias}';
495
496 if ( ! empty($content_uid)) {
497 $attributes['class'][] = 'ose-uid-' . $content_uid;
498 }
499
500 if ($embedShouldBeResponsive && ! $embedShouldHaveCustomDimensions) {
501 $attributes['class'][] = 'responsive';
502 } else {
503 $attributes['data-responsive'] = "false";
504 }
505
506 $attributes['class'] = implode(' ', array_unique(array_filter($attributes['class'])));
507 if(isset($attributes['width'])){
508 $attributes['style'] = "width:{$attributes['width'] }px;height:{$attributes['height'] }px;";
509 }
510
511 return $attributes;
512 }
513
514 /**
515 * Method that checks if a given value is/can be identified as (bool)false.
516 *
517 * @since 1.0.0
518 * @static
519 *
520 * @param mixed $subject The value to be checked.
521 *
522 * @return boolean
523 */
524 public static function valueIsFalse($subject)
525 {
526 $subject = strtolower(trim((string)$subject));
527 switch ($subject) {
528 case "0":
529 case "false":
530 case "off":
531 case "no":
532 case "n":
533 case "nil":
534 case "null":
535 return true;
536 default:
537 return false;
538 }
539 }
540
541 /**
542 * Return the value from a header which is in an array resulted from a get_headers() call.
543 * If the header cannot be found, this method will return null instead.
544 *
545 * @since 1.1.0
546 * @access private
547 * @static
548 *
549 * @param string $headerPattern Regex pattern the header and its value must match.
550 * @param array $headersList A list of headers resulted from a get_headers() call.
551 *
552 * @return mixed
553 */
554 private static function extractContentFromHeaderAsArray($headerPattern, $headersList)
555 {
556 $headerValue = null;
557
558 foreach ($headersList as $header) {
559 if (preg_match($headerPattern, $header, $matches)) {
560 $headerValue = $matches[1];
561 break;
562 }
563 }
564
565 return $headerValue;
566 }
567
568 /**
569 * Sanitize the object returned by the embed source. Sometimes we need to convert
570 * attributes from "dash" separated to "underline" separated to be able to access
571 * those attributes from the object, without having to convert it to an array.
572 *
573 * @since 1.6.1
574 * @access private
575 * @static
576 *
577 * @param object $data
578 *
579 * @return object
580 */
581 private static function sanitizeUrlData($data)
582 {
583 if (is_object($data)) {
584 $attributes = get_object_vars($data);
585
586 foreach ($attributes as $key => $value) {
587 if (substr_count($key, '-')) {
588 unset($data->$key);
589
590 $key = str_replace('-', '_', $key);
591 $data->$key = $value;
592 }
593 }
594 } elseif (is_array($data)) {
595 foreach ($data as $key => $value) {
596 if (substr_count($key, '-')) {
597 unset($data[$key]);
598
599 $key = str_replace('-', '_', $key);
600 $data[$key] = $value;
601 }
602 }
603 }
604
605 return $data;
606 }
607 }
608