PluginProbe
Embed Privacy / trunk
Embed Privacy vtrunk
1.14.0 1.13.0 trunk 0.1 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.10.0 1.10.1 1.10.10 1.10.2 1.10.3 1.10.4 1.10.5 1.10.6 1.10.7 1.10.8 1.10.9 1.11.0 1.11.1 1.11.2 All 68 releases
embed-privacy / inc / integration / class-x.php

class-x.php in Embed Privacy trunk, at inc/integration/class-x.php

114 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace epiphyt\Embed_Privacy\integration;
3
4 use DOMDocument;
5 use DOMElement;
6 use DOMXPath;
7
8 /**
9 * Twitter/X integration for Embed Privacy.
10 *
11 * @author Epiphyt
12 * @license GPL2
13 * @package epiphyt\Embed_Privacy
14 * @since 1.10.5
15 */
16 class X {
17 /**
18 * Initialize functionality.
19 */
20 public static function init() {
21 \add_filter( 'embed_privacy_custom_oembed_replacement', [ self::class, 'set_local_tweet' ], 10, 3 );
22 }
23
24 /**
25 * Transform a tweet into a local one.
26 *
27 * @param string $html Embed code
28 * @return string Local embed
29 */
30 public static function get_local_tweet( $html ) {
31 \libxml_use_internal_errors( true );
32 $dom = new DOMDocument();
33 $dom->loadHTML(
34 '<html><meta charset="utf-8">' . $html . '</html>',
35 \LIBXML_HTML_NOIMPLIED | \LIBXML_HTML_NODEFDTD
36 );
37
38 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
39 // remove script tag
40 foreach ( $dom->getElementsByTagName( 'script' ) as $script ) {
41 $script->parentNode->removeChild( $script );
42 }
43
44 $xpath = new DOMXPath( $dom );
45
46 // get text node, which represents the author name
47 // and give it a span with class
48 foreach ( $xpath->query( '//blockquote/text()' ) as $node ) {
49 $author_node = $dom->createElement( 'span', $node->nodeValue );
50 $author_node->setAttribute( 'class', 'embed-privacy-author-meta' );
51 $node->parentNode->replaceChild( $author_node, $node );
52 }
53
54 // wrap author name by a meta div
55 /** @var \DOMElement $node */
56 foreach ( $dom->getElementsByTagName( 'span' ) as $node ) {
57 if ( $node->getAttribute( 'class' ) !== 'embed-privacy-author-meta' ) {
58 continue;
59 }
60
61 // create meta cite
62 $parent_node = $dom->createElement( 'cite' );
63 $parent_node->setAttribute( 'class', 'embed-privacy-tweet-meta' );
64 // append created cite to blockquote
65 $node->parentNode->appendChild( $parent_node );
66 // move author meta inside meta cite
67 $parent_node->appendChild( $node );
68 }
69
70 /** @var \DOMElement $link */
71 foreach ( $dom->getElementsByTagName( 'a' ) as $link ) {
72 if (
73 ! \preg_match( '/https?:\/\/twitter.com\/([^\/]+)\/status\/(\d+)/', $link->getAttribute( 'href' ) )
74 && ! \preg_match( '/https?:\/\/x.com\/([^\/]+)\/status\/(\d+)/', $link->getAttribute( 'href' ) )
75 ) {
76 continue;
77 }
78
79 // modify date in link to tweet
80 $l10n_date = \wp_date( \get_option( 'date_format' ), \strtotime( $link->nodeValue ) );
81
82 if ( \is_string( $l10n_date ) ) {
83 $link->nodeValue = $l10n_date;
84 }
85
86 // move link inside meta div
87 if ( isset( $parent_node ) && $parent_node instanceof DOMElement ) {
88 $parent_node->appendChild( $link );
89 }
90 }
91
92 $content = $dom->saveHTML( $dom->documentElement );
93 // phpcs:enable
94
95 return \str_replace( [ '<html><meta charset="utf-8">', '</html>' ], [ '<div class="embed-privacy-local-tweet">', '</div>' ], $content );
96 }
97
98 /**
99 * Set local tweets.
100 *
101 * @param string $custom_replacement Current custom replacement
102 * @param string $content The original content
103 * @param \epiphyt\Embed_privacy\embed\Provider $provider Current provider
104 * @return string Original replacement or local tweet
105 */
106 public static function set_local_tweet( $custom_replacement, $content, $provider ) {
107 if ( $provider->is( 'x' ) && \get_option( 'embed_privacy_local_tweets' ) ) {
108 return self::get_local_tweet( $content );
109 }
110
111 return $custom_replacement;
112 }
113 }
114