PluginProbe
Open Graph / 1.11.1
Open Graph v1.11.1
trunk 1.1 1.10.0 1.11.0 1.11.1 1.11.2 1.11.3 1.12.0 1.12.1 1.12.2 1.2 1.3 1.4 1.5 1.5.1 1.6 1.7.0 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 2.0.0 2.0.1 2.0.2
opengraph / opengraph.php

opengraph.php in Open Graph 1.11.1, at opengraph.php

606 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Open Graph
4 * Plugin URI: https://wordpress.org/plugins/opengraph
5 * Description: Adds Open Graph metadata to your pages
6 * Author: Will Norris
7 * Author URI: https://willnorris.com/
8 * Version: 1.11.1
9 * License: Apache License, Version 2.0
10 * License URI: http://www.apache.org/licenses/LICENSE-2.0.html
11 * Text Domain: opengraph
12 */
13
14
15 // If you have the opengraph plugin running alongside jetpack, we assume you'd
16 // rather use our opengraph support, so disable jetpack's opengraph functionality.
17 add_filter( 'jetpack_enable_opengraph', '__return_false' );
18 add_filter( 'jetpack_enable_open_graph', '__return_false' );
19
20
21 // Disable strict mode by default.
22 if ( ! defined( 'OPENGRAPH_STRICT_MODE' ) ) {
23 define( 'OPENGRAPH_STRICT_MODE', false );
24 }
25
26
27 /**
28 * Add Open Graph XML prefix to <html> element.
29 *
30 * @uses apply_filters calls 'opengraph_prefixes' filter on RDFa prefix array
31 */
32 function opengraph_add_prefix( $output ) {
33 $prefixes = array(
34 'og' => 'http://ogp.me/ns#',
35 );
36 $prefixes = apply_filters( 'opengraph_prefixes', $prefixes );
37
38 $prefix_str = '';
39 foreach ( $prefixes as $k => $v ) {
40 $prefix_str .= $k . ': ' . $v . ' ';
41 }
42 $prefix_str = trim( $prefix_str );
43
44 if ( preg_match( '/(prefix\s*=\s*[\"|\'])/i', $output ) ) {
45 $output = preg_replace( '/(prefix\s*=\s*[\"|\'])/i', '${1}' . $prefix_str, $output );
46 } else {
47 $output .= ' prefix="' . esc_attr( $prefix_str ) . '"';
48 }
49
50 return $output;
51 }
52 add_filter( 'language_attributes', 'opengraph_add_prefix' );
53
54
55 /**
56 * Add additional prefix namespaces that are supported by the opengraph plugin.
57 */
58 function opengraph_additional_prefixes( $prefixes ) {
59 if ( is_author() ) {
60 $prefixes['profile'] = 'http://ogp.me/ns/profile#';
61 }
62 if ( is_singular() ) {
63 $prefixes['article'] = 'http://ogp.me/ns/article#';
64 }
65
66 return $prefixes;
67 }
68
69
70 /**
71 * Get the Open Graph metadata for the current page.
72 *
73 * @uses apply_filters() Calls 'opengraph_{$name}' for each property name
74 * @uses apply_filters() Calls 'twitter_{$name}' for each property name
75 * @uses apply_filters() Calls 'opengraph_metadata' before returning metadata array
76 */
77 function opengraph_metadata() {
78 $metadata = array();
79
80 // default properties defined at http://ogp.me/
81 $properties = array(
82 // required
83 'title',
84 'type',
85 'image',
86 'url',
87
88 // optional
89 'audio',
90 'description',
91 'determiner',
92 'locale',
93 'site_name',
94 'video',
95 );
96
97 foreach ( $properties as $property ) {
98 $filter = 'opengraph_' . $property;
99
100 $metadata[ "og:$property" ] = apply_filters( $filter, '' );
101 }
102
103 $twitter_properties = array( 'card', 'creator' );
104
105 foreach ( $twitter_properties as $property ) {
106 $filter = 'twitter_' . $property;
107
108 $metadata[ "twitter:$property" ] = apply_filters( $filter, '' );
109 }
110
111 return apply_filters( 'opengraph_metadata', $metadata );
112 }
113
114
115 /**
116 * Register filters for default Open Graph metadata.
117 */
118 function opengraph_default_metadata() {
119 // core metadata attributes
120 add_filter( 'opengraph_title', 'opengraph_default_title', 5 );
121 add_filter( 'opengraph_type', 'opengraph_default_type', 5 );
122 add_filter( 'opengraph_image', 'opengraph_default_image', 5 );
123 add_filter( 'opengraph_url', 'opengraph_default_url', 5 );
124
125 add_filter( 'opengraph_description', 'opengraph_default_description', 5 );
126 add_filter( 'opengraph_locale', 'opengraph_default_locale', 5 );
127 add_filter( 'opengraph_site_name', 'opengraph_default_sitename', 5 );
128 add_filter( 'opengraph_audio', 'opengraph_default_audio', 5 );
129 add_filter( 'opengraph_video', 'opengraph_default_video', 5 );
130
131 // additional prefixes
132 add_filter( 'opengraph_prefixes', 'opengraph_additional_prefixes' );
133
134 // additional profile metadata
135 add_filter( 'opengraph_metadata', 'opengraph_profile_metadata' );
136
137 // additional article metadata
138 add_filter( 'opengraph_metadata', 'opengraph_article_metadata' );
139
140 // twitter card metadata
141 add_filter( 'twitter_card', 'twitter_default_card', 5 );
142 add_filter( 'twitter_creator', 'twitter_default_creator', 5 );
143 }
144 add_action( 'wp', 'opengraph_default_metadata' );
145
146
147 /**
148 * Default title property, using the page title.
149 */
150 function opengraph_default_title( $title ) {
151 if ( $title ) {
152 return $title;
153 }
154
155 // set default title, because twitter is requiring one
156 $title = __( 'Untitled', 'opengraph' );
157
158 if ( is_home() || is_front_page() ) {
159 $title = get_bloginfo( 'name' );
160 } elseif ( is_singular() ) {
161 $title = get_the_title( get_queried_object_id() );
162 // fall back to description
163 if ( empty( $title ) ) {
164 $title = opengraph_default_description( null, 5 );
165 }
166 } elseif ( is_author() ) {
167 $author = get_queried_object();
168 $title = $author->display_name;
169 } elseif ( is_category() && single_cat_title( '', false ) ) {
170 $title = single_cat_title( '', false );
171 } elseif ( is_tag() && single_tag_title( '', false ) ) {
172 $title = single_tag_title( '', false );
173 } elseif ( is_archive() && get_post_format() ) {
174 $title = get_post_format_string( get_post_format() );
175 } elseif ( is_archive() && function_exists( 'get_the_archive_title' ) && get_the_archive_title() ) { // new in version 4.1 to get all other archive titles
176 $title = get_the_archive_title();
177 }
178
179 return esc_attr( $title );
180 }
181
182
183 /**
184 * Default type property.
185 */
186 function opengraph_default_type( $type ) {
187 if ( empty( $type ) ) {
188 if ( is_singular( array( 'post', 'page' ) ) ) {
189 $type = 'article';
190 } elseif ( is_author() ) {
191 $type = 'profile';
192 } else {
193 $type = 'website';
194 }
195 }
196
197 return esc_attr( $type );
198 }
199
200
201 /**
202 * Default image property, using the post-thumbnail and any attached images.
203 */
204 function opengraph_default_image( $image ) {
205 if ( $image ) {
206 return $image;
207 }
208
209 // show avatar on profile pages
210 if ( is_author() ) {
211 return get_avatar_url( get_the_author_meta( 'ID' ), array( 'size' => 512 ) );
212 }
213
214 // As of July 2014, Facebook seems to only let you select from the first 3 images
215 $max_images = apply_filters( 'opengraph_max_images', 3 );
216
217 // max images can't be negative or zero
218 if ( $max_images <= 0 ) {
219 $max_images = 1;
220 }
221
222 if ( is_singular() && ! is_attachment() ) {
223 $id = get_queried_object_id();
224 $image_ids = array();
225
226 // list post thumbnail first if this post has one
227 if ( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail( $id ) ) {
228 $image_ids[] = get_post_thumbnail_id( $id );
229 } else {
230 // otherwise list any image attachments
231 $query = new WP_Query(
232 array(
233 'post_parent' => $id,
234 'post_status' => 'inherit',
235 'post_type' => 'attachment',
236 'post_mime_type' => 'image',
237 'order' => 'ASC',
238 'orderby' => 'menu_order ID',
239 'posts_per_page' => $max_images,
240 )
241 );
242
243 foreach ( $query->get_posts() as $attachment ) {
244 if ( ! in_array( $attachment->ID, $image_ids, true ) ) {
245 $image_ids[] = $attachment->ID;
246 }
247 }
248 }
249
250 // get URLs for each image
251 $image = array();
252 foreach ( $image_ids as $id ) {
253 $thumbnail = wp_get_attachment_image_src( $id, 'full' );
254 if ( $thumbnail ) {
255 $image[] = $thumbnail[0];
256 }
257 }
258 } elseif ( is_attachment() && wp_attachment_is_image() ) {
259 $id = get_queried_object_id();
260 $image = array( wp_get_attachment_url( $id ) );
261 }
262
263 if ( empty( $image ) ) {
264 $image = array();
265
266 // add header images
267 if ( function_exists( 'get_uploaded_header_images' ) ) {
268 if ( is_random_header_image() ) {
269 foreach ( get_uploaded_header_images() as $header_image ) {
270 $image[] = $header_image['url'];
271
272 if ( sizeof( $image ) >= $max_images ) {
273 break;
274 }
275 }
276 } elseif ( get_header_image() ) {
277 $image[] = get_header_image();
278 }
279 }
280
281 // add site icon
282 if ( empty( $image ) && function_exists( 'get_site_icon_url' ) && has_site_icon() ) {
283 $image[] = get_site_icon_url( 512 );
284 }
285 }
286
287 return $image;
288 }
289
290
291 /**
292 * Default audio property, using get_attached_media.
293 */
294 function opengraph_default_audio( $audio ) {
295 $id = get_queried_object_id();
296 $attachments = get_attached_media( 'audio', $id );
297
298 if ( empty( $attachments ) ) {
299 return $audio;
300 }
301
302 if ( empty( $audio ) ) {
303 $audio = array();
304 }
305
306 foreach ( $attachments as $attachment ) {
307 $audio[] = wp_get_attachment_url( $attachment->ID );
308 }
309
310 return $audio;
311 }
312
313
314 /**
315 * Default video property, using get_attached_media.
316 */
317 function opengraph_default_video( $video ) {
318 $id = get_queried_object_id();
319 $attachments = get_attached_media( 'video', $id );
320
321 if ( empty( $attachments ) ) {
322 return $video;
323 }
324
325 if ( empty( $video ) ) {
326 $video = array();
327 }
328
329 foreach ( $attachments as $attachment ) {
330 $video[] = wp_get_attachment_url( $attachment->ID );
331 }
332
333 return $video;
334 }
335
336
337 /**
338 * Default url property, using the permalink for the page.
339 */
340 function opengraph_default_url( $url ) {
341 if ( empty( $url ) ) {
342 if ( is_singular() ) {
343 $url = get_permalink();
344 } elseif ( is_author() ) {
345 $url = get_author_posts_url( get_queried_object_id() );
346 }
347 }
348
349 return esc_url( $url );
350 }
351
352
353 /**
354 * Default site_name property, using the bloginfo name.
355 */
356 function opengraph_default_sitename( $name ) {
357 if ( empty( $name ) ) {
358 $name = get_bloginfo( 'name' );
359 }
360
361 return esc_attr( $name );
362 }
363
364
365 /**
366 * Default description property, using the excerpt or content for posts, or the
367 * bloginfo description.
368 */
369 function opengraph_default_description( $description, $length = 55 ) {
370 if ( $description ) {
371 return $description;
372 }
373
374 if ( is_singular() ) {
375 $post = get_queried_object();
376 if ( ! empty( $post->post_excerpt ) ) {
377 $description = $post->post_excerpt;
378 } else {
379 $description = $post->post_content;
380 }
381 } elseif ( is_author() ) {
382 $id = get_queried_object_id();
383 $description = get_user_meta( $id, 'description', true );
384 } elseif ( is_category() && category_description() ) {
385 $description = category_description();
386 } elseif ( is_tag() && tag_description() ) {
387 $description = tag_description();
388 } elseif ( is_archive() && function_exists( 'get_the_archive_description' ) && get_the_archive_description() ) { // new in version 4.1 to get all other archive descriptions
389 $description = get_the_archive_description();
390 } else {
391 $description = get_bloginfo( 'description' );
392 }
393
394 // strip description to first 55 words.
395 $description = strip_tags( strip_shortcodes( $description ) );
396 $description = opengraph_trim_text( $description, $length );
397
398 return esc_attr( $description );
399 }
400
401
402 /**
403 * Default locale property, using the WordPress locale.
404 */
405 function opengraph_default_locale( $locale ) {
406 if ( empty( $locale ) ) {
407 $locale = get_locale();
408 }
409
410 return $locale;
411 }
412
413
414 /**
415 * Default twitter-card type.
416 */
417 function twitter_default_card( $card ) {
418 if ( $card ) {
419 return $card;
420 }
421
422 $card = 'summary';
423 $images = opengraph_default_image( null );
424
425 // show large image on...
426 if ( is_singular() ) {
427 if (
428 // gallery and image posts
429 in_array( get_post_format(), array( 'image', 'gallery' ), true ) ||
430 // posts with more than one image
431 ( is_array( $images ) && count( $images ) > 1 ) ||
432 // posts with a post-thumbnail
433 ( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail() )
434 ) {
435 $card = 'summary_large_image';
436 }
437 }
438
439 return esc_attr( $card );
440 }
441
442
443 /**
444 * Default twitter-card creator.
445 */
446 function twitter_default_creator( $creator ) {
447 if ( $creator || ! is_singular() ) {
448 return $creator;
449 }
450
451 $post = get_queried_object();
452 $author = $post->post_author;
453 $twitter = get_the_author_meta( 'twitter', $author );
454
455 if ( ! $twitter ) {
456 return $creator;
457 }
458
459 // check if twitter-account matches "http://twitter.com/username"
460 if ( preg_match( '/^http:\/\/twitter\.com\/(#!\/)?(\w+)/i', $twitter, $matches ) ) {
461 $creator = '@' . $matches[2];
462 } elseif ( preg_match( '/^@?(\w+)$/i', $twitter, $matches ) ) { // check if twitter-account matches "(@)username"
463 $creator = '@' . $matches[1];
464 }
465
466 return esc_attr( $creator );
467 }
468
469
470 /**
471 * Output Open Graph <meta> tags in the page header.
472 */
473 function opengraph_meta_tags() {
474 $metadata = opengraph_metadata();
475 foreach ( $metadata as $key => $value ) {
476 if ( empty( $key ) || empty( $value ) ) {
477 continue;
478 }
479 $value = (array) $value;
480
481 foreach ( $value as $v ) {
482 // check if "strict mode" is enabled
483 if ( OPENGRAPH_STRICT_MODE === false ) {
484 // use "property" and "name"
485 printf(
486 '<meta property="%1$s" name="%1$s" content="%2$s" />' . PHP_EOL,
487 esc_attr( $key ),
488 esc_attr( $v )
489 );
490 } else {
491 // use "name" attribute for Twitter Cards
492 if ( stripos( $key, 'twitter:' ) === 0 ) {
493 printf(
494 '<meta name="%1$s" content="%2$s" />' . PHP_EOL,
495 esc_attr( $key ),
496 esc_attr( $v )
497 );
498 } else { // use "property" attribute for Open Graph
499 printf(
500 '<meta property="%1$s" content="%2$s" />' . PHP_EOL,
501 esc_attr( $key ),
502 esc_attr( $v )
503 );
504 }
505 }
506 }
507 }
508 }
509 add_action( 'wp_head', 'opengraph_meta_tags' );
510
511
512 /**
513 * Include profile metadata for author pages.
514 *
515 * @link http://ogp.me/#type_profile
516 */
517 function opengraph_profile_metadata( $metadata ) {
518 if ( is_author() ) {
519 $id = get_queried_object_id();
520
521 $metadata['profile:first_name'] = get_the_author_meta( 'first_name', $id );
522 $metadata['profile:last_name'] = get_the_author_meta( 'last_name', $id );
523 $metadata['profile:username'] = get_the_author_meta( 'nicename', $id );
524 }
525
526 return $metadata;
527 }
528
529
530 /**
531 * Include article metadata for posts and pages.
532 *
533 * @link http://ogp.me/#type_article
534 */
535 function opengraph_article_metadata( $metadata ) {
536 if ( ! is_singular() ) {
537 return $metadata;
538 }
539
540 $post = get_queried_object();
541 $author = $post->post_author;
542
543 // check if page/post has tags
544 $tags = wp_get_object_terms( $post->ID, 'post_tag' );
545 if ( $tags && is_array( $tags ) ) {
546 foreach ( $tags as $tag ) {
547 $metadata['article:tag'][] = $tag->name;
548 }
549 }
550
551 // check if page/post has categories
552 $categories = wp_get_object_terms( $post->ID, 'category' );
553 if ( $categories && is_array( $categories ) ) {
554 $metadata['article:section'][] = current( $categories )->name;
555 }
556
557 $metadata['article:published_time'] = get_the_time( 'c', $post->ID );
558 $metadata['article:modified_time'] = get_the_modified_time( 'c', $post->ID );
559 $metadata['article:author'][] = get_author_posts_url( $author );
560
561 $facebook = get_the_author_meta( 'facebook', $author );
562
563 if ( ! empty( $facebook ) ) {
564 $metadata['article:author'][] = $facebook;
565 }
566
567 return $metadata;
568 }
569
570
571 /**
572 * Add "twitter" as a contact method
573 */
574 function opengraph_user_contactmethods( $user_contactmethods ) {
575 $user_contactmethods['twitter'] = __( 'Twitter', 'opengraph' );
576 $user_contactmethods['facebook'] = __( 'Facebook (Profile URL)', 'opengraph' );
577
578 return $user_contactmethods;
579 }
580 add_filter( 'user_contactmethods', 'opengraph_user_contactmethods', 1 );
581
582
583 /**
584 * Add 512x512 icon size
585 *
586 * @param array $sizes sizes available for the site icon
587 * @return array updated list of icons
588 */
589 function opengraph_site_icon_image_sizes( $sizes ) {
590 $sizes[] = 512;
591
592 return array_unique( $sizes );
593 }
594 add_filter( 'site_icon_image_sizes', 'opengraph_site_icon_image_sizes' );
595
596
597 /**
598 * Helper function to trim text using the same default values for length and
599 * 'more' text as wp_trim_excerpt.
600 */
601 function opengraph_trim_text( $text, $length = 55 ) {
602 $excerpt_length = apply_filters( 'excerpt_length', $length );
603 $excerpt_more = apply_filters( 'excerpt_more', ' [...]' );
604
605 return wp_trim_words( $text, $excerpt_length, $excerpt_more );
606 }