| Server IP : 80.74.154.100 / Your IP : 216.73.217.0 Web Server : Apache System : Linux marissa.metanet.ch 4.18.0-553.141.2.lve.el7h.x86_64 #1 SMP Wed Jul 8 17:20:31 UTC 2026 x86_64 User : onlineadmin ( 10487) PHP Version : 8.5.7 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/httpd/vhosts/comeonline.ch/httpdocs/wp-content/plugins/wpsso/lib/ |
Upload File : |
<?php
/*
* License: GPLv3
* License URI: https://www.gnu.org/licenses/gpl.txt
* Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/)
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'These aren\'t the droids you\'re looking for.' );
}
if ( ! defined( 'WPSSO_PLUGINDIR' ) ) {
die( 'Do. Or do not. There is no try.' );
}
if ( ! class_exists( 'WpssoTwitterCard' ) ) {
class WpssoTwitterCard {
private $p; // Wpsso class object.
public function __construct( &$plugin ) {
$this->p =& $plugin;
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$this->p->util->add_plugin_filters( $this, array(
'plugin_image_sizes' => 1,
) );
}
public function filter_plugin_image_sizes( array $sizes ) {
$sizes[ 'tc_sum' ] = array( // Option prefix.
'name' => 'tc-summary',
'label_transl' => _x( 'X (Twitter) Summary Card', 'option label', 'wpsso' ),
);
$sizes[ 'tc_lrg' ] = array( // Option prefix.
'name' => 'tc-lrgimg',
'label_transl' => _x( 'X (Twitter) Summary Card Large Image', 'option label', 'wpsso' ),
);
return $sizes;
}
/*
* Use reference for $mt_og argument to allow unset of existing twitter meta tags.
*/
public function get_array( array $mod, array $mt_og = array(), $author_id = false ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$mt_tc = apply_filters( 'wpsso_tc_seed', array(), $mod );
/*
* The twitter:domain is used in place of the 'view on web' text.
*/
if ( ! isset( $mt_tc[ 'twitter:domain' ] ) && ! empty( $mt_og[ 'og:url' ] ) ) {
$mt_tc[ 'twitter:domain' ] = preg_replace( '/^.*\/\/([^\/]+).*$/', '$1', $mt_og[ 'og:url' ] );
}
if ( ! isset( $mt_tc[ 'twitter:site' ] ) ) {
$mt_tc[ 'twitter:site' ] = SucomUtilOptions::get_key_value( 'tc_site', $this->p->options, $mod );
}
if ( ! isset( $mt_tc[ 'twitter:title' ] ) ) {
$mt_tc[ 'twitter:title' ] = $this->p->page->get_title( $mod, $md_key = 'tc_title', $max_len = 'tc_title' );
}
if ( ! isset( $mt_tc[ 'twitter:description' ] ) ) {
$mt_tc[ 'twitter:description' ] = $this->p->page->get_description( $mod, $md_key = 'tc_desc', $max_len = 'tc_desc', $num_hashtags = true );
}
if ( ! isset( $mt_tc[ 'twitter:creator' ] ) ) {
if ( $author_id ) {
$mt_tc[ 'twitter:creator' ] = get_the_author_meta( $this->p->options[ 'plugin_cm_twitter_name' ], $author_id );
$mt_tc[ 'twitter:creator' ] = SucomUtil::sanitize_twitter_name( $mt_tc[ 'twitter:creator' ] ); // Just in case.
}
}
/*
* Player video card.
*/
$this->maybe_add_player_card( $mt_tc, $mod, $mt_og, $author_id );
/*
* Post summary or large image summary card.
*/
$this->maybe_add_post_card( $mt_tc, $mod, $mt_og, $author_id );
/*
* Default card.
*/
$this->maybe_add_default_card( $mt_tc, $mod, $mt_og, $author_id );
/*
* Additional article and product data.
*/
$this->maybe_add_extra_data( $mt_tc, $mod, $mt_og, $author_id );
return apply_filters( 'wpsso_tc', $mt_tc, $mod );
}
/*
* $mixed = 'singular' | 'default' | $mod.
*
* Example return:
*
* array(
* 'summary_large_image',
* 'X (Twitter) Summary Card Large Image',
* 'wpsso-tc-lrgimg',
* 'tc_lrg',
* )
*/
public function get_card_info( $mixed, array $head_tags = array(), $use_md_opts = true ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
$card_type = 'summary';
$size_label = '';
$size_name = 'thumbnail'; // Just in case.
$md_pre = '';
if ( ! empty( $head_tags[ 'twitter:card' ] ) ) {
$card_type = $head_tags[ 'twitter:card' ];
} elseif ( is_string( $mixed ) ) { // $mixed is 'singular' or 'default'.
if ( ! empty( $this->p->options[ 'tc_type_' . $mixed ] ) ) {
$card_type = $this->p->options[ 'tc_type_' . $mixed ];
}
} elseif ( is_array( $mixed ) ) { // $mixed is $mod.
/*
* Get the default card type for this post type.
*/
if ( ! empty( $mixed[ 'is_post' ] ) ) {
if ( ! empty( $mixed[ 'post_type' ] ) && is_string( $mixed[ 'post_type' ] ) &&
! empty( $this->p->options[ 'tc_type_for_' . $mixed[ 'post_type' ] ] ) ) {
$card_type = $this->p->options[ 'tc_type_for_' . $mixed[ 'post_type' ] ];
} elseif ( ! empty( $this->p->options[ 'tc_type_singular' ] ) ) {
$card_type = $this->p->options[ 'tc_type_singular' ];
}
}
/*
* Maybe override the default with a custom card type.
*/
if ( ! empty( $mixed[ 'obj' ] ) && $use_md_opts ) {
$md_card_type = $mixed[ 'obj' ]->get_options( $mixed[ 'id' ], 'tc_type' ); // Returns null if index key not found.
if ( ! empty( $md_card_type ) ) {
$card_type = $md_card_type;
}
}
}
switch ( $card_type ) {
case 'app':
$card_label = _x( 'X (Twitter) App Card', 'metabox title', 'wpsso' );
$size_name = '';
$md_pre = 'tc_app';
break;
case 'player':
$card_label = _x( 'X (Twitter) Player Card', 'metabox title', 'wpsso' );
$size_name = '';
$md_pre = 'tc_play';
break;
case 'summary':
$card_label = _x( 'X (Twitter) Summary Card', 'metabox title', 'wpsso' );
$size_name = 'wpsso-tc-summary';
$md_pre = 'tc_sum';
break;
case 'summary_large_image':
$card_label = _x( 'X (Twitter) Summary Card Large Image', 'metabox title', 'wpsso' );
$size_name = 'wpsso-tc-lrgimg';
$md_pre = 'tc_lrg';
break;
}
/*
* Example return:
*
* array(
* 'summary_large_image',
* 'X (Twitter) Summary Card Large Image',
* 'wpsso-tc-lrgimg',
* 'tc_lrg',
* )
*/
$card_info = array( $card_type, $card_label, $size_name, $md_pre );
if ( $this->p->debug->enabled ) {
$this->p->debug->log_arr( 'card_info', $card_info );
}
return $card_info;
}
/*
* Player video card.
*
* The twitter:player:stream meta tags are used for self-hosted MP4 videos. The videos provided by
* YouTube, Vimeo, Wistia, etc. are application/x-shockwave-flash or text/html.
*
* twitter:player:stream
* This is a URL to the video file itself (not a video embed). The video must be an mp4 file. The
* supported codecs within the file are: H.264 video, Baseline Profile Level 3.0, up to 640 x 480 at
* 30 fps and AAC Low Complexity Profile (LC) audio. This property is optional.
*
* twitter:player:stream:content_type
* The MIME type for your video file (video/mp4). This property is only required if you have set a
* twitter:player:stream meta tag.
*/
private function maybe_add_player_card( &$mt_tc, $mod, $mt_og, $author_id ) { // Pass by reference is OK.
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( isset( $mt_tc[ 'twitter:card' ] ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'exiting early: twitter card is set' );
}
return;
}
if ( empty( $mt_og[ 'og:video' ] ) || ! count( $mt_og[ 'og:video' ] ) > 1 ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'exiting early: no videos for player card' );
}
return;
}
foreach ( $mt_og[ 'og:video' ] as $mt_single_video ) {
$player_embed_url = '';
$player_stream_url = '';
/*
* Check for internal meta tag embed_url or stream_url.
*/
if ( ! empty( $mt_single_video[ 'og:video:embed_url' ] ) ) {
$player_embed_url = $mt_single_video[ 'og:video:embed_url' ];
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'player card: embed url = ' . $player_embed_url );
}
}
if ( ! empty( $mt_single_video[ 'og:video:stream_url' ] ) ) {
$player_stream_url = $mt_single_video[ 'og:video:stream_url' ];
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'player card: stream url = ' . $player_stream_url );
}
}
/*
* Check for a video mime-type meta tag.
*/
if ( isset( $mt_single_video[ 'og:video:type' ] ) ) {
switch ( $mt_single_video[ 'og:video:type' ] ) {
/*
* twitter:player
*
* HTTPS URL to iFrame player. This must be a HTTPS URL which does not generate active
* mixed content warnings in a web browser. The audio or video player must not require
* plugins such as Adobe Flash.
*/
case 'text/html':
if ( empty( $player_embed_url ) ) {
$player_embed_url = SucomUtil::get_first_mt_media_url( $mt_single_video, $media_pre = 'og:video' );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'player card: ' . $mt_single_video[ 'og:video:type' ] .
' url = ' . $player_embed_url );
}
}
break;
/*
* twitter:player:stream
*/
case 'video/mp4':
if ( empty( $player_stream_url ) ) {
$player_stream_url = SucomUtil::get_first_mt_media_url( $mt_single_video, $media_pre = 'og:video' );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'player card: ' . $mt_single_video[ 'og:video:type' ] .
' url = ' . $player_stream_url );
}
}
break;
default:
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'player card: video type "' . $mt_single_video[ 'og:video:type' ] . '" is unknown' );
}
break;
}
}
/*
* Set the twitter:player meta tag value(s).
*/
if ( ! empty( $player_embed_url ) ) {
$mt_tc[ 'twitter:card' ] = 'player';
$mt_tc[ 'twitter:player' ] = $player_embed_url;
}
if ( ! empty( $player_stream_url ) ) {
$mt_tc[ 'twitter:card' ] = 'player';
if ( empty( $mt_tc[ 'twitter:player' ] ) ) {
$mt_tc[ 'twitter:player' ] = $player_stream_url; // Fallback to video/mp4.
}
$mt_tc[ 'twitter:player:stream' ] = $player_stream_url;
$mt_tc[ 'twitter:player:stream:content_type' ] = $mt_single_video[ 'og:video:type' ];
}
/*
* Set twitter:player related values (player width, height, mobile apps, etc.)
*/
if ( ! empty( $mt_tc[ 'twitter:card' ] ) ) {
foreach ( array(
'og:video:width' => 'twitter:player:width',
'og:video:height' => 'twitter:player:height',
'og:video:iphone_name' => 'twitter:app:name:iphone',
'og:video:iphone_id' => 'twitter:app:id:iphone',
'og:video:iphone_url' => 'twitter:app:url:iphone',
'og:video:ipad_name' => 'twitter:app:name:ipad',
'og:video:ipad_id' => 'twitter:app:id:ipad',
'og:video:ipad_url' => 'twitter:app:url:ipad',
'og:video:googleplay_name' => 'twitter:app:name:googleplay',
'og:video:googleplay_id' => 'twitter:app:id:googleplay',
'og:video:googleplay_url' => 'twitter:app:url:googleplay',
) as $og_name => $tc_name ) {
if ( ! empty( $mt_single_video[ $og_name ] ) ) {
$mt_tc[ $tc_name ] = $mt_single_video[ $og_name ];
}
}
/*
* Get the video preview image (if one is available).
*/
$mt_tc[ 'twitter:image' ] = SucomUtil::get_first_mt_media_url( $mt_single_video );
if ( ! empty( $mt_single_video[ 'og:image:alt' ] ) ) {
$mt_tc[ 'twitter:image:alt' ] = $mt_single_video[ 'og:image:alt' ];
}
/*
* Fallback to the open graph image.
*/
if ( empty( $mt_tc[ 'twitter:image' ] ) && ! empty( $mt_og[ 'og:image' ] ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'player card: no video image - using og:image instead' );
}
$mt_tc[ 'twitter:image' ] = SucomUtil::get_first_mt_media_url( $mt_og[ 'og:image' ] );
}
}
return; // Use only the first video.
}
}
/*
* Post summary or large image summary card.
*/
private function maybe_add_post_card( &$mt_tc, $mod, $mt_og, $author_id ) { // Pass by reference is OK.
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( isset( $mt_tc[ 'twitter:card' ] ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'exiting early: twitter card is set' );
}
return;
}
if ( empty( $mod[ 'is_post' ] ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'exiting early: module is not post object' );
}
return;
}
list( $card_type, $card_label, $size_name, $md_pre ) = $this->get_card_info( $mod );
/*
* Post image.
*/
if ( $this->p->debug->enabled ) {
$this->p->debug->log( $card_type . ' card: checking for post image (meta, featured, attached)' );
}
$mt_images = $this->p->media->get_post_images( 1, $size_name, $mod[ 'id' ], $md_pre );
if ( count( $mt_images ) > 0 ) {
$mt_single_image = reset( $mt_images );
$image_url = SucomUtil::get_first_mt_media_url( $mt_single_image );
/*
* 'summary_large_image' webpages cannot have the same image URLs, so add the post ID to all
* 'summary_large_image' images.
*/
if ( 'summary_large_image' === $card_type ) {
$image_url = add_query_arg( 'p', $mod[ 'id' ], $image_url );
}
$mt_tc[ 'twitter:card' ] = $card_type;
$mt_tc[ 'twitter:image' ] = $image_url;
if ( ! empty( $mt_single_image[ 'og:image:alt' ] ) ) {
$mt_tc[ 'twitter:image:alt' ] = $mt_single_image[ 'og:image:alt' ];
}
} elseif ( $this->p->debug->enabled ) {
$this->p->debug->log( 'no post image found' );
}
}
/*
* Default card.
*/
private function maybe_add_default_card( &$mt_tc, $mod, $mt_og, $author_id ) { // Pass by reference is OK.
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( isset( $mt_tc[ 'twitter:card' ] ) ) {
if ( $this->p->debug->enabled ) {
$this->p->debug->log( 'exiting early: twitter card is set' );
}
return;
}
list( $card_type, $card_label, $size_name, $md_pre ) = $this->get_card_info( 'default' );
if ( $this->p->debug->enabled ) {
$this->p->debug->log( $card_type . ' card: using default card type' );
}
$mt_tc[ 'twitter:card' ] = $card_type;
if ( $this->p->debug->enabled ) {
$this->p->debug->log( $card_type . ' card: checking other images' );
}
$mt_images = $this->p->media->get_all_images( $num = 1, $size_name, $mod, $md_pre );
if ( count( $mt_images ) > 0 ) {
$mt_single_image = reset( $mt_images );
$image_url = SucomUtil::get_first_mt_media_url( $mt_single_image );
$mt_tc[ 'twitter:image' ] = $image_url;
if ( ! empty( $mt_single_image[ 'og:image:alt' ] ) ) {
$mt_tc[ 'twitter:image:alt' ] = $mt_single_image[ 'og:image:alt' ];
}
} elseif ( $this->p->debug->enabled ) {
$this->p->debug->log( 'no other images found' );
}
}
/*
* Additional article and product data.
*/
private function maybe_add_extra_data( &$mt_tc, $mod, $mt_og, $author_id ) { // Pass by reference is OK.
if ( $this->p->debug->enabled ) {
$this->p->debug->mark();
}
if ( isset( $mt_og[ 'og:type' ] ) ) {
switch ( $mt_og[ 'og:type' ] ) {
case 'article':
if ( ! empty( $mt_og[ 'article:author:name' ] ) ) {
$mt_tc[ 'twitter:label1' ] = __( 'Written by', 'wpsso' );
$mt_tc[ 'twitter:data1' ] = $mt_og[ 'article:author:name' ];
}
if ( ! empty( $mt_og[ 'article:reading_mins' ] ) ) {
$mt_tc[ 'twitter:label2' ] = __( 'Est. reading time', 'wpsso' );
$mt_tc[ 'twitter:data2' ] = $this->p->page->fmt_reading_mins( $mt_og[ 'article:reading_mins' ] );
}
break;
case 'product':
if ( isset( $mt_og[ 'product:price:amount' ] ) && isset( $mt_og[ 'product:price:currency' ] ) ) {
$mt_tc[ 'twitter:label1' ] = __( 'Price', 'wpsso' );
$mt_tc[ 'twitter:data1' ] = $mt_og[ 'product:price:amount' ] . ' ' . $mt_og[ 'product:price:currency' ];
}
if ( isset( $mt_og[ 'product:availability' ] ) ) {
$mt_name = 'product:availability';
$map_key = $mt_og[ $mt_name ];
/*
* Map 'https://schema.org/InStock' to 'in stock', for example.
*/
if ( ! empty( $this->p->cf[ 'head' ][ 'og_content_map' ][ $mt_name ][ $map_key ] ) ) {
$map_key = $this->p->cf[ 'head' ][ 'og_content_map' ][ $mt_name ][ $map_key ];
}
$mt_tc[ 'twitter:label2' ] = __( 'Availability', 'wpsso' );
$mt_tc[ 'twitter:data2' ] = ucwords( $map_key );
}
break;
}
}
}
}
}