Version Description
Adds profile, list, search, and collection timelines. Upgrade advertising pixel.
Download this release
Release Info
Developer | niallkennedy |
Plugin | |
Version | 2.0.0 |
Comparing to | |
See all releases |
Code changes from version 1.5.0 to 2.0.0
- autoload.php +21 -22
- readme.txt +47 -57
- src/Twitter/Cards/Card.php +6 -6
- src/Twitter/Cards/Components/Account.php +3 -3
- src/Twitter/Cards/Components/Creator.php +1 -1
- src/Twitter/Cards/Components/Description.php +1 -1
- src/Twitter/Cards/Components/Image.php +54 -10
- src/Twitter/Cards/Components/SingleImage.php +14 -7
- src/Twitter/Cards/Summary.php +5 -7
- src/Twitter/Helpers/HTMLBuilder.php +24 -21
- src/Twitter/Helpers/Validators/ScreenName.php +63 -2
- src/Twitter/Helpers/Validators/WebsiteTag.php +121 -0
- src/Twitter/Intents/Traits/Related.php +95 -0
- src/Twitter/Intents/Tweet.php +34 -88
- src/Twitter/Widgets/{BaseWidget.php → Base.php} +8 -8
- src/Twitter/Widgets/{FollowButton.php → Buttons/Follow.php} +15 -15
- src/Twitter/Widgets/{PeriscopeOnAir.php → Buttons/Periscope/OnAir.php} +27 -24
- src/Twitter/Widgets/{TweetButton.php → Buttons/Tweet.php} +17 -15
- src/Twitter/Widgets/Embeds/Moment.php +96 -0
- src/Twitter/Widgets/Embeds/Theme.php +321 -0
- src/Twitter/Widgets/Embeds/Timeline.php +678 -0
- src/Twitter/Widgets/Embeds/Timeline/Collection.php +317 -0
- src/Twitter/Widgets/Embeds/Timeline/Profile.php +192 -0
- src/Twitter/Widgets/Embeds/Timeline/Search.php +358 -0
- src/Twitter/Widgets/Embeds/Timeline/TwitterList.php +199 -0
- src/Twitter/Widgets/Embeds/Tweet.php +344 -0
- src/Twitter/Widgets/Embeds/Tweet/Base.php +215 -0
- src/Twitter/Widgets/Embeds/Tweet/Video.php +84 -0
- src/Twitter/Widgets/Embeds/Vine.php +227 -0
- src/Twitter/Widgets/Language.php +2 -0
- src/Twitter/WordPress/Admin/Post/MetaBox.php +1 -1
- src/Twitter/WordPress/Admin/Post/TweetIntent.php +21 -7
- src/Twitter/WordPress/Admin/Post/TwitterCard.php +18 -11
- src/Twitter/WordPress/Admin/Profile/PeriscopeUser.php +5 -5
- src/Twitter/WordPress/Admin/Profile/User.php +5 -5
- src/Twitter/WordPress/Admin/Settings/{TweetButton.php → Buttons/Tweet.php} +27 -12
- src/Twitter/WordPress/Admin/Settings/{SiteAttribution.php → Cards/SiteAttribution.php} +32 -10
- src/Twitter/WordPress/Admin/Settings/{Theme.php → Embeds/Theme.php} +35 -13
- src/Twitter/WordPress/Admin/Settings/Loader.php +1 -1
- src/Twitter/WordPress/Admin/Settings/SinglePage.php +13 -8
- src/Twitter/WordPress/Cards/Compatibility.php +1 -1
- src/Twitter/WordPress/Cards/Generator.php +21 -17
- src/Twitter/WordPress/Cards/ImageHandler.php +12 -6
- src/Twitter/WordPress/Content/{TweetButton.php → Buttons/Tweet.php} +4 -4
- src/Twitter/WordPress/Features.php +68 -18
- src/Twitter/WordPress/Head/AuthorshipLink.php +6 -1
- src/Twitter/WordPress/Head/CardsMetaElements.php +11 -2
- src/Twitter/WordPress/Head/WidgetsMetaElements.php +2 -3
- src/Twitter/WordPress/Helpers/HTMLBuilder.php +1 -1
- src/Twitter/WordPress/Helpers/TwitterAPI.php +27 -8
- src/Twitter/WordPress/JavaScriptLoaders/AsyncJavaScript.php +45 -8
- src/Twitter/WordPress/JavaScriptLoaders/Tracking.php +34 -35
- src/Twitter/WordPress/JavaScriptLoaders/Widgets.php +3 -2
- src/Twitter/WordPress/PluginLoader.php +51 -26
- src/Twitter/WordPress/Shortcodes/{Tracking.php → Advertising/Tracking.php} +97 -34
- src/Twitter/WordPress/Shortcodes/AuthorContext.php +51 -0
- src/Twitter/WordPress/Shortcodes/Buttons/Follow.php +244 -0
- src/Twitter/WordPress/Shortcodes/{PeriscopeOnAir.php → Buttons/Periscope/OnAir.php} +83 -77
- src/Twitter/WordPress/Shortcodes/{Share.php → Buttons/Share.php} +55 -18
- src/Twitter/WordPress/Shortcodes/EmbeddedTweet.php +0 -434
- src/Twitter/WordPress/Shortcodes/{Moment.php → Embeds/Moment.php} +32 -3
- src/Twitter/WordPress/Shortcodes/Embeds/Timeline.php +347 -0
- src/Twitter/WordPress/Shortcodes/Embeds/Timeline/Collection.php +220 -0
- src/Twitter/WordPress/Shortcodes/Embeds/Timeline/CollectionGrid.php +163 -0
- src/Twitter/WordPress/Shortcodes/Embeds/Timeline/Profile.php +220 -0
- src/Twitter/WordPress/Shortcodes/Embeds/Timeline/Search.php +228 -0
- src/Twitter/WordPress/Shortcodes/Embeds/Timeline/TwitterList.php +218 -0
- src/Twitter/WordPress/Shortcodes/Embeds/Tweet.php +559 -0
- src/Twitter/WordPress/Shortcodes/{EmbeddedTweetVideo.php → Embeds/Tweet/Video.php} +61 -92
- src/Twitter/WordPress/Shortcodes/{Vine.php → Embeds/Vine.php} +104 -51
- src/Twitter/WordPress/Shortcodes/Follow.php +0 -293
- src/Twitter/WordPress/Shortcodes/Helpers/Attributes.php +157 -0
- src/Twitter/WordPress/Shortcodes/OEmbedTrait.php +19 -25
- src/Twitter/WordPress/Shortcodes/PublishOEmbedEndpoint.php +14 -1
- src/Twitter/WordPress/Shortcodes/ShortcodeInterface.php +22 -1
- src/Twitter/WordPress/Shortcodes/TweetGrid.php +0 -288
- src/Twitter/WordPress/Site/Username.php +1 -1
- src/Twitter/WordPress/User/Meta.php +7 -4
- src/Twitter/WordPress/Widgets/Advertising/Tracking.php +181 -0
- src/Twitter/WordPress/Widgets/{Follow.php → Buttons/Follow.php} +67 -27
- src/Twitter/WordPress/Widgets/{PeriscopeOnAir.php → Buttons/Periscope/OnAir.php} +50 -23
- src/Twitter/WordPress/Widgets/Embeds/Timeline.php +222 -0
- src/Twitter/WordPress/Widgets/Embeds/Timeline/Collection.php +128 -0
- src/Twitter/WordPress/Widgets/Embeds/Timeline/Profile.php +128 -0
- src/Twitter/WordPress/Widgets/Embeds/Timeline/Search.php +139 -0
- src/Twitter/WordPress/Widgets/Embeds/Timeline/TwitterList.php +133 -0
- src/Twitter/WordPress/Widgets/Widget.php +52 -0
- src/Twitter/WordPress/Widgets/WidgetInterface.php +86 -0
- twitter.php +2 -2
autoload.php
CHANGED
@@ -37,31 +37,30 @@ THE SOFTWARE.
|
|
37 |
*
|
38 |
* @return void
|
39 |
*/
|
40 |
-
spl_autoload_register(
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
});
|
67 |
-
?>
|
37 |
*
|
38 |
* @return void
|
39 |
*/
|
40 |
+
spl_autoload_register(function ($class) {
|
41 |
+
// project-specific namespace prefix
|
42 |
+
$prefix = 'Twitter\\';
|
43 |
|
44 |
+
// base directory for the namespace prefix
|
45 |
+
$base_dir = defined('TWITTER_PLUGIN_DIR') ? TWITTER_PLUGIN_DIR : __DIR__ . '/src/Twitter/';
|
46 |
|
47 |
+
// does the class use the namespace prefix?
|
48 |
+
$len = strlen($prefix);
|
49 |
+
if (0 !== strncmp($prefix, $class, $len)) {
|
50 |
+
// no, move to the next registered autoloader
|
51 |
+
return;
|
52 |
+
}
|
53 |
|
54 |
+
// get the relative class name
|
55 |
+
$relative_class = substr($class, $len);
|
56 |
|
57 |
+
// replace the namespace prefix with the base directory, replace namespace
|
58 |
+
// separators with directory separators in the relative class name, append
|
59 |
+
// with .php
|
60 |
+
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
61 |
|
62 |
+
// if the file exists, require it
|
63 |
+
if (file_exists($file)) {
|
64 |
+
require $file;
|
65 |
+
}
|
66 |
});
|
|
readme.txt
CHANGED
@@ -1,71 +1,58 @@
|
|
1 |
=== Plugin Name ===
|
2 |
Contributors: Twitter, niallkennedy
|
3 |
-
Tags: twitter, embedded tweet, twitter moment, twitter video, twitter grid, vine, periscope, twitter cards, tweet button, follow button, twitter analytics, twitter ads
|
4 |
-
Requires at least:
|
5 |
Tested up to: 4.7
|
6 |
-
Stable tag:
|
7 |
License: MIT
|
8 |
-
License URI:
|
9 |
|
10 |
-
Official Twitter,
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
All features are deeply integrated with WordPress APIs to make building your webpages and administrative features as easy as possible with the extensibility you expect from WordPress. The plugin is multisite-aware, supports post meta customizations through the WordPress REST API, and shortcode customizations through shortcode UI.
|
17 |
|
18 |
Requires PHP version 5.4 or greater.
|
19 |
|
20 |
= Embed Twitter content =
|
|
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
Embed a Vine by pasting a URL into your article content. Customize advanced options using a shortcode.
|
31 |
-
|
32 |
-
The plugin optimally enqueues Vine's embed JavaScript to handle unpausing and unmuting videos as they become visible on the page.
|
33 |
-
|
34 |
-
= Add a Tweet button to public posts =
|
35 |
-
|
36 |
-
Add a Tweet button to public posts to encourage your visitors to share your content on Twitter. The Tweet button automatically constructs share text, URLs, and shares your site's Twitter account in the Tweet. Visitors may see recommended accounts to follow after posting your content, including your site's specified accounts.
|
37 |
-
|
38 |
-
Customize the pre-populated share text and hashtags shown in a Tweet composer for each post from your site's post editor.
|
39 |
-
|
40 |
-
= Enable link previews and Twitter bylines with Twitter Cards =
|
41 |
|
42 |
-
|
43 |
|
44 |
-
|
45 |
|
46 |
-
|
47 |
|
48 |
-
|
49 |
|
50 |
-
Add a [
|
51 |
|
52 |
-
|
53 |
|
54 |
-
|
55 |
|
56 |
-
=
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
= Add an advertising pixel with a shortcode =
|
61 |
-
|
62 |
-
Add a Twitter audience pixel or [track advertising conversions](https://support.twitter.com/articles/20170807-conversion-tracking-for-websites "Twitter advertising conversion tracking") by adding an advertising pixel through a simple shortcode.
|
63 |
|
64 |
> <strong>Docs and active development</strong><br>
|
65 |
-
>Contribute to the plugin, submit pull requests, or run test suites through the [Twitter plugin for WordPress GitHub repository](https://github.com/twitter/wordpress).
|
66 |
> View [Twitter for WordPress documentation](https://dev.twitter.com/web/wordpress) to learn more about customization through WordPress filters.
|
67 |
|
68 |
== Upgrade Notice ==
|
|
|
|
|
|
|
69 |
= 1.5.0 =
|
70 |
Update admin menu functionality for compatibility with WordPress 4.5+.
|
71 |
|
@@ -85,8 +72,21 @@ Shortcode improvements for ajax-loaded posts. Remove photo, gallery, and product
|
|
85 |
Display admin notice if current PHP version does not meet minimum requirements. Do not display Tweet button in auto-generated excerpt.
|
86 |
|
87 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
= 1.5.0 =
|
89 |
-
* Place Twitter administrative menu as a general menu item, not the deprecated utility menu. WordPress 4.5 compatibility feature
|
90 |
* Use publish.twitter.com oEmbed API endpoint for single Tweet oEmbed
|
91 |
|
92 |
= 1.4.0 =
|
@@ -128,19 +128,13 @@ Display admin notice if current PHP version does not meet minimum requirements.
|
|
128 |
|
129 |
= How can I change an embedded Tweet's background and link colors to match my site's theme? =
|
130 |
|
131 |
-
The Twitter plugin for WordPress includes a settings page with options to
|
132 |
-
|
133 |
-
= How do I include an embedded timeline in my page? =
|
134 |
-
|
135 |
-
Paste a Twitter collection URL into your post content to see a media-rich grid display on your website.
|
136 |
-
|
137 |
-
Log in to Twitter.com and visit the [Twitter widgets settings page](https://twitter.com/settings/widgets) to create and manage user, list, and search [embedded timeline](https://dev.twitter.com/web/embedded-timelines) widgets for your account. Widget settings are saved to a widget identifier for the logged in account; you may want to create a widget from your site's account, not your personal account, for continuity and general organization. Copy-and-paste the HTML generated by the Twitter widgets configuration tool into a new [WordPress text widget](http://codex.wordpress.org/WordPress_Widgets#Using_Text_Widgets).
|
138 |
|
139 |
= My custom link color and border color do not appear in embedded Tweets or timelines =
|
140 |
|
141 |
Your site may have a [Content Security Policy](https://developer.mozilla.org/docs/Web/Security/CSP/Introducing_Content_Security_Policy) blocking Twitter's JavaScript from inserting your custom styling into the widget.
|
142 |
|
143 |
-
You may have configured an embedded timeline widget with a non-default link color. Your widget configuration overrides your page
|
144 |
|
145 |
= Does the Twitter plugin add additional tracking of my site's visitors? =
|
146 |
|
@@ -148,15 +142,11 @@ The Twitter plugin for WordPress makes it easier to explicitly include Twitter f
|
|
148 |
|
149 |
Twitter widgets and buttons load Twitter's widgets.js library through the WordPress JavaScript queue. Read more about [how Twitter for Websites widgets respect user privacy](https://dev.twitter.com/web/overview/privacy).
|
150 |
|
151 |
-
Twitter advertising trackers are only included on the page when invoked by the site using the `twitter_tracking` shortcode. Read more about [Twitter's policies for conversion tracking and tailored audiences products](https://support.twitter.com/articles/20171365
|
152 |
|
153 |
== Screenshots ==
|
154 |
|
155 |
1. Settings screen. Customize Tweet and Timeline color schemes including background, text colors, and borders. Attribute site content to a Twitter account. Automatically include Tweet buttons alongside your post content.
|
156 |
2. Post editor meta box. Define custom Tweet text, hashtags, and Twitter Card data.
|
157 |
-
3. Embed single Tweets,
|
158 |
-
|
159 |
-
== Installation ==
|
160 |
-
|
161 |
-
1. Add the Twitter plugin to your WordPress installation
|
162 |
-
1. Activate the plugin through the 'Plugins' menu in WordPress
|
1 |
=== Plugin Name ===
|
2 |
Contributors: Twitter, niallkennedy
|
3 |
+
Tags: twitter, embedded tweet, embedded timeline, twitter profile, twitter list, twitter moment, twitter video, twitter grid, vine, periscope, twitter cards, tweet button, follow button, twitter analytics, twitter ads
|
4 |
+
Requires at least: 4.1
|
5 |
Tested up to: 4.7
|
6 |
+
Stable tag: 2.0.0
|
7 |
License: MIT
|
8 |
+
License URI: https://opensource.org/licenses/MIT
|
9 |
|
10 |
+
Official Twitter, Periscope, and Vine plugin for WordPress. Embed content and grow your audience. Requires PHP 5.4 or greater.
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
+
Embed Twitter content, improve sharing on Twitter, convert your web audience into Twitter or Periscope subscribers, and easily track visits to your website from Twitter advertising.
|
|
|
|
|
15 |
|
16 |
Requires PHP version 5.4 or greater.
|
17 |
|
18 |
= Embed Twitter content =
|
19 |
+
Embed Twitter content by pasting a URL, customizing a shortcode, or in a widget area.
|
20 |
|
21 |
+
* [single Tweet](https://dev.twitter.com/web/embedded-tweets "single Tweet embed")
|
22 |
+
* [single Tweet with video template](https://dev.twitter.com/web/embedded-video "single Tweet with video embed")
|
23 |
+
* [profile timeline](https://dev.twitter.com/web/embedded-timelines/user "Twitter embedded profile timeline")
|
24 |
+
* [list timeline](https://dev.twitter.com/web/embedded-timelines/list "Twitter embedded list timeline")
|
25 |
+
* [search timeline](https://dev.twitter.com/web/embedded-timelines/search "Twitter embedded search timeline")
|
26 |
+
* [collection](https://dev.twitter.com/web/embedded-timelines/collection "Twitter embedded collection")
|
27 |
+
* [Moment](https://dev.twitter.com/web/embedded-moments "Twitter embedded Moment")
|
28 |
+
* [Vine](https://dev.twitter.com/web/vine "Vine embed")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
+
Customize embed display to match your theme. Choose a light or dark background, customize link and border colors, and customize timeline template components through your site's WordPress administrative interface.
|
31 |
|
32 |
+
The plugin automatically customizes an embed's template text to match the locale of your site, optimally loads Twitter's JavaScript to improve site speed and extensibility, and handles advanced use cases such as articles loaded asynchronously via the WordPress API.
|
33 |
|
34 |
+
= Grow your Twitter audience =
|
35 |
|
36 |
+
Automatically generate link previews for your site's URLs shared on Twitter using [Twitter Cards markup](https://dev.twitter.com/cards/overview) . Easily identify your site and author Twitter accounts through your site and user administrative interfaces.
|
37 |
|
38 |
+
Add a [Tweet button](https://dev.twitter.com/web/tweet-button) to public posts to encourage your visitors to share your content on Twitter. Visitors may see recommended accounts to follow after sharing your content including your site and its authors.
|
39 |
|
40 |
+
Add a [Follow button](https://dev.twitter.com/web/follow-button) to convert your site visitors into Twitter subscribers.
|
41 |
|
42 |
+
Add a [Periscope On Air button](https://www.periscope.tv/embed#on-air-button) to convert your site visitors into Periscope subscribers.
|
43 |
|
44 |
+
= Improve Twitter advertising campaigns =
|
45 |
|
46 |
+
Easily add a Twitter website tag to your website to track the effectiveness and [conversion rates](https://business.twitter.com/en/help/campaign-measurement-and-analytics/conversion-tracking-for-websites.html) of Twitter advertising campaigns or [build tailored audiences](https://business.twitter.com/en/targeting/tailored-audiences.html) to target your Twitter advertisements for your website audience.
|
|
|
|
|
|
|
|
|
47 |
|
48 |
> <strong>Docs and active development</strong><br>
|
49 |
+
> Contribute to the plugin, submit pull requests, or run test suites through the [Twitter plugin for WordPress GitHub repository](https://github.com/twitter/wordpress).
|
50 |
> View [Twitter for WordPress documentation](https://dev.twitter.com/web/wordpress) to learn more about customization through WordPress filters.
|
51 |
|
52 |
== Upgrade Notice ==
|
53 |
+
= 2.0.0 =
|
54 |
+
Adds profile, list, search, and collection timelines. Upgrade advertising pixel.
|
55 |
+
|
56 |
= 1.5.0 =
|
57 |
Update admin menu functionality for compatibility with WordPress 4.5+.
|
58 |
|
72 |
Display admin notice if current PHP version does not meet minimum requirements. Do not display Tweet button in auto-generated excerpt.
|
73 |
|
74 |
== Changelog ==
|
75 |
+
= 2.0.0 =
|
76 |
+
* Embed a [profile timeline](https://dev.twitter.com/web/embedded-timelines/user "Twitter embedded profile timeline"), [list timeline](https://dev.twitter.com/web/embedded-timelines/list "Twitter embedded list timeline"), or [collection](https://dev.twitter.com/web/embedded-timelines/collection "Twitter embedded collection") by pasting a URL, customizing a shortcode, or a widget
|
77 |
+
* Embed a [search timeline](https://dev.twitter.com/web/embedded-timelines/search "Twitter embedded search timeline") by shortcode or widget using a widget ID configured on Twitter.com
|
78 |
+
* Upgrade Twitter advertising tracker to [universal website tag](https://blog.twitter.com/2016/website-conversion-tracking-and-remarketing-made-easier-and-more-flexible "Twitter blog: announcing universal website tag")
|
79 |
+
* Twitter Cards include image alternative text when available
|
80 |
+
* Follow button and Periscope On Air button use post author or site username if no username specified
|
81 |
+
* Improved compatibility with WordPress.com / Jetpack formatting of `tweet` shortcode
|
82 |
+
* Prefer wp_resource_hints API for DNS prefetch in WordPress 4.6+
|
83 |
+
* Update single Tweet with video to remove status customization no longer supported by Twitter
|
84 |
+
* Fix bug when a large featured image is highlighted in a Twitter Card
|
85 |
+
* Describe site username option for WordPress REST API in WordPress 4.7
|
86 |
+
* Bump minimum WordPress version to 4.1
|
87 |
+
|
88 |
= 1.5.0 =
|
89 |
+
* Place Twitter administrative menu as a general menu item, not the deprecated utility menu. WordPress 4.5 compatibility feature
|
90 |
* Use publish.twitter.com oEmbed API endpoint for single Tweet oEmbed
|
91 |
|
92 |
= 1.4.0 =
|
128 |
|
129 |
= How can I change an embedded Tweet's background and link colors to match my site's theme? =
|
130 |
|
131 |
+
The Twitter plugin for WordPress includes a settings page with options to set a light or dark theme and choose a link or border color used in embedded Tweets and timelines.
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
|
133 |
= My custom link color and border color do not appear in embedded Tweets or timelines =
|
134 |
|
135 |
Your site may have a [Content Security Policy](https://developer.mozilla.org/docs/Web/Security/CSP/Introducing_Content_Security_Policy) blocking Twitter's JavaScript from inserting your custom styling into the widget.
|
136 |
|
137 |
+
You may have configured an embedded search timeline widget with a non-default link color. Your stored widget configuration overrides your page or theme’s configuration.
|
138 |
|
139 |
= Does the Twitter plugin add additional tracking of my site's visitors? =
|
140 |
|
142 |
|
143 |
Twitter widgets and buttons load Twitter's widgets.js library through the WordPress JavaScript queue. Read more about [how Twitter for Websites widgets respect user privacy](https://dev.twitter.com/web/overview/privacy).
|
144 |
|
145 |
+
Twitter advertising trackers are only included on the page when invoked by the site using the `twitter_tracking` shortcode or placing the Twitter advertising shortcode in a widget area. Read more about [Twitter's policies for conversion tracking and tailored audiences products](https://support.twitter.com/articles/20171365).
|
146 |
|
147 |
== Screenshots ==
|
148 |
|
149 |
1. Settings screen. Customize Tweet and Timeline color schemes including background, text colors, and borders. Attribute site content to a Twitter account. Automatically include Tweet buttons alongside your post content.
|
150 |
2. Post editor meta box. Define custom Tweet text, hashtags, and Twitter Card data.
|
151 |
+
3. Embed single Tweets, timelines, Twitter Moments, and Vines.
|
152 |
+
4. Embed a Twitter profile, list, collection, Moment, or search result in a theme widget area. Add a Twitter follow button or Periscope on Air button to a theme widget area to increase followers. Easily add advertising conversion tracking through a widget.
|
|
|
|
|
|
|
|
src/Twitter/Cards/Card.php
CHANGED
@@ -104,7 +104,7 @@ class Card
|
|
104 |
*
|
105 |
* @param string $title content title
|
106 |
*
|
107 |
-
* @return
|
108 |
*/
|
109 |
public function setTitle($title)
|
110 |
{
|
@@ -123,7 +123,7 @@ class Card
|
|
123 |
*
|
124 |
* @since 1.0.0
|
125 |
*
|
126 |
-
* @return
|
127 |
*/
|
128 |
public function setSite($site)
|
129 |
{
|
@@ -146,21 +146,21 @@ class Card
|
|
146 |
*/
|
147 |
public function toArray()
|
148 |
{
|
149 |
-
if (! ( isset(
|
150 |
return array();
|
151 |
}
|
152 |
|
153 |
$card = array( 'card' => $this->type );
|
154 |
-
if (isset(
|
155 |
$card['title'] = $this->title;
|
156 |
}
|
157 |
|
158 |
-
if (isset(
|
159 |
$site = $this->site->asCardProperties();
|
160 |
if ($site) {
|
161 |
$card['site'] = $site;
|
162 |
}
|
163 |
-
unset(
|
164 |
}
|
165 |
|
166 |
return $card;
|
104 |
*
|
105 |
* @param string $title content title
|
106 |
*
|
107 |
+
* @return self support chaining
|
108 |
*/
|
109 |
public function setTitle($title)
|
110 |
{
|
123 |
*
|
124 |
* @since 1.0.0
|
125 |
*
|
126 |
+
* @return self support chaining
|
127 |
*/
|
128 |
public function setSite($site)
|
129 |
{
|
146 |
*/
|
147 |
public function toArray()
|
148 |
{
|
149 |
+
if (! ( isset($this->type) && $this->type )) {
|
150 |
return array();
|
151 |
}
|
152 |
|
153 |
$card = array( 'card' => $this->type );
|
154 |
+
if (isset($this->title) && $this->title) {
|
155 |
$card['title'] = $this->title;
|
156 |
}
|
157 |
|
158 |
+
if (isset($this->site) && $this->site) {
|
159 |
$site = $this->site->asCardProperties();
|
160 |
if ($site) {
|
161 |
$card['site'] = $site;
|
162 |
}
|
163 |
+
unset($site);
|
164 |
}
|
165 |
|
166 |
return $card;
|
src/Twitter/Cards/Components/Account.php
CHANGED
@@ -63,7 +63,7 @@ class Account
|
|
63 |
$account->setScreenName($screen_name);
|
64 |
|
65 |
if (! $account->hasScreenName()) {
|
66 |
-
return;
|
67 |
}
|
68 |
|
69 |
return $account;
|
@@ -84,7 +84,7 @@ class Account
|
|
84 |
$account->setID($id);
|
85 |
|
86 |
if (! $account->hasID()) {
|
87 |
-
return;
|
88 |
}
|
89 |
|
90 |
return $account;
|
@@ -135,7 +135,7 @@ class Account
|
|
135 |
*
|
136 |
* @param string $id Twitter user id
|
137 |
*
|
138 |
-
* @return
|
139 |
*/
|
140 |
public function setID($id)
|
141 |
{
|
63 |
$account->setScreenName($screen_name);
|
64 |
|
65 |
if (! $account->hasScreenName()) {
|
66 |
+
return null;
|
67 |
}
|
68 |
|
69 |
return $account;
|
84 |
$account->setID($id);
|
85 |
|
86 |
if (! $account->hasID()) {
|
87 |
+
return null;
|
88 |
}
|
89 |
|
90 |
return $account;
|
135 |
*
|
136 |
* @param string $id Twitter user id
|
137 |
*
|
138 |
+
* @return self support chaining
|
139 |
*/
|
140 |
public function setID($id)
|
141 |
{
|
src/Twitter/Cards/Components/Creator.php
CHANGED
@@ -46,7 +46,7 @@ trait Creator
|
|
46 |
*
|
47 |
* @param \Twitter\Cards\Components\Account $creator Twitter account
|
48 |
*
|
49 |
-
* @return
|
50 |
*/
|
51 |
public function setCreator($creator)
|
52 |
{
|
46 |
*
|
47 |
* @param \Twitter\Cards\Components\Account $creator Twitter account
|
48 |
*
|
49 |
+
* @return self support chaining
|
50 |
*/
|
51 |
public function setCreator($creator)
|
52 |
{
|
src/Twitter/Cards/Components/Description.php
CHANGED
@@ -71,7 +71,7 @@ trait Description
|
|
71 |
*
|
72 |
* @param string $description content description
|
73 |
*
|
74 |
-
* @return
|
75 |
*/
|
76 |
public function setDescription($description)
|
77 |
{
|
71 |
*
|
72 |
* @param string $description content description
|
73 |
*
|
74 |
+
* @return self support chaining
|
75 |
*/
|
76 |
public function setDescription($description)
|
77 |
{
|
src/Twitter/Cards/Components/Image.php
CHANGED
@@ -59,10 +59,19 @@ class Image
|
|
59 |
*/
|
60 |
protected $height;
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
/**
|
63 |
* @since 1.0.0
|
64 |
*
|
65 |
-
* @
|
66 |
*/
|
67 |
public function __construct($src)
|
68 |
{
|
@@ -103,7 +112,7 @@ class Image
|
|
103 |
*
|
104 |
* @param int $width width of the image in whole pixels
|
105 |
*
|
106 |
-
* @return
|
107 |
*/
|
108 |
public function setWidth($width)
|
109 |
{
|
@@ -132,7 +141,7 @@ class Image
|
|
132 |
*
|
133 |
* @param int $height
|
134 |
*
|
135 |
-
* @return
|
136 |
*/
|
137 |
public function setHeight($height)
|
138 |
{
|
@@ -142,6 +151,36 @@ class Image
|
|
142 |
return $this;
|
143 |
}
|
144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
/**
|
146 |
* Convert to card properties
|
147 |
*
|
@@ -151,15 +190,20 @@ class Image
|
|
151 |
*/
|
152 |
public function asCardProperties()
|
153 |
{
|
154 |
-
if (! ( isset(
|
155 |
return '';
|
156 |
}
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
163 |
} else {
|
164 |
return $this->src;
|
165 |
}
|
59 |
*/
|
60 |
protected $height;
|
61 |
|
62 |
+
/**
|
63 |
+
* A text description of the image
|
64 |
+
*
|
65 |
+
* @since 2.0.0
|
66 |
+
*
|
67 |
+
* @type string
|
68 |
+
*/
|
69 |
+
protected $alt;
|
70 |
+
|
71 |
/**
|
72 |
* @since 1.0.0
|
73 |
*
|
74 |
+
* @param string $src image URL
|
75 |
*/
|
76 |
public function __construct($src)
|
77 |
{
|
112 |
*
|
113 |
* @param int $width width of the image in whole pixels
|
114 |
*
|
115 |
+
* @return self support chaining
|
116 |
*/
|
117 |
public function setWidth($width)
|
118 |
{
|
141 |
*
|
142 |
* @param int $height
|
143 |
*
|
144 |
+
* @return self support chaining
|
145 |
*/
|
146 |
public function setHeight($height)
|
147 |
{
|
151 |
return $this;
|
152 |
}
|
153 |
|
154 |
+
/**
|
155 |
+
* Get a text description of the image
|
156 |
+
*
|
157 |
+
* @since 2.0.0
|
158 |
+
*
|
159 |
+
* @return string a text description of the image
|
160 |
+
*/
|
161 |
+
public function getAlternativeText()
|
162 |
+
{
|
163 |
+
return $this->alt ?: '';
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Set a text description of the image
|
168 |
+
*
|
169 |
+
* @since 2.0.0
|
170 |
+
*
|
171 |
+
* @return self support chaining
|
172 |
+
*/
|
173 |
+
public function setAlternativeText($alt)
|
174 |
+
{
|
175 |
+
if (is_string($alt)) {
|
176 |
+
$alt = trim($alt);
|
177 |
+
if ($alt) {
|
178 |
+
$this->alt = $alt;
|
179 |
+
}
|
180 |
+
}
|
181 |
+
return $this;
|
182 |
+
}
|
183 |
+
|
184 |
/**
|
185 |
* Convert to card properties
|
186 |
*
|
190 |
*/
|
191 |
public function asCardProperties()
|
192 |
{
|
193 |
+
if (! ( isset($this->src) && $this->src )) {
|
194 |
return '';
|
195 |
}
|
196 |
+
$properties = array(
|
197 |
+
'src' => $this->src
|
198 |
+
);
|
199 |
+
$has_properties = false;
|
200 |
+
if (isset($this->alt)) {
|
201 |
+
$properties['alt'] = $this->alt;
|
202 |
+
$has_properties = true;
|
203 |
+
}
|
204 |
+
|
205 |
+
if ($has_properties) {
|
206 |
+
return $properties;
|
207 |
} else {
|
208 |
return $this->src;
|
209 |
}
|
src/Twitter/Cards/Components/SingleImage.php
CHANGED
@@ -51,9 +51,9 @@ trait SingleImage
|
|
51 |
* @param int $width width of the image in whole pixels
|
52 |
* @param int $height height of the image in whole pixels
|
53 |
*
|
54 |
-
* @return
|
55 |
*/
|
56 |
-
public function setImage($url, $width = 0, $height = 0)
|
57 |
{
|
58 |
if (! $url) {
|
59 |
return $this;
|
@@ -64,6 +64,9 @@ trait SingleImage
|
|
64 |
if (! ( is_int($height) && $height >= 0 )) {
|
65 |
$height = 0;
|
66 |
}
|
|
|
|
|
|
|
67 |
|
68 |
$image = null;
|
69 |
$preset = false;
|
@@ -72,10 +75,11 @@ trait SingleImage
|
|
72 |
$image = $url;
|
73 |
$width = $url->getWidth();
|
74 |
$height = $url->getHeight();
|
|
|
75 |
} elseif (is_string($url)) {
|
76 |
try {
|
77 |
$image = new \Twitter\Cards\Components\Image($url);
|
78 |
-
} catch (Exception $e) {
|
79 |
return $this;
|
80 |
}
|
81 |
}
|
@@ -104,6 +108,9 @@ trait SingleImage
|
|
104 |
}
|
105 |
}
|
106 |
}
|
|
|
|
|
|
|
107 |
|
108 |
$this->image = $image;
|
109 |
|
@@ -127,13 +134,13 @@ trait SingleImage
|
|
127 |
*/
|
128 |
protected function imageCardProperties()
|
129 |
{
|
130 |
-
if (! isset(
|
131 |
-
return
|
132 |
}
|
133 |
|
134 |
$card_properties = $this->image->asCardProperties();
|
135 |
-
if (empty(
|
136 |
-
return
|
137 |
}
|
138 |
|
139 |
return $card_properties;
|
51 |
* @param int $width width of the image in whole pixels
|
52 |
* @param int $height height of the image in whole pixels
|
53 |
*
|
54 |
+
* @return self support chaining
|
55 |
*/
|
56 |
+
public function setImage($url, $width = 0, $height = 0, $alt = '')
|
57 |
{
|
58 |
if (! $url) {
|
59 |
return $this;
|
64 |
if (! ( is_int($height) && $height >= 0 )) {
|
65 |
$height = 0;
|
66 |
}
|
67 |
+
if (! is_string($alt)) {
|
68 |
+
$alt = '';
|
69 |
+
}
|
70 |
|
71 |
$image = null;
|
72 |
$preset = false;
|
75 |
$image = $url;
|
76 |
$width = $url->getWidth();
|
77 |
$height = $url->getHeight();
|
78 |
+
$alt = $url->getAlternativeText();
|
79 |
} elseif (is_string($url)) {
|
80 |
try {
|
81 |
$image = new \Twitter\Cards\Components\Image($url);
|
82 |
+
} catch (\Exception $e) {
|
83 |
return $this;
|
84 |
}
|
85 |
}
|
108 |
}
|
109 |
}
|
110 |
}
|
111 |
+
if (is_string($alt) && $alt) {
|
112 |
+
$image->setAlternativeText($alt);
|
113 |
+
}
|
114 |
|
115 |
$this->image = $image;
|
116 |
|
134 |
*/
|
135 |
protected function imageCardProperties()
|
136 |
{
|
137 |
+
if (! isset($this->image)) {
|
138 |
+
return array();
|
139 |
}
|
140 |
|
141 |
$card_properties = $this->image->asCardProperties();
|
142 |
+
if (empty($card_properties)) {
|
143 |
+
return array();
|
144 |
}
|
145 |
|
146 |
return $card_properties;
|
src/Twitter/Cards/Summary.php
CHANGED
@@ -69,8 +69,6 @@ class Summary extends Card
|
|
69 |
* Set the card type
|
70 |
*
|
71 |
* @since 1.0.0
|
72 |
-
*
|
73 |
-
* @return void
|
74 |
*/
|
75 |
public function __construct()
|
76 |
{
|
@@ -91,22 +89,22 @@ class Summary extends Card
|
|
91 |
{
|
92 |
$card = parent::toArray();
|
93 |
|
94 |
-
if (isset(
|
95 |
$card['description'] = $this->description;
|
96 |
}
|
97 |
|
98 |
$image_properties = $this->imageCardProperties();
|
99 |
-
if (! empty(
|
100 |
$card['image'] = $image_properties;
|
101 |
}
|
102 |
-
unset(
|
103 |
|
104 |
-
if (isset(
|
105 |
$creator = $this->creator->asCardProperties();
|
106 |
if ($creator) {
|
107 |
$card['creator'] = $creator;
|
108 |
}
|
109 |
-
unset(
|
110 |
}
|
111 |
|
112 |
return $card;
|
69 |
* Set the card type
|
70 |
*
|
71 |
* @since 1.0.0
|
|
|
|
|
72 |
*/
|
73 |
public function __construct()
|
74 |
{
|
89 |
{
|
90 |
$card = parent::toArray();
|
91 |
|
92 |
+
if (isset($this->description) && $this->description) {
|
93 |
$card['description'] = $this->description;
|
94 |
}
|
95 |
|
96 |
$image_properties = $this->imageCardProperties();
|
97 |
+
if (! empty($image_properties)) {
|
98 |
$card['image'] = $image_properties;
|
99 |
}
|
100 |
+
unset($image_properties);
|
101 |
|
102 |
+
if (isset($this->creator) && $this->creator) {
|
103 |
$creator = $this->creator->asCardProperties();
|
104 |
if ($creator) {
|
105 |
$card['creator'] = $creator;
|
106 |
}
|
107 |
+
unset($creator);
|
108 |
}
|
109 |
|
110 |
return $card;
|
src/Twitter/Helpers/HTMLBuilder.php
CHANGED
@@ -40,7 +40,7 @@ class HTMLBuilder
|
|
40 |
*
|
41 |
* @param string $class possible HTML class
|
42 |
*
|
43 |
-
* @return class name stripped of invalid values or empty string
|
44 |
*/
|
45 |
public static function escapeClassName($class)
|
46 |
{
|
@@ -109,82 +109,85 @@ class HTMLBuilder
|
|
109 |
|
110 |
$clean_attributes = array();
|
111 |
|
112 |
-
if (is_array($attributes) && ! empty(
|
113 |
// string
|
114 |
-
if (isset(
|
115 |
$id = static::escapeAttributeValue(trim($attributes['id']));
|
116 |
if ($id) {
|
117 |
$clean_attributes['id'] = $id;
|
118 |
}
|
119 |
-
unset(
|
120 |
}
|
121 |
|
122 |
// accept array of values to be combined
|
123 |
$tokens = array( 'class', 'rel' );
|
124 |
foreach ($tokens as $attribute) {
|
125 |
-
if (! isset(
|
126 |
continue;
|
127 |
}
|
128 |
|
129 |
$attribute_tokens = array();
|
130 |
if (is_array($attributes[ $attribute ])) {
|
131 |
-
if (! empty(
|
132 |
$cleaned_tokens = array_filter(array_map('trim', $attributes[ $attribute ]));
|
133 |
-
if (! empty(
|
134 |
$attribute_tokens = $cleaned_tokens;
|
135 |
}
|
136 |
-
unset(
|
137 |
}
|
138 |
} elseif (is_string($attributes[ $attribute ])) {
|
139 |
$cleaned_token = trim($attributes[ $attribute ]);
|
140 |
if ($cleaned_token) {
|
141 |
$attribute_tokens = explode(' ', $cleaned_token);
|
142 |
}
|
143 |
-
unset(
|
144 |
}
|
145 |
|
146 |
// filter and store
|
147 |
-
if (! empty(
|
148 |
$attribute_tokens = array_map(
|
149 |
-
|
150 |
$attribute_tokens
|
151 |
);
|
152 |
-
if (! empty(
|
153 |
$clean_attributes[ $attribute ] = implode(' ', $attribute_tokens);
|
154 |
}
|
155 |
}
|
156 |
-
unset(
|
157 |
}
|
158 |
-
unset(
|
159 |
|
160 |
// URL
|
161 |
-
if (isset(
|
162 |
$ping = static::escapeURL(trim($attributes['ping']));
|
163 |
if ($ping) {
|
164 |
$clean_attributes['ping'] = $ping;
|
165 |
}
|
166 |
-
unset(
|
167 |
}
|
168 |
|
169 |
// enum
|
170 |
-
if (isset(
|
171 |
$target = trim('target');
|
172 |
if ($target) {
|
173 |
$valid_targets = array( '_blank' => true, '_self' => true, '_parent' => true, '_top' => true );
|
174 |
-
if (isset(
|
175 |
$clean_attributes['target'] = $target;
|
176 |
}
|
177 |
-
unset(
|
178 |
}
|
179 |
-
unset(
|
180 |
}
|
181 |
}
|
182 |
|
183 |
-
if (is_array($data_attributes) && ! empty(
|
184 |
foreach ($data_attributes as $attribute => $value) {
|
185 |
if (! $attribute) {
|
186 |
continue;
|
187 |
}
|
|
|
|
|
|
|
188 |
|
189 |
$clean_attributes[ 'data-' . $attribute ] = static::escapeAttributeValue(trim($value));
|
190 |
}
|
40 |
*
|
41 |
* @param string $class possible HTML class
|
42 |
*
|
43 |
+
* @return string class name stripped of invalid values or empty string
|
44 |
*/
|
45 |
public static function escapeClassName($class)
|
46 |
{
|
109 |
|
110 |
$clean_attributes = array();
|
111 |
|
112 |
+
if (is_array($attributes) && ! empty($attributes)) {
|
113 |
// string
|
114 |
+
if (isset($attributes['id'])) {
|
115 |
$id = static::escapeAttributeValue(trim($attributes['id']));
|
116 |
if ($id) {
|
117 |
$clean_attributes['id'] = $id;
|
118 |
}
|
119 |
+
unset($id);
|
120 |
}
|
121 |
|
122 |
// accept array of values to be combined
|
123 |
$tokens = array( 'class', 'rel' );
|
124 |
foreach ($tokens as $attribute) {
|
125 |
+
if (! isset($attributes[ $attribute ])) {
|
126 |
continue;
|
127 |
}
|
128 |
|
129 |
$attribute_tokens = array();
|
130 |
if (is_array($attributes[ $attribute ])) {
|
131 |
+
if (! empty($attributes[ $attribute ])) {
|
132 |
$cleaned_tokens = array_filter(array_map('trim', $attributes[ $attribute ]));
|
133 |
+
if (! empty($cleaned_tokens)) {
|
134 |
$attribute_tokens = $cleaned_tokens;
|
135 |
}
|
136 |
+
unset($cleaned_tokens);
|
137 |
}
|
138 |
} elseif (is_string($attributes[ $attribute ])) {
|
139 |
$cleaned_token = trim($attributes[ $attribute ]);
|
140 |
if ($cleaned_token) {
|
141 |
$attribute_tokens = explode(' ', $cleaned_token);
|
142 |
}
|
143 |
+
unset($cleaned_token);
|
144 |
}
|
145 |
|
146 |
// filter and store
|
147 |
+
if (! empty($attribute_tokens)) {
|
148 |
$attribute_tokens = array_map(
|
149 |
+
get_called_class() . '::' . ( $attribute === 'class' ? 'escapeClassName' : 'escapeAttribute' ),
|
150 |
$attribute_tokens
|
151 |
);
|
152 |
+
if (! empty($attribute_tokens)) {
|
153 |
$clean_attributes[ $attribute ] = implode(' ', $attribute_tokens);
|
154 |
}
|
155 |
}
|
156 |
+
unset($attribute_tokens);
|
157 |
}
|
158 |
+
unset($tokens);
|
159 |
|
160 |
// URL
|
161 |
+
if (isset($attributes['ping'])) {
|
162 |
$ping = static::escapeURL(trim($attributes['ping']));
|
163 |
if ($ping) {
|
164 |
$clean_attributes['ping'] = $ping;
|
165 |
}
|
166 |
+
unset($ping);
|
167 |
}
|
168 |
|
169 |
// enum
|
170 |
+
if (isset($attributes['target'])) {
|
171 |
$target = trim('target');
|
172 |
if ($target) {
|
173 |
$valid_targets = array( '_blank' => true, '_self' => true, '_parent' => true, '_top' => true );
|
174 |
+
if (isset($valid_targets[ $target ])) {
|
175 |
$clean_attributes['target'] = $target;
|
176 |
}
|
177 |
+
unset($valid_targets);
|
178 |
}
|
179 |
+
unset($target);
|
180 |
}
|
181 |
}
|
182 |
|
183 |
+
if (is_array($data_attributes) && ! empty($data_attributes)) {
|
184 |
foreach ($data_attributes as $attribute => $value) {
|
185 |
if (! $attribute) {
|
186 |
continue;
|
187 |
}
|
188 |
+
if (is_array($value)) {
|
189 |
+
$value = implode(' ', $value);
|
190 |
+
}
|
191 |
|
192 |
$clean_attributes[ 'data-' . $attribute ] = static::escapeAttributeValue(trim($value));
|
193 |
}
|
src/Twitter/Helpers/Validators/ScreenName.php
CHANGED
@@ -32,6 +32,67 @@ namespace Twitter\Helpers\Validators;
|
|
32 |
*/
|
33 |
class ScreenName
|
34 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
/**
|
36 |
* Remove possible '@' from beginning of a Twitter screen_name
|
37 |
*
|
@@ -43,7 +104,7 @@ class ScreenName
|
|
43 |
*/
|
44 |
public static function trim($screen_name)
|
45 |
{
|
46 |
-
return ltrim(trim($screen_name),
|
47 |
}
|
48 |
|
49 |
/**
|
@@ -59,7 +120,7 @@ class ScreenName
|
|
59 |
*/
|
60 |
public static function isValid($screen_name)
|
61 |
{
|
62 |
-
return (bool) preg_match(
|
63 |
}
|
64 |
|
65 |
/**
|
32 |
*/
|
33 |
class ScreenName
|
34 |
{
|
35 |
+
/**
|
36 |
+
* Unicode characters possibly preceding a Twitter username in common citation syntax
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @link https://github.com/twitter/twitter-text/blob/master/java/src/com/twitter/Regex.java Twitter Text AT_SIGNS_CHARS
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const AT_SIGNS = '@@';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Characters allowed in a Twitter username
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @link https://github.com/twitter/twitter-text/blob/master/java/src/com/twitter/Regex.java Twitter Text VALID_REPLY
|
52 |
+
*
|
53 |
+
* @type string
|
54 |
+
*/
|
55 |
+
const ALLOWED_CHARACTERS = 'a-zA-Z0-9_';
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Maximum allowed length of a Twitter username
|
59 |
+
*
|
60 |
+
* @since 2.0.0
|
61 |
+
*
|
62 |
+
* @link https://github.com/twitter/twitter-text/blob/master/java/src/com/twitter/Regex.java Twitter Text VALID_REPLY
|
63 |
+
*
|
64 |
+
* @type int
|
65 |
+
*/
|
66 |
+
const MAX_LENGTH = 20;
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Combine allowed characters and max length into a pattern suitable for use in HTML form validation or inside a regex matcher
|
70 |
+
*
|
71 |
+
* @since 2.0.0
|
72 |
+
*
|
73 |
+
* @link https://tc39.github.io/ecma262/#prod-Pattern JavaScript pattern production
|
74 |
+
*
|
75 |
+
* @return string pattern string
|
76 |
+
*/
|
77 |
+
public static function getPattern()
|
78 |
+
{
|
79 |
+
return '[' . static::ALLOWED_CHARACTERS . ']{1,' . static::MAX_LENGTH . '}';
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Get a PCRE pattern suitable for use in a matcher
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @link http://php.net/manual/en/pcre.pattern.php PHP PCRE pattern
|
88 |
+
*
|
89 |
+
* @return string PCRE pattern
|
90 |
+
*/
|
91 |
+
public static function getRegexPattern()
|
92 |
+
{
|
93 |
+
return '/^' . static::getPattern() . '$/';
|
94 |
+
}
|
95 |
+
|
96 |
/**
|
97 |
* Remove possible '@' from beginning of a Twitter screen_name
|
98 |
*
|
104 |
*/
|
105 |
public static function trim($screen_name)
|
106 |
{
|
107 |
+
return ltrim(trim($screen_name), static::AT_SIGNS);
|
108 |
}
|
109 |
|
110 |
/**
|
120 |
*/
|
121 |
public static function isValid($screen_name)
|
122 |
{
|
123 |
+
return (bool) preg_match(static::getRegexPattern(), $screen_name);
|
124 |
}
|
125 |
|
126 |
/**
|
src/Twitter/Helpers/Validators/WebsiteTag.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2015 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Helpers\Validators;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Test for Twitter screen_name validity
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
*/
|
33 |
+
class WebsiteTag
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Characters allowed in a Twitter website tag
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const ALLOWED_CHARACTERS = 'a-zA-Z0-9';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Maximum allowed length of a Twitter website tag
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type int
|
50 |
+
*/
|
51 |
+
const MAX_LENGTH = 5;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Combine allowed characters and max length into a pattern suitable for use in HTML form validation or inside a regex matcher
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @link https://tc39.github.io/ecma262/#prod-Pattern JavaScript pattern production
|
59 |
+
*
|
60 |
+
* @return string pattern string
|
61 |
+
*/
|
62 |
+
public static function getPattern()
|
63 |
+
{
|
64 |
+
return '[' . static::ALLOWED_CHARACTERS . ']{1,' . static::MAX_LENGTH . '}';
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Get a PCRE pattern suitable for use in a matcher
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*
|
72 |
+
* @link http://php.net/manual/en/pcre.pattern.php PHP PCRE pattern
|
73 |
+
*
|
74 |
+
* @return string PCRE pattern
|
75 |
+
*/
|
76 |
+
public static function getRegexPattern()
|
77 |
+
{
|
78 |
+
return '/^' . static::getPattern() . '$/';
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Tests a supplied Twitter website tag for validity
|
83 |
+
*
|
84 |
+
* @since 2.0.0
|
85 |
+
*
|
86 |
+
* @param string $website_tag Twitter website tag
|
87 |
+
*
|
88 |
+
* @return bool true if valid Twitter website tag
|
89 |
+
*/
|
90 |
+
public static function isValid($website_tag)
|
91 |
+
{
|
92 |
+
return (bool) preg_match(static::getRegexPattern(), $website_tag);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Sanitize a user-inputted Twitter website tag value
|
97 |
+
*
|
98 |
+
* @since 2.0.0
|
99 |
+
*
|
100 |
+
* @param string $website_tag Twitter website tag
|
101 |
+
*
|
102 |
+
* @return string Twitter website tag or empty string if invalid website provided
|
103 |
+
*/
|
104 |
+
public static function sanitize($website_tag)
|
105 |
+
{
|
106 |
+
if (! is_string($website_tag)) {
|
107 |
+
return '';
|
108 |
+
}
|
109 |
+
|
110 |
+
$website_tag = strtolower(trim($website_tag));
|
111 |
+
if ( ! $website_tag ) {
|
112 |
+
return '';
|
113 |
+
}
|
114 |
+
|
115 |
+
if (! static::isValid($website_tag)) {
|
116 |
+
return '';
|
117 |
+
}
|
118 |
+
|
119 |
+
return $website_tag;
|
120 |
+
}
|
121 |
+
}
|
src/Twitter/Intents/Traits/Related.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2015 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Intents\Traits;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Accounts related to web intent
|
30 |
+
*
|
31 |
+
* May be used to suggest accounts to follow after completing an action
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
trait Related
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Related Twitter usernames
|
39 |
+
*
|
40 |
+
* May be presented as a suggested account to follow after the Tweet is published
|
41 |
+
*
|
42 |
+
* @since 2.0.0
|
43 |
+
*
|
44 |
+
* @type array {
|
45 |
+
* @type string username in lowercase
|
46 |
+
* @type string description of how the username relates to Tweet content
|
47 |
+
* }
|
48 |
+
*/
|
49 |
+
protected $related = array();
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Add a related Twitter account
|
53 |
+
*
|
54 |
+
* @since 2.0.0
|
55 |
+
*
|
56 |
+
* @param string $username Twitter username
|
57 |
+
* @param string $label brief description of how the account relates to the Tweet content
|
58 |
+
*
|
59 |
+
* @return self support chaining
|
60 |
+
*/
|
61 |
+
public function addRelated($username, $label = '')
|
62 |
+
{
|
63 |
+
$username = \Twitter\Helpers\Validators\ScreenName::trim($username);
|
64 |
+
if ($username) {
|
65 |
+
// normalize passed parameter
|
66 |
+
$comparison_username = strtolower($username);
|
67 |
+
if (! isset($this->related[ $comparison_username ])) {
|
68 |
+
if (property_exists(get_called_class(), 'validate_inputs') && $this->validate_inputs) {
|
69 |
+
if (\Twitter\Helpers\Validators\ScreenName::isValid($username)) {
|
70 |
+
$this->related[ $comparison_username ] = trim($label);
|
71 |
+
}
|
72 |
+
} else {
|
73 |
+
$this->related[ $comparison_username ] = trim($label);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
return $this;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get related Twitter usernames
|
83 |
+
*
|
84 |
+
* @since 2.0.0
|
85 |
+
*
|
86 |
+
* @return array {
|
87 |
+
* @type string username in lowercase
|
88 |
+
* @type string description of how the username relates to Tweet content
|
89 |
+
* }
|
90 |
+
*/
|
91 |
+
public function getRelated()
|
92 |
+
{
|
93 |
+
return $this->related;
|
94 |
+
}
|
95 |
+
}
|
src/Twitter/Intents/Tweet.php
CHANGED
@@ -34,6 +34,7 @@ namespace Twitter\Intents;
|
|
34 |
*/
|
35 |
class Tweet
|
36 |
{
|
|
|
37 |
|
38 |
/**
|
39 |
* Tweet Web Intent URL
|
@@ -101,20 +102,6 @@ class Tweet
|
|
101 |
*/
|
102 |
protected $via;
|
103 |
|
104 |
-
/**
|
105 |
-
* Related Twitter usernames
|
106 |
-
*
|
107 |
-
* May be presented as a suggested account to follow after the Tweet is published
|
108 |
-
*
|
109 |
-
* @since 1.0.0
|
110 |
-
*
|
111 |
-
* @type array {
|
112 |
-
* @type string username in lowercase
|
113 |
-
* @type string description of how the username relates to Tweet content
|
114 |
-
* }
|
115 |
-
*/
|
116 |
-
protected $related = array();
|
117 |
-
|
118 |
/**
|
119 |
* Do not validate inputs
|
120 |
*
|
@@ -122,7 +109,7 @@ class Tweet
|
|
122 |
*
|
123 |
* @since 1.0.0
|
124 |
*
|
125 |
-
* @return
|
126 |
*/
|
127 |
public function disableValidation()
|
128 |
{
|
@@ -135,7 +122,7 @@ class Tweet
|
|
135 |
*
|
136 |
* @since 1.0.0
|
137 |
*
|
138 |
-
* @return
|
139 |
*/
|
140 |
public function enableValidation()
|
141 |
{
|
@@ -162,7 +149,7 @@ class Tweet
|
|
162 |
*
|
163 |
* @param string $tweet_id Parent Tweet ID
|
164 |
*
|
165 |
-
* @return
|
166 |
*/
|
167 |
public function setInReplyTo($tweet_id)
|
168 |
{
|
@@ -181,7 +168,7 @@ class Tweet
|
|
181 |
*
|
182 |
* @param string $text Tweet text
|
183 |
*
|
184 |
-
* @return
|
185 |
*/
|
186 |
public function setText($text)
|
187 |
{
|
@@ -228,7 +215,7 @@ class Tweet
|
|
228 |
*
|
229 |
* @param string $url absolute URL
|
230 |
*
|
231 |
-
* @return
|
232 |
*/
|
233 |
public function setURL($url)
|
234 |
{
|
@@ -253,14 +240,18 @@ class Tweet
|
|
253 |
*
|
254 |
* @param string $hashtag hashtag
|
255 |
*
|
256 |
-
* @return
|
257 |
*/
|
258 |
public function addHashtag($hashtag)
|
259 |
{
|
260 |
$hashtag = \Twitter\Helpers\Validators\Hashtag::trim($hashtag);
|
261 |
if ($hashtag) {
|
262 |
-
|
263 |
-
|
|
|
|
|
|
|
|
|
264 |
$this->hashtags[ $comparison_hashtag ] = $hashtag;
|
265 |
}
|
266 |
}
|
@@ -301,7 +292,7 @@ class Tweet
|
|
301 |
*
|
302 |
* @param string $username Twitter username
|
303 |
*
|
304 |
-
* @return
|
305 |
*/
|
306 |
public function setVia($username)
|
307 |
{
|
@@ -319,51 +310,6 @@ class Tweet
|
|
319 |
return $this;
|
320 |
}
|
321 |
|
322 |
-
/**
|
323 |
-
* Add a related Twitter account
|
324 |
-
*
|
325 |
-
* @since 1.0.0
|
326 |
-
*
|
327 |
-
* @param string $username Twitter username
|
328 |
-
* @param string $label brief description of how the account relates to the Tweet content
|
329 |
-
*
|
330 |
-
* @return __CLASS__ support chaining
|
331 |
-
*/
|
332 |
-
public function addRelated($username, $label = '')
|
333 |
-
{
|
334 |
-
$username = \Twitter\Helpers\Validators\ScreenName::trim($username);
|
335 |
-
if ($username) {
|
336 |
-
// normalize passed parameter
|
337 |
-
$comparison_username = strtolower($username);
|
338 |
-
if (! isset( $this->related[ $comparison_username ] )) {
|
339 |
-
if ($this->validate_inputs) {
|
340 |
-
if (\Twitter\Helpers\Validators\ScreenName::isValid($username)) {
|
341 |
-
$this->related[ $comparison_username ] = trim($label);
|
342 |
-
}
|
343 |
-
} else {
|
344 |
-
$this->related[ $comparison_username ] = trim($label);
|
345 |
-
}
|
346 |
-
}
|
347 |
-
}
|
348 |
-
|
349 |
-
return $this;
|
350 |
-
}
|
351 |
-
|
352 |
-
/**
|
353 |
-
* Get related Twitter usernames
|
354 |
-
*
|
355 |
-
* @since 1.0.0
|
356 |
-
*
|
357 |
-
* @return array {
|
358 |
-
* @type string username in lowercase
|
359 |
-
* @type string description of how the username relates to Tweet content
|
360 |
-
* }
|
361 |
-
*/
|
362 |
-
public function getRelated()
|
363 |
-
{
|
364 |
-
return $this->related;
|
365 |
-
}
|
366 |
-
|
367 |
/**
|
368 |
* Construct a new Tweet intent object from an options array
|
369 |
*
|
@@ -374,7 +320,7 @@ class Tweet
|
|
374 |
* @type string|int|bool option value
|
375 |
* }
|
376 |
*
|
377 |
-
* @return
|
378 |
*/
|
379 |
public static function fromArray($values)
|
380 |
{
|
@@ -384,9 +330,9 @@ class Tweet
|
|
384 |
|
385 |
$class = get_called_class();
|
386 |
$intent = new $class;
|
387 |
-
unset(
|
388 |
|
389 |
-
if (isset(
|
390 |
if (false == $values['validate'] || 'false' === $values['validate'] || 0 == $values['validate']) {
|
391 |
$intent->disableValidation();
|
392 |
}
|
@@ -396,16 +342,16 @@ class Tweet
|
|
396 |
$values = array_filter($values);
|
397 |
|
398 |
// intent parameters
|
399 |
-
if (isset(
|
400 |
$intent->setInReplyTo($values['in_reply_to']);
|
401 |
}
|
402 |
-
if (isset(
|
403 |
$intent->setText($values['text']);
|
404 |
}
|
405 |
-
if (isset(
|
406 |
$intent->setURL($values['url']);
|
407 |
}
|
408 |
-
if (isset(
|
409 |
$hashtags = array();
|
410 |
|
411 |
if (is_array($values['hashtags'])) {
|
@@ -414,16 +360,16 @@ class Tweet
|
|
414 |
$hashtags = explode(',', $values['hashtags']);
|
415 |
}
|
416 |
|
417 |
-
if (! empty(
|
418 |
array_walk($hashtags, array( $intent, 'addHashtag' ));
|
419 |
}
|
420 |
|
421 |
-
unset(
|
422 |
}
|
423 |
-
if (isset(
|
424 |
$intent->setVia($values['via']);
|
425 |
}
|
426 |
-
if (isset(
|
427 |
$related = array();
|
428 |
|
429 |
if (is_array($values['related'])) {
|
@@ -433,12 +379,12 @@ class Tweet
|
|
433 |
foreach ($related_accounts as $related_account) {
|
434 |
// extract the label
|
435 |
$account_pieces = explode(':', $related_account, 2);
|
436 |
-
$related[ $account_pieces[0] ] = ( isset(
|
437 |
-
unset(
|
438 |
}
|
439 |
}
|
440 |
|
441 |
-
if (! empty(
|
442 |
foreach ($related as $username => $label) {
|
443 |
if (! ( is_string($username) && $username )) {
|
444 |
continue;
|
@@ -448,7 +394,7 @@ class Tweet
|
|
448 |
}
|
449 |
}
|
450 |
|
451 |
-
unset(
|
452 |
}
|
453 |
|
454 |
return $intent;
|
@@ -479,16 +425,16 @@ class Tweet
|
|
479 |
}
|
480 |
|
481 |
$hashtags = $this->getHashtags();
|
482 |
-
if (! empty(
|
483 |
$data['hashtags'] = implode(',', $hashtags);
|
484 |
}
|
485 |
-
unset(
|
486 |
|
487 |
if ($this->via) {
|
488 |
$data['via'] = $this->via;
|
489 |
}
|
490 |
|
491 |
-
if (! empty(
|
492 |
$related_value = array();
|
493 |
foreach ($this->related as $username => $label) {
|
494 |
if ($label) {
|
@@ -498,7 +444,7 @@ class Tweet
|
|
498 |
}
|
499 |
}
|
500 |
$data['related'] = implode(',', $related_value);
|
501 |
-
unset(
|
502 |
}
|
503 |
|
504 |
return $data;
|
@@ -515,7 +461,7 @@ class Tweet
|
|
515 |
{
|
516 |
$query_parameters = $this->toQueryParameters();
|
517 |
|
518 |
-
if (! empty(
|
519 |
return self::INTENT_URL . '?' . http_build_query($query_parameters, '', '&', PHP_QUERY_RFC3986);
|
520 |
}
|
521 |
|
34 |
*/
|
35 |
class Tweet
|
36 |
{
|
37 |
+
use \Twitter\Intents\Traits\Related;
|
38 |
|
39 |
/**
|
40 |
* Tweet Web Intent URL
|
102 |
*/
|
103 |
protected $via;
|
104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
/**
|
106 |
* Do not validate inputs
|
107 |
*
|
109 |
*
|
110 |
* @since 1.0.0
|
111 |
*
|
112 |
+
* @return self support chaining
|
113 |
*/
|
114 |
public function disableValidation()
|
115 |
{
|
122 |
*
|
123 |
* @since 1.0.0
|
124 |
*
|
125 |
+
* @return self support chaining
|
126 |
*/
|
127 |
public function enableValidation()
|
128 |
{
|
149 |
*
|
150 |
* @param string $tweet_id Parent Tweet ID
|
151 |
*
|
152 |
+
* @return self support chaining
|
153 |
*/
|
154 |
public function setInReplyTo($tweet_id)
|
155 |
{
|
168 |
*
|
169 |
* @param string $text Tweet text
|
170 |
*
|
171 |
+
* @return self support chaining
|
172 |
*/
|
173 |
public function setText($text)
|
174 |
{
|
215 |
*
|
216 |
* @param string $url absolute URL
|
217 |
*
|
218 |
+
* @return self support chaining
|
219 |
*/
|
220 |
public function setURL($url)
|
221 |
{
|
240 |
*
|
241 |
* @param string $hashtag hashtag
|
242 |
*
|
243 |
+
* @return self support chaining
|
244 |
*/
|
245 |
public function addHashtag($hashtag)
|
246 |
{
|
247 |
$hashtag = \Twitter\Helpers\Validators\Hashtag::trim($hashtag);
|
248 |
if ($hashtag) {
|
249 |
+
if (function_exists('mb_strtolower')) {
|
250 |
+
$comparison_hashtag = mb_strtolower($hashtag);
|
251 |
+
} else {
|
252 |
+
$comparison_hashtag = strtolower($hashtag);
|
253 |
+
}
|
254 |
+
if (! isset($this->hashtags[ $comparison_hashtag ])) {
|
255 |
$this->hashtags[ $comparison_hashtag ] = $hashtag;
|
256 |
}
|
257 |
}
|
292 |
*
|
293 |
* @param string $username Twitter username
|
294 |
*
|
295 |
+
* @return self support chaining
|
296 |
*/
|
297 |
public function setVia($username)
|
298 |
{
|
310 |
return $this;
|
311 |
}
|
312 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
313 |
/**
|
314 |
* Construct a new Tweet intent object from an options array
|
315 |
*
|
320 |
* @type string|int|bool option value
|
321 |
* }
|
322 |
*
|
323 |
+
* @return self object initialized based on passed array values
|
324 |
*/
|
325 |
public static function fromArray($values)
|
326 |
{
|
330 |
|
331 |
$class = get_called_class();
|
332 |
$intent = new $class;
|
333 |
+
unset($class);
|
334 |
|
335 |
+
if (isset($values['validate'])) {
|
336 |
if (false == $values['validate'] || 'false' === $values['validate'] || 0 == $values['validate']) {
|
337 |
$intent->disableValidation();
|
338 |
}
|
342 |
$values = array_filter($values);
|
343 |
|
344 |
// intent parameters
|
345 |
+
if (isset($values['in_reply_to'])) {
|
346 |
$intent->setInReplyTo($values['in_reply_to']);
|
347 |
}
|
348 |
+
if (isset($values['text'])) {
|
349 |
$intent->setText($values['text']);
|
350 |
}
|
351 |
+
if (isset($values['url'])) {
|
352 |
$intent->setURL($values['url']);
|
353 |
}
|
354 |
+
if (isset($values['hashtags'])) {
|
355 |
$hashtags = array();
|
356 |
|
357 |
if (is_array($values['hashtags'])) {
|
360 |
$hashtags = explode(',', $values['hashtags']);
|
361 |
}
|
362 |
|
363 |
+
if (! empty($hashtags)) {
|
364 |
array_walk($hashtags, array( $intent, 'addHashtag' ));
|
365 |
}
|
366 |
|
367 |
+
unset($hashtags);
|
368 |
}
|
369 |
+
if (isset($values['via'])) {
|
370 |
$intent->setVia($values['via']);
|
371 |
}
|
372 |
+
if (isset($values['related'])) {
|
373 |
$related = array();
|
374 |
|
375 |
if (is_array($values['related'])) {
|
379 |
foreach ($related_accounts as $related_account) {
|
380 |
// extract the label
|
381 |
$account_pieces = explode(':', $related_account, 2);
|
382 |
+
$related[ $account_pieces[0] ] = ( isset($account_pieces[1]) ? rawurldecode($account_pieces[1]) : '' );
|
383 |
+
unset($account_pieces);
|
384 |
}
|
385 |
}
|
386 |
|
387 |
+
if (! empty($related)) {
|
388 |
foreach ($related as $username => $label) {
|
389 |
if (! ( is_string($username) && $username )) {
|
390 |
continue;
|
394 |
}
|
395 |
}
|
396 |
|
397 |
+
unset($related);
|
398 |
}
|
399 |
|
400 |
return $intent;
|
425 |
}
|
426 |
|
427 |
$hashtags = $this->getHashtags();
|
428 |
+
if (! empty($hashtags)) {
|
429 |
$data['hashtags'] = implode(',', $hashtags);
|
430 |
}
|
431 |
+
unset($hashtags);
|
432 |
|
433 |
if ($this->via) {
|
434 |
$data['via'] = $this->via;
|
435 |
}
|
436 |
|
437 |
+
if (! empty($this->related)) {
|
438 |
$related_value = array();
|
439 |
foreach ($this->related as $username => $label) {
|
440 |
if ($label) {
|
444 |
}
|
445 |
}
|
446 |
$data['related'] = implode(',', $related_value);
|
447 |
+
unset($related_value);
|
448 |
}
|
449 |
|
450 |
return $data;
|
461 |
{
|
462 |
$query_parameters = $this->toQueryParameters();
|
463 |
|
464 |
+
if (! empty($query_parameters)) {
|
465 |
return self::INTENT_URL . '?' . http_build_query($query_parameters, '', '&', PHP_QUERY_RFC3986);
|
466 |
}
|
467 |
|
src/Twitter/Widgets/{BaseWidget.php → Base.php}
RENAMED
@@ -30,7 +30,7 @@ namespace Twitter\Widgets;
|
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
abstract class
|
34 |
{
|
35 |
|
36 |
/**
|
@@ -58,7 +58,7 @@ abstract class BaseWidget
|
|
58 |
*
|
59 |
* @since 1.0.0
|
60 |
*
|
61 |
-
* @return
|
62 |
*/
|
63 |
public function doNotTrack()
|
64 |
{
|
@@ -71,7 +71,7 @@ abstract class BaseWidget
|
|
71 |
*
|
72 |
* @since 1.0.0
|
73 |
*
|
74 |
-
* @return
|
75 |
*/
|
76 |
public function allowTracking()
|
77 |
{
|
@@ -88,7 +88,7 @@ abstract class BaseWidget
|
|
88 |
*
|
89 |
* @param string $lang Twitter-supported language code
|
90 |
*
|
91 |
-
* @return
|
92 |
*/
|
93 |
public function setLanguage($lang)
|
94 |
{
|
@@ -100,7 +100,7 @@ abstract class BaseWidget
|
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
-
* Populate
|
104 |
*
|
105 |
* @since 1.0.0
|
106 |
*
|
@@ -109,15 +109,15 @@ abstract class BaseWidget
|
|
109 |
* @type string|int|bool option value
|
110 |
* }
|
111 |
*
|
112 |
-
* @return
|
113 |
*/
|
114 |
public function setBaseOptions($options)
|
115 |
{
|
116 |
-
if (isset(
|
117 |
$this->doNotTrack();
|
118 |
}
|
119 |
|
120 |
-
if (isset(
|
121 |
$this->setLanguage($options['lang']);
|
122 |
}
|
123 |
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
abstract class Base
|
34 |
{
|
35 |
|
36 |
/**
|
58 |
*
|
59 |
* @since 1.0.0
|
60 |
*
|
61 |
+
* @return self support chaining
|
62 |
*/
|
63 |
public function doNotTrack()
|
64 |
{
|
71 |
*
|
72 |
* @since 1.0.0
|
73 |
*
|
74 |
+
* @return self support chaining
|
75 |
*/
|
76 |
public function allowTracking()
|
77 |
{
|
88 |
*
|
89 |
* @param string $lang Twitter-supported language code
|
90 |
*
|
91 |
+
* @return self support chaining
|
92 |
*/
|
93 |
public function setLanguage($lang)
|
94 |
{
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
+
* Populate Base options from a passed associative array
|
104 |
*
|
105 |
* @since 1.0.0
|
106 |
*
|
109 |
* @type string|int|bool option value
|
110 |
* }
|
111 |
*
|
112 |
+
* @return self support chaining
|
113 |
*/
|
114 |
public function setBaseOptions($options)
|
115 |
{
|
116 |
+
if (isset($options['dnt']) && ( true === $options['dnt'] || 'true' === $options['dnt'] || 'on' === $options['dnt'] || 1 == $options['dnt'] )) {
|
117 |
$this->doNotTrack();
|
118 |
}
|
119 |
|
120 |
+
if (isset($options['lang']) && $options['lang']) {
|
121 |
$this->setLanguage($options['lang']);
|
122 |
}
|
123 |
|
src/Twitter/Widgets/{FollowButton.php → Buttons/Follow.php}
RENAMED
@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\Widgets;
|
27 |
|
28 |
/**
|
29 |
* Follow button markup to be interpreted by Twitter's widget JavaScript
|
@@ -32,7 +32,7 @@ namespace Twitter\Widgets;
|
|
32 |
*
|
33 |
* @link https://dev.twitter.com/web/follow-button Follow button documentation
|
34 |
*/
|
35 |
-
class
|
36 |
{
|
37 |
|
38 |
/**
|
@@ -110,7 +110,7 @@ class FollowButton extends BaseWidget
|
|
110 |
*
|
111 |
* @since 1.0.0
|
112 |
*
|
113 |
-
* @return
|
114 |
*/
|
115 |
public function showCount()
|
116 |
{
|
@@ -123,7 +123,7 @@ class FollowButton extends BaseWidget
|
|
123 |
*
|
124 |
* @since 1.0.0
|
125 |
*
|
126 |
-
* @return
|
127 |
*/
|
128 |
public function hideCount()
|
129 |
{
|
@@ -148,7 +148,7 @@ class FollowButton extends BaseWidget
|
|
148 |
*
|
149 |
* @since 1.0.0
|
150 |
*
|
151 |
-
* @return
|
152 |
*/
|
153 |
public function showScreenName()
|
154 |
{
|
@@ -161,7 +161,7 @@ class FollowButton extends BaseWidget
|
|
161 |
*
|
162 |
* @since 1.0.0
|
163 |
*
|
164 |
-
* @return
|
165 |
*/
|
166 |
public function hideScreenName()
|
167 |
{
|
@@ -176,7 +176,7 @@ class FollowButton extends BaseWidget
|
|
176 |
*
|
177 |
* @param string $size button size
|
178 |
*
|
179 |
-
* @return
|
180 |
*/
|
181 |
public function setSize($size)
|
182 |
{
|
@@ -197,28 +197,28 @@ class FollowButton extends BaseWidget
|
|
197 |
* @type string|int|bool option value
|
198 |
* }
|
199 |
*
|
200 |
-
* @return
|
201 |
*/
|
202 |
public static function fromArray($options)
|
203 |
{
|
204 |
-
if (! isset(
|
205 |
-
return;
|
206 |
}
|
207 |
|
208 |
-
$class =
|
209 |
$follow = new $class( $options['screen_name'] );
|
210 |
-
unset(
|
211 |
|
212 |
$follow->setBaseOptions($options);
|
213 |
|
214 |
-
if (isset(
|
215 |
$follow->hideCount();
|
216 |
}
|
217 |
-
if (isset(
|
218 |
$follow->hideScreenName();
|
219 |
}
|
220 |
|
221 |
-
if (isset(
|
222 |
$follow->setSize($options['size']);
|
223 |
}
|
224 |
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\Widgets\Buttons;
|
27 |
|
28 |
/**
|
29 |
* Follow button markup to be interpreted by Twitter's widget JavaScript
|
32 |
*
|
33 |
* @link https://dev.twitter.com/web/follow-button Follow button documentation
|
34 |
*/
|
35 |
+
class Follow extends \Twitter\Widgets\Base
|
36 |
{
|
37 |
|
38 |
/**
|
110 |
*
|
111 |
* @since 1.0.0
|
112 |
*
|
113 |
+
* @return self support chaining
|
114 |
*/
|
115 |
public function showCount()
|
116 |
{
|
123 |
*
|
124 |
* @since 1.0.0
|
125 |
*
|
126 |
+
* @return self support chaining
|
127 |
*/
|
128 |
public function hideCount()
|
129 |
{
|
148 |
*
|
149 |
* @since 1.0.0
|
150 |
*
|
151 |
+
* @return self support chaining
|
152 |
*/
|
153 |
public function showScreenName()
|
154 |
{
|
161 |
*
|
162 |
* @since 1.0.0
|
163 |
*
|
164 |
+
* @return self support chaining
|
165 |
*/
|
166 |
public function hideScreenName()
|
167 |
{
|
176 |
*
|
177 |
* @param string $size button size
|
178 |
*
|
179 |
+
* @return self support chaining
|
180 |
*/
|
181 |
public function setSize($size)
|
182 |
{
|
197 |
* @type string|int|bool option value
|
198 |
* }
|
199 |
*
|
200 |
+
* @return static|null Follow button object or null if minimum requirements not met
|
201 |
*/
|
202 |
public static function fromArray($options)
|
203 |
{
|
204 |
+
if (! isset($options['screen_name']) && $options['screen_name']) {
|
205 |
+
return null;
|
206 |
}
|
207 |
|
208 |
+
$class = get_called_class();
|
209 |
$follow = new $class( $options['screen_name'] );
|
210 |
+
unset($class);
|
211 |
|
212 |
$follow->setBaseOptions($options);
|
213 |
|
214 |
+
if (isset($options['show_count']) && ( false === $options['show_count'] || 'false' === $options['show_count'] || 0 == $options['show_count'] )) {
|
215 |
$follow->hideCount();
|
216 |
}
|
217 |
+
if (isset($options['show_screen_name']) && ( false === $options['show_screen_name'] || 'false' === $options['show_screen_name'] || 0 == $options['show_screen_name'] )) {
|
218 |
$follow->hideScreenName();
|
219 |
}
|
220 |
|
221 |
+
if (isset($options['size']) && 'medium' !== $options['size']) {
|
222 |
$follow->setSize($options['size']);
|
223 |
}
|
224 |
|
src/Twitter/Widgets/{PeriscopeOnAir.php → Buttons/Periscope/OnAir.php}
RENAMED
@@ -23,19 +23,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\Widgets;
|
27 |
|
28 |
/**
|
29 |
* Periscope profile button with on-air status display
|
30 |
*
|
31 |
-
* @since
|
32 |
*/
|
33 |
-
class
|
34 |
{
|
35 |
/**
|
36 |
* HTML class expected by the Periscope widget JS
|
37 |
*
|
38 |
-
* @since
|
39 |
*
|
40 |
* @type string
|
41 |
*/
|
@@ -45,7 +45,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
45 |
/**
|
46 |
* Default button size
|
47 |
*
|
48 |
-
* @since
|
49 |
*
|
50 |
* @type string
|
51 |
*/
|
@@ -54,7 +54,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
54 |
/**
|
55 |
* Periscope web profile base URL
|
56 |
*
|
57 |
-
* @since
|
58 |
*
|
59 |
* @type string
|
60 |
*/
|
@@ -63,7 +63,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
63 |
/**
|
64 |
* Periscope username
|
65 |
*
|
66 |
-
* @since
|
67 |
*
|
68 |
* @type string
|
69 |
*/
|
@@ -72,7 +72,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
72 |
/**
|
73 |
* Allowed values for the size property
|
74 |
*
|
75 |
-
* @since
|
76 |
*
|
77 |
* @type array allowed sizes {
|
78 |
* @type string size
|
@@ -84,7 +84,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
84 |
/**
|
85 |
* Size of the button
|
86 |
*
|
87 |
-
* @since
|
88 |
*
|
89 |
* @type string
|
90 |
*/
|
@@ -93,7 +93,10 @@ class PeriscopeOnAir extends BaseWidget
|
|
93 |
/**
|
94 |
* Require username
|
95 |
*
|
96 |
-
* @
|
|
|
|
|
|
|
97 |
*/
|
98 |
public function __construct($username, $validate = true)
|
99 |
{
|
@@ -106,7 +109,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
106 |
/**
|
107 |
* Retrieve the stored Periscope username
|
108 |
*
|
109 |
-
* @since
|
110 |
*
|
111 |
* @return string Periscope username or empty string if username not set
|
112 |
*/
|
@@ -118,9 +121,9 @@ class PeriscopeOnAir extends BaseWidget
|
|
118 |
/**
|
119 |
* Build a Periscope web profile URL
|
120 |
*
|
121 |
-
* @since
|
122 |
*
|
123 |
-
* @return Periscope web profile URL or empty string if username not set
|
124 |
*/
|
125 |
public function getWebProfileURL()
|
126 |
{
|
@@ -130,11 +133,11 @@ class PeriscopeOnAir extends BaseWidget
|
|
130 |
/**
|
131 |
* Set the desired size of the On Air button
|
132 |
*
|
133 |
-
* @since
|
134 |
*
|
135 |
* @param string $size button size
|
136 |
*
|
137 |
-
* @return
|
138 |
*/
|
139 |
public function setSize($size)
|
140 |
{
|
@@ -147,28 +150,28 @@ class PeriscopeOnAir extends BaseWidget
|
|
147 |
/**
|
148 |
* Build a Periscope On Air object from an associative array
|
149 |
*
|
150 |
-
* @since
|
151 |
*
|
152 |
* @param array $options associative array of options {
|
153 |
* @type string option name
|
154 |
* @type string option value
|
155 |
* }
|
156 |
*
|
157 |
-
* @return
|
158 |
*/
|
159 |
public static function fromArray($options)
|
160 |
{
|
161 |
-
if (! isset(
|
162 |
-
return;
|
163 |
}
|
164 |
|
165 |
-
$class =
|
166 |
$on_air = new $class( $options['username'] );
|
167 |
-
unset(
|
168 |
|
169 |
$on_air->setBaseOptions($options);
|
170 |
|
171 |
-
if (isset(
|
172 |
$on_air->setSize($options['size']);
|
173 |
}
|
174 |
|
@@ -178,7 +181,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
178 |
/**
|
179 |
* Convert the class object into an array, removing default field values
|
180 |
*
|
181 |
-
* @since
|
182 |
*
|
183 |
* @return array properties as associative array
|
184 |
*/
|
@@ -196,7 +199,7 @@ class PeriscopeOnAir extends BaseWidget
|
|
196 |
/**
|
197 |
* Generate a link to a Periscope web profile configured for enhancement by the Twitter for Websites JavaScript
|
198 |
*
|
199 |
-
* @since
|
200 |
*
|
201 |
* @param string $html_builder_class callable HTML builder with a static anchorElement class
|
202 |
*
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\Widgets\Buttons\Periscope;
|
27 |
|
28 |
/**
|
29 |
* Periscope profile button with on-air status display
|
30 |
*
|
31 |
+
* @since 2.0.0
|
32 |
*/
|
33 |
+
class OnAir extends \Twitter\Widgets\Base
|
34 |
{
|
35 |
/**
|
36 |
* HTML class expected by the Periscope widget JS
|
37 |
*
|
38 |
+
* @since 2.0.0
|
39 |
*
|
40 |
* @type string
|
41 |
*/
|
45 |
/**
|
46 |
* Default button size
|
47 |
*
|
48 |
+
* @since 2.0.0
|
49 |
*
|
50 |
* @type string
|
51 |
*/
|
54 |
/**
|
55 |
* Periscope web profile base URL
|
56 |
*
|
57 |
+
* @since 2.0.0
|
58 |
*
|
59 |
* @type string
|
60 |
*/
|
63 |
/**
|
64 |
* Periscope username
|
65 |
*
|
66 |
+
* @since 2.0.0
|
67 |
*
|
68 |
* @type string
|
69 |
*/
|
72 |
/**
|
73 |
* Allowed values for the size property
|
74 |
*
|
75 |
+
* @since 2.0.0
|
76 |
*
|
77 |
* @type array allowed sizes {
|
78 |
* @type string size
|
84 |
/**
|
85 |
* Size of the button
|
86 |
*
|
87 |
+
* @since 2.0.0
|
88 |
*
|
89 |
* @type string
|
90 |
*/
|
93 |
/**
|
94 |
* Require username
|
95 |
*
|
96 |
+
* @param string $username target username
|
97 |
+
* @param bool $validate validate inputs such as username before storing
|
98 |
+
*
|
99 |
+
* @since 2.0.0
|
100 |
*/
|
101 |
public function __construct($username, $validate = true)
|
102 |
{
|
109 |
/**
|
110 |
* Retrieve the stored Periscope username
|
111 |
*
|
112 |
+
* @since 2.0.0
|
113 |
*
|
114 |
* @return string Periscope username or empty string if username not set
|
115 |
*/
|
121 |
/**
|
122 |
* Build a Periscope web profile URL
|
123 |
*
|
124 |
+
* @since 2.0.0
|
125 |
*
|
126 |
+
* @return string Periscope web profile URL or empty string if username not set
|
127 |
*/
|
128 |
public function getWebProfileURL()
|
129 |
{
|
133 |
/**
|
134 |
* Set the desired size of the On Air button
|
135 |
*
|
136 |
+
* @since 2.0.0
|
137 |
*
|
138 |
* @param string $size button size
|
139 |
*
|
140 |
+
* @return self support chaining
|
141 |
*/
|
142 |
public function setSize($size)
|
143 |
{
|
150 |
/**
|
151 |
* Build a Periscope On Air object from an associative array
|
152 |
*
|
153 |
+
* @since 2.0.0
|
154 |
*
|
155 |
* @param array $options associative array of options {
|
156 |
* @type string option name
|
157 |
* @type string option value
|
158 |
* }
|
159 |
*
|
160 |
+
* @return self|null new OnAir object of null if minimum requirements not met
|
161 |
*/
|
162 |
public static function fromArray($options)
|
163 |
{
|
164 |
+
if (! isset($options['username']) && $options['username']) {
|
165 |
+
return null;
|
166 |
}
|
167 |
|
168 |
+
$class = get_called_class();
|
169 |
$on_air = new $class( $options['username'] );
|
170 |
+
unset($class);
|
171 |
|
172 |
$on_air->setBaseOptions($options);
|
173 |
|
174 |
+
if (isset($options['size']) && static::DEFAULT_SIZE !== $options['size']) {
|
175 |
$on_air->setSize($options['size']);
|
176 |
}
|
177 |
|
181 |
/**
|
182 |
* Convert the class object into an array, removing default field values
|
183 |
*
|
184 |
+
* @since 2.0.0
|
185 |
*
|
186 |
* @return array properties as associative array
|
187 |
*/
|
199 |
/**
|
200 |
* Generate a link to a Periscope web profile configured for enhancement by the Twitter for Websites JavaScript
|
201 |
*
|
202 |
+
* @since 2.0.0
|
203 |
*
|
204 |
* @param string $html_builder_class callable HTML builder with a static anchorElement class
|
205 |
*
|
src/Twitter/Widgets/{TweetButton.php → Buttons/Tweet.php}
RENAMED
@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\Widgets;
|
27 |
|
28 |
/**
|
29 |
* Tweet button markup to be interpreted by Twitter's widget JavaScript
|
@@ -32,7 +32,7 @@ namespace Twitter\Widgets;
|
|
32 |
*
|
33 |
* @link https://dev.twitter.com/web/tweet-button Tweet button documentation
|
34 |
*/
|
35 |
-
class
|
36 |
{
|
37 |
|
38 |
/**
|
@@ -96,7 +96,7 @@ class TweetButton extends BaseWidget
|
|
96 |
*
|
97 |
* @param \Twitter\Intents\Tweet $intent Tweet Intent
|
98 |
*
|
99 |
-
* @return
|
100 |
*/
|
101 |
public function setIntent($intent)
|
102 |
{
|
@@ -114,7 +114,7 @@ class TweetButton extends BaseWidget
|
|
114 |
*
|
115 |
* @param string $size button size
|
116 |
*
|
117 |
-
* @return
|
118 |
*/
|
119 |
public function setSize($size)
|
120 |
{
|
@@ -132,7 +132,7 @@ class TweetButton extends BaseWidget
|
|
132 |
*
|
133 |
* @param string $tweet_id Parent Tweet ID
|
134 |
*
|
135 |
-
* @return
|
136 |
*/
|
137 |
public function setInReplyTo($tweet_id)
|
138 |
{
|
@@ -148,7 +148,7 @@ class TweetButton extends BaseWidget
|
|
148 |
*
|
149 |
* @param string $text Tweet text
|
150 |
*
|
151 |
-
* @return
|
152 |
*/
|
153 |
public function setText($text)
|
154 |
{
|
@@ -164,7 +164,7 @@ class TweetButton extends BaseWidget
|
|
164 |
*
|
165 |
* @param string $url absolute URL
|
166 |
*
|
167 |
-
* @return
|
168 |
*/
|
169 |
public function setURL($url)
|
170 |
{
|
@@ -180,7 +180,7 @@ class TweetButton extends BaseWidget
|
|
180 |
*
|
181 |
* @param string $hashtag hashtag
|
182 |
*
|
183 |
-
* @return
|
184 |
*/
|
185 |
public function addHashtag($hashtag)
|
186 |
{
|
@@ -196,11 +196,13 @@ class TweetButton extends BaseWidget
|
|
196 |
*
|
197 |
* @param string $username Twitter username
|
198 |
*
|
199 |
-
* @return
|
200 |
*/
|
201 |
public function setVia($username)
|
202 |
{
|
203 |
$this->intent->setVia($username);
|
|
|
|
|
204 |
}
|
205 |
|
206 |
/**
|
@@ -211,7 +213,7 @@ class TweetButton extends BaseWidget
|
|
211 |
* @param string $username Twitter username
|
212 |
* @param string $label brief description of how the account relates to the Tweet content
|
213 |
*
|
214 |
-
* @return
|
215 |
*/
|
216 |
public function addRelated($username, $label = '')
|
217 |
{
|
@@ -228,7 +230,7 @@ class TweetButton extends BaseWidget
|
|
228 |
* @type string|int|bool parameter value
|
229 |
* }
|
230 |
*
|
231 |
-
* @return
|
232 |
*/
|
233 |
public static function fromArray($options)
|
234 |
{
|
@@ -239,7 +241,7 @@ class TweetButton extends BaseWidget
|
|
239 |
|
240 |
$class = get_called_class();
|
241 |
$button = new $class();
|
242 |
-
unset(
|
243 |
|
244 |
// remove values which evaluate to false
|
245 |
$options = array_filter($options);
|
@@ -248,10 +250,10 @@ class TweetButton extends BaseWidget
|
|
248 |
// intent parameters
|
249 |
$intent_class = static::INTENT_CLASS;
|
250 |
$button->setIntent($intent_class::fromArray($options));
|
251 |
-
unset(
|
252 |
|
253 |
// button parameters
|
254 |
-
if (isset(
|
255 |
$button->setSize($options['size']);
|
256 |
}
|
257 |
|
@@ -259,7 +261,7 @@ class TweetButton extends BaseWidget
|
|
259 |
}
|
260 |
|
261 |
/**
|
262 |
-
* Return Tweet button parameters suitable
|
263 |
*
|
264 |
* @since 1.0.0
|
265 |
*
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\Widgets\Buttons;
|
27 |
|
28 |
/**
|
29 |
* Tweet button markup to be interpreted by Twitter's widget JavaScript
|
32 |
*
|
33 |
* @link https://dev.twitter.com/web/tweet-button Tweet button documentation
|
34 |
*/
|
35 |
+
class Tweet extends \Twitter\Widgets\Base
|
36 |
{
|
37 |
|
38 |
/**
|
96 |
*
|
97 |
* @param \Twitter\Intents\Tweet $intent Tweet Intent
|
98 |
*
|
99 |
+
* @return self support chaining
|
100 |
*/
|
101 |
public function setIntent($intent)
|
102 |
{
|
114 |
*
|
115 |
* @param string $size button size
|
116 |
*
|
117 |
+
* @return self support chaining
|
118 |
*/
|
119 |
public function setSize($size)
|
120 |
{
|
132 |
*
|
133 |
* @param string $tweet_id Parent Tweet ID
|
134 |
*
|
135 |
+
* @return self support chaining
|
136 |
*/
|
137 |
public function setInReplyTo($tweet_id)
|
138 |
{
|
148 |
*
|
149 |
* @param string $text Tweet text
|
150 |
*
|
151 |
+
* @return self support chaining
|
152 |
*/
|
153 |
public function setText($text)
|
154 |
{
|
164 |
*
|
165 |
* @param string $url absolute URL
|
166 |
*
|
167 |
+
* @return self support chaining
|
168 |
*/
|
169 |
public function setURL($url)
|
170 |
{
|
180 |
*
|
181 |
* @param string $hashtag hashtag
|
182 |
*
|
183 |
+
* @return self support chaining
|
184 |
*/
|
185 |
public function addHashtag($hashtag)
|
186 |
{
|
196 |
*
|
197 |
* @param string $username Twitter username
|
198 |
*
|
199 |
+
* @return self support chaining
|
200 |
*/
|
201 |
public function setVia($username)
|
202 |
{
|
203 |
$this->intent->setVia($username);
|
204 |
+
|
205 |
+
return $this;
|
206 |
}
|
207 |
|
208 |
/**
|
213 |
* @param string $username Twitter username
|
214 |
* @param string $label brief description of how the account relates to the Tweet content
|
215 |
*
|
216 |
+
* @return self support chaining
|
217 |
*/
|
218 |
public function addRelated($username, $label = '')
|
219 |
{
|
230 |
* @type string|int|bool parameter value
|
231 |
* }
|
232 |
*
|
233 |
+
* @return self new button with configured parameters
|
234 |
*/
|
235 |
public static function fromArray($options)
|
236 |
{
|
241 |
|
242 |
$class = get_called_class();
|
243 |
$button = new $class();
|
244 |
+
unset($class);
|
245 |
|
246 |
// remove values which evaluate to false
|
247 |
$options = array_filter($options);
|
250 |
// intent parameters
|
251 |
$intent_class = static::INTENT_CLASS;
|
252 |
$button->setIntent($intent_class::fromArray($options));
|
253 |
+
unset($intent_class);
|
254 |
|
255 |
// button parameters
|
256 |
+
if (isset($options['size'])) {
|
257 |
$button->setSize($options['size']);
|
258 |
}
|
259 |
|
261 |
}
|
262 |
|
263 |
/**
|
264 |
+
* Return Tweet button parameters suitable for conversion to data-*
|
265 |
*
|
266 |
* @since 1.0.0
|
267 |
*
|
src/Twitter/Widgets/Embeds/Moment.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display Tweets included in a Twitter Moment
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Moment extends \Twitter\Widgets\Embeds\Timeline\Collection
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Construct a full Twitter URI by appending to base string
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const BASE_URL = 'https://twitter.com/i/moments/';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Create a new Moment object
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @param string $id unique identifier of the Moment
|
50 |
+
*/
|
51 |
+
public function __construct($id)
|
52 |
+
{
|
53 |
+
parent::__construct($id);
|
54 |
+
|
55 |
+
// all moments are grids
|
56 |
+
$this->setGridTemplate();
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Return Moment parameters suitable for conversion to data-*
|
61 |
+
*
|
62 |
+
* @since 2.0.0
|
63 |
+
*
|
64 |
+
* @return array Moment timeline parameter array {
|
65 |
+
* @type string dashed parameter name
|
66 |
+
* @type string parameter value
|
67 |
+
* }
|
68 |
+
*/
|
69 |
+
public function toArray()
|
70 |
+
{
|
71 |
+
$data = parent::toArray();
|
72 |
+
|
73 |
+
unset($data['widget-type']);
|
74 |
+
|
75 |
+
return $data;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Output Moment as an array suitable for use as oEmbed query parameters
|
80 |
+
*
|
81 |
+
* @since 2.0.0
|
82 |
+
*
|
83 |
+
* @return array Moment parameter array {
|
84 |
+
* @type string query parameter name
|
85 |
+
* @type string query parameter value
|
86 |
+
* }
|
87 |
+
*/
|
88 |
+
public function toOEmbedParameterArray()
|
89 |
+
{
|
90 |
+
$query_parameters = parent::toOEmbedParameterArray();
|
91 |
+
|
92 |
+
unset($query_parameters['widget_type']);
|
93 |
+
|
94 |
+
return $query_parameters;
|
95 |
+
}
|
96 |
+
}
|
src/Twitter/Widgets/Embeds/Theme.php
ADDED
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2015 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* An embed capable of theming
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
trait Theme
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Light background, dark text
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
public static $THEME_LIGHT = 'light';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Dark background, light text
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type string
|
50 |
+
*/
|
51 |
+
public static $THEME_DARK = 'dark';
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Embed display theme
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @type string
|
59 |
+
*/
|
60 |
+
protected $theme = 'light';
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Hexadecimal color of borders separating Tweets or Tweet elements
|
64 |
+
*
|
65 |
+
* @since 2.0.0
|
66 |
+
*
|
67 |
+
* @type string
|
68 |
+
*/
|
69 |
+
protected $border_color;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Hexadecimal color of links appearing in Tweet text
|
73 |
+
*
|
74 |
+
* @since 2.0.0
|
75 |
+
*
|
76 |
+
* @type string
|
77 |
+
*/
|
78 |
+
protected $link_color;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Test if the provided theme value is accepted by Twitter for Websites embeds
|
82 |
+
*
|
83 |
+
* @since 2.0.0
|
84 |
+
*
|
85 |
+
* @param string $theme dark or light theme
|
86 |
+
*
|
87 |
+
* @return bool true if valid theme value, else false
|
88 |
+
*/
|
89 |
+
public static function isValidTheme($theme)
|
90 |
+
{
|
91 |
+
return ( $theme === static::$THEME_LIGHT || $theme === static::$THEME_DARK );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Test if a provided string is a valid hexadecimal color
|
96 |
+
*
|
97 |
+
* @param string $color hexadecimal color
|
98 |
+
*
|
99 |
+
* @return bool true if valid hexadecimal color else false
|
100 |
+
*/
|
101 |
+
public static function isValidHexadecimalColor($color)
|
102 |
+
{
|
103 |
+
if ($color && is_string($color) && 6 === strlen($color)) {
|
104 |
+
if (function_exists('ctype_xdigit')) {
|
105 |
+
if (ctype_xdigit($color)) {
|
106 |
+
return true;
|
107 |
+
}
|
108 |
+
} elseif (preg_match('/^[a-f0-9]{6}$/i', $color)) {
|
109 |
+
return true;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
return false;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Set a widget embed theme
|
118 |
+
*
|
119 |
+
* @since 2.0.0
|
120 |
+
*
|
121 |
+
* @param string $theme light or dark
|
122 |
+
*
|
123 |
+
* @return self support chaining
|
124 |
+
*/
|
125 |
+
public function setTheme($theme)
|
126 |
+
{
|
127 |
+
if ($theme && is_string($theme)) {
|
128 |
+
$theme = trim(strtolower($theme));
|
129 |
+
if ($theme && static::isValidTheme($theme)) {
|
130 |
+
$this->theme = $theme;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
return $this;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Set a light theme
|
139 |
+
*
|
140 |
+
* @since 2.0.0
|
141 |
+
*
|
142 |
+
* @return self support chaining
|
143 |
+
*/
|
144 |
+
public function setThemeLight()
|
145 |
+
{
|
146 |
+
if ($this->theme !== static::$THEME_LIGHT) {
|
147 |
+
$this->theme = static::$THEME_LIGHT;
|
148 |
+
}
|
149 |
+
|
150 |
+
return $this;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Set a light theme
|
155 |
+
*
|
156 |
+
* @since 2.0.0
|
157 |
+
*
|
158 |
+
* @return self support chaining
|
159 |
+
*/
|
160 |
+
public function setThemeDark()
|
161 |
+
{
|
162 |
+
if ($this->theme !== static::$THEME_DARK) {
|
163 |
+
$this->theme = static::$THEME_DARK;
|
164 |
+
}
|
165 |
+
|
166 |
+
return $this;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Clean and normalize supplied hexadecimal color
|
171 |
+
*
|
172 |
+
* @since 2.0.0
|
173 |
+
*
|
174 |
+
* @param string $color hexadecimal color
|
175 |
+
*
|
176 |
+
* @return string cleaned and normalized hexadecimal color
|
177 |
+
*/
|
178 |
+
protected static function cleanHexadecimalColor($color)
|
179 |
+
{
|
180 |
+
if ($color && is_string($color)) {
|
181 |
+
// remove any leading hash
|
182 |
+
$color = ltrim(trim($color), '#');
|
183 |
+
|
184 |
+
if ($color) {
|
185 |
+
// convert abbrevated colors
|
186 |
+
if (3 === strlen($color)) {
|
187 |
+
$color .= $color;
|
188 |
+
}
|
189 |
+
|
190 |
+
$color = strtoupper($color);
|
191 |
+
if (static::isValidHexadecimalColor($color)) {
|
192 |
+
return $color;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
return '';
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Set the color of links in Tweet text
|
202 |
+
*
|
203 |
+
* @since 2.0.0
|
204 |
+
*
|
205 |
+
* @param string $color hexadecimal color
|
206 |
+
*
|
207 |
+
* @return self support chaining
|
208 |
+
*/
|
209 |
+
public function setLinkColor($color)
|
210 |
+
{
|
211 |
+
$color = static::cleanHexadecimalColor($color);
|
212 |
+
if ($color) {
|
213 |
+
$this->link_color = $color;
|
214 |
+
}
|
215 |
+
|
216 |
+
return $this;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Set the color of borders separating Tweets or Tweet components
|
221 |
+
*
|
222 |
+
* @since 2.0.0
|
223 |
+
*
|
224 |
+
* @param string $color hexadecimal color
|
225 |
+
*
|
226 |
+
* @return self support chaining
|
227 |
+
*/
|
228 |
+
public function setBorderColor($color)
|
229 |
+
{
|
230 |
+
$color = static::cleanHexadecimalColor($color);
|
231 |
+
if ($color) {
|
232 |
+
$this->border_color = $color;
|
233 |
+
}
|
234 |
+
|
235 |
+
return $this;
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Set theme-related options from an associative array
|
240 |
+
*
|
241 |
+
* @since 2.0.0
|
242 |
+
*
|
243 |
+
* @param array $options associative array of options {
|
244 |
+
* @type string option name
|
245 |
+
* @type string|int|bool option value
|
246 |
+
* }
|
247 |
+
*
|
248 |
+
* @return self support chaining
|
249 |
+
*/
|
250 |
+
public function setThemeOptions($options)
|
251 |
+
{
|
252 |
+
if (isset($options['theme']) && is_string($options['theme']) && static::$THEME_DARK === strtolower($options['theme'])) {
|
253 |
+
$this->setThemeDark();
|
254 |
+
}
|
255 |
+
|
256 |
+
if (isset($options['link-color']) && $options['link-color'] && is_string($options['link-color'])) {
|
257 |
+
$this->setLinkColor($options['link-color']);
|
258 |
+
}
|
259 |
+
|
260 |
+
if (isset($options['border-color']) && $options['border-color'] && is_string($options['border-color'])) {
|
261 |
+
$this->setBorderColor($options['border-color']);
|
262 |
+
}
|
263 |
+
|
264 |
+
return $this;
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Convert trait properties into an associative array
|
269 |
+
*
|
270 |
+
* @since 2.0.0
|
271 |
+
*
|
272 |
+
* @return array properties as associative array
|
273 |
+
*/
|
274 |
+
public function themeToArray()
|
275 |
+
{
|
276 |
+
$data = array();
|
277 |
+
|
278 |
+
if (isset($this->theme) && static::$THEME_LIGHT !== $this->theme) {
|
279 |
+
$data['theme'] = $this->theme;
|
280 |
+
}
|
281 |
+
|
282 |
+
if (isset($this->link_color) && is_string($this->link_color) && 6 === strlen($this->link_color)) {
|
283 |
+
$data['link-color'] = '#' . $this->link_color;
|
284 |
+
}
|
285 |
+
|
286 |
+
if (isset($this->border_color) && is_string($this->border_color) && 6 === strlen($this->border_color)) {
|
287 |
+
$data['border-color'] = '#' . $this->border_color;
|
288 |
+
}
|
289 |
+
|
290 |
+
return $data;
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Format theme parameters as oEmbed-ready query parameters
|
295 |
+
*
|
296 |
+
* @since 2.0.0
|
297 |
+
*
|
298 |
+
* @return array parameter array {
|
299 |
+
* @type string query parameter name
|
300 |
+
* @type string query parameter value
|
301 |
+
* }
|
302 |
+
*/
|
303 |
+
public function themeToOEmbedParameterArray()
|
304 |
+
{
|
305 |
+
$oembed = $this->themeToArray();
|
306 |
+
|
307 |
+
$data_to_oembed = array(
|
308 |
+
'link-color' => 'link_color',
|
309 |
+
'border-color' => 'border_color',
|
310 |
+
);
|
311 |
+
|
312 |
+
foreach ($data_to_oembed as $data_attribute => $oembed_parameter) {
|
313 |
+
if (isset($oembed[$data_attribute])) {
|
314 |
+
$oembed[$oembed_parameter] = $oembed[$data_attribute];
|
315 |
+
unset($oembed[$data_attribute]);
|
316 |
+
}
|
317 |
+
}
|
318 |
+
|
319 |
+
return $oembed;
|
320 |
+
}
|
321 |
+
}
|
src/Twitter/Widgets/Embeds/Timeline.php
ADDED
@@ -0,0 +1,678 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Base properties used across all embedded timelines
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
abstract class Timeline extends \Twitter\Widgets\Base
|
34 |
+
{
|
35 |
+
use \Twitter\Widgets\Embeds\Theme;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* The minimum supported display height of an embedded timeline
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type int
|
43 |
+
*/
|
44 |
+
const MIN_HEIGHT = 200;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The minimum supported display height of an embedded timeline
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type int
|
52 |
+
*/
|
53 |
+
const MIN_WIDTH = 180;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* The maximum supported display width of an embedded timeline
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type int
|
61 |
+
*/
|
62 |
+
const MAX_WIDTH = 1200;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* The minimum number of Tweets supported without pagination
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @type int
|
70 |
+
*/
|
71 |
+
const MIN_LIMIT = 1;
|
72 |
+
|
73 |
+
/**
|
74 |
+
* The maximum number of Tweets supported without pagination
|
75 |
+
*
|
76 |
+
* @since 2.0.0
|
77 |
+
*
|
78 |
+
* @type int
|
79 |
+
*/
|
80 |
+
const MAX_LIMIT = 20;
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Chrome option token for no header display
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @type string
|
88 |
+
*/
|
89 |
+
const CHROME_NOHEADER = 'noheader';
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Chrome option token for no header display
|
93 |
+
*
|
94 |
+
* @since 2.0.0
|
95 |
+
*
|
96 |
+
* @type string
|
97 |
+
*/
|
98 |
+
const CHROME_NOFOOTER = 'nofooter';
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Chrome option token for no borders display
|
102 |
+
*
|
103 |
+
* @since 2.0.0
|
104 |
+
*
|
105 |
+
* @type string
|
106 |
+
*/
|
107 |
+
const CHROME_NOBORDERS = 'noborders';
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Chrome option token for no embedded timeline scrollbar
|
111 |
+
*
|
112 |
+
* @since 2.0.0
|
113 |
+
*
|
114 |
+
* @type string
|
115 |
+
*/
|
116 |
+
const CHROME_NOSCROLLBAR = 'noscrollbar';
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Chrome option token for transparent background
|
120 |
+
*
|
121 |
+
* @since 2.0.0
|
122 |
+
*
|
123 |
+
* @type string
|
124 |
+
*/
|
125 |
+
const CHROME_TRANSPARENT = 'transparent';
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Tweets added to an embedded timeline should only be announced if the user is not currently doing anything
|
129 |
+
*
|
130 |
+
* @since 2.0.0
|
131 |
+
*
|
132 |
+
* @type string
|
133 |
+
*/
|
134 |
+
const ARIA_POLITE_POLITE = 'polite';
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Tweets added to an embedded timeline are important enough to be announced to the user as soon as possible, but it is not necessary to immediately interrupt the user
|
138 |
+
*
|
139 |
+
* @since 2.0.0
|
140 |
+
*
|
141 |
+
* @type string
|
142 |
+
*/
|
143 |
+
const ARIA_POLITE_ASSERTIVE = 'assertive';
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Available values for customizing embedded timeline chrome
|
147 |
+
*
|
148 |
+
* @since 2.0.0
|
149 |
+
*
|
150 |
+
* @type array {
|
151 |
+
* @type string valid value
|
152 |
+
* @type bool unused
|
153 |
+
* }
|
154 |
+
*/
|
155 |
+
public static $CHROME_OPTIONS = array(
|
156 |
+
self::CHROME_NOHEADER => true,
|
157 |
+
self::CHROME_NOFOOTER => true,
|
158 |
+
self::CHROME_NOBORDERS => true,
|
159 |
+
self::CHROME_NOSCROLLBAR => true,
|
160 |
+
self::CHROME_TRANSPARENT => true
|
161 |
+
);
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Maximum display width of the widget
|
165 |
+
*
|
166 |
+
* @since 2.0.0
|
167 |
+
*
|
168 |
+
* @type int
|
169 |
+
*/
|
170 |
+
protected $width;
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Maximum display height of the widget
|
174 |
+
*
|
175 |
+
* @since 2.0.0
|
176 |
+
*
|
177 |
+
* @type int
|
178 |
+
*/
|
179 |
+
protected $height;
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Display a specific number of Tweets, disabling auto-pagination of possible results
|
183 |
+
*
|
184 |
+
* @since 2.0.0
|
185 |
+
*
|
186 |
+
* @type int
|
187 |
+
*/
|
188 |
+
protected $limit;
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Display customizations for the widget container
|
192 |
+
*
|
193 |
+
* @since 2.0.0
|
194 |
+
*
|
195 |
+
* @type array {
|
196 |
+
* @type string chrome customization
|
197 |
+
* @type bool unused
|
198 |
+
* }
|
199 |
+
*/
|
200 |
+
protected $chrome = array();
|
201 |
+
|
202 |
+
/**
|
203 |
+
* The politeness / priority of the embedded timeline ARIA live region
|
204 |
+
*
|
205 |
+
* @since 2.0.0
|
206 |
+
*
|
207 |
+
* @link https://www.w3.org/TR/wai-aria/states_and_properties#aria-live
|
208 |
+
*
|
209 |
+
* @type string
|
210 |
+
*/
|
211 |
+
protected $aria_politeness = self::ARIA_POLITE_POLITE;
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Tests a supplied width for validity
|
215 |
+
*
|
216 |
+
* @since 2.0.0
|
217 |
+
*
|
218 |
+
* @param int $width the maximum display width of an embedded timeline in whole pixels
|
219 |
+
*
|
220 |
+
* @return bool true if supplied width is an integer in the range of MIN_WIDTH and MAX_WIDTH inclusive
|
221 |
+
*/
|
222 |
+
public static function isValidWidth($width)
|
223 |
+
{
|
224 |
+
return (is_int($width) && $width>=static::MIN_WIDTH && $width<=static::MAX_WIDTH);
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Set the maximum display width of an embedded timeline in whole pixels
|
229 |
+
*
|
230 |
+
* Must be an integer in the allowed range: 180-1200 inclusive
|
231 |
+
*
|
232 |
+
* @since 2.0.0
|
233 |
+
*
|
234 |
+
* @param int $width the maximum display width of an embedded timeline in whole pixels
|
235 |
+
*
|
236 |
+
* @return self allow chaining
|
237 |
+
*/
|
238 |
+
public function setWidth($width)
|
239 |
+
{
|
240 |
+
if (static::isValidWidth($width)) {
|
241 |
+
$this->width = $width;
|
242 |
+
}
|
243 |
+
|
244 |
+
return $this;
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Tests a supplied height for validity
|
249 |
+
*
|
250 |
+
* @since 2.0.0
|
251 |
+
*
|
252 |
+
* @param int $height height of the embedded timeline in whole pixels
|
253 |
+
*
|
254 |
+
* @return bool true if height is an integer greater than or equal to the minimum allowed height
|
255 |
+
*/
|
256 |
+
public static function isValidHeight($height)
|
257 |
+
{
|
258 |
+
return (is_int($height) && $height>=static::MIN_HEIGHT);
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Set the maximum display height of an embedded timeline in whole pixels
|
263 |
+
*
|
264 |
+
* Must be an integer greater than or equal to MIN_HEIGHT
|
265 |
+
*
|
266 |
+
* @since 2.0.0
|
267 |
+
*
|
268 |
+
* @param int $height the maximum display height of an embedded timeline in whole pixels
|
269 |
+
*
|
270 |
+
* @return self allow chaining
|
271 |
+
*/
|
272 |
+
public function setHeight($height)
|
273 |
+
{
|
274 |
+
if (static::isValidHeight($height)) {
|
275 |
+
$this->height = $height;
|
276 |
+
}
|
277 |
+
|
278 |
+
return $this;
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Tests a supplied limit for validity
|
283 |
+
*
|
284 |
+
* @since 2.0.0
|
285 |
+
*
|
286 |
+
* @param int $limit maximum number of Tweets to display in a timeline without pagination
|
287 |
+
*
|
288 |
+
* @return bool true if supplied limit is an integer and within the allowed range inclusive
|
289 |
+
*/
|
290 |
+
public static function isValidLimit($limit)
|
291 |
+
{
|
292 |
+
return ( is_int($limit) && $limit >=static::MIN_LIMIT && $limit<=static::MAX_LIMIT );
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Set the maximum number of Tweets to display in the embedded timeline
|
297 |
+
*
|
298 |
+
* @param int $limit maximum number of Tweets to display
|
299 |
+
*
|
300 |
+
* @return self support chaining
|
301 |
+
*/
|
302 |
+
public function setLimit($limit)
|
303 |
+
{
|
304 |
+
if (static::isValidLimit($limit)) {
|
305 |
+
$this->limit = $limit;
|
306 |
+
}
|
307 |
+
|
308 |
+
return $this;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Is the provided chrome option supported by embedded timelines?
|
313 |
+
*
|
314 |
+
* @since 2.0.0
|
315 |
+
*
|
316 |
+
* @param string $option chrome option
|
317 |
+
*
|
318 |
+
* @return bool true if provided option is a known chrome option
|
319 |
+
*/
|
320 |
+
public static function isValidChromeOption($option)
|
321 |
+
{
|
322 |
+
return ( $option && isset(static::$CHROME_OPTIONS[$option]) );
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Set chrome preferences from a list of possible chrome tokens
|
327 |
+
*
|
328 |
+
* @since 2.0.0
|
329 |
+
*
|
330 |
+
* @param array $chrome chrome preference tokens {
|
331 |
+
* @type string chrome preference token
|
332 |
+
* @type bool not used
|
333 |
+
* }
|
334 |
+
*
|
335 |
+
* @return self support chaining
|
336 |
+
*/
|
337 |
+
public function setChrome($chrome)
|
338 |
+
{
|
339 |
+
if (! is_array($chrome) || empty($chrome)) {
|
340 |
+
return $this;
|
341 |
+
}
|
342 |
+
|
343 |
+
$keys = null;
|
344 |
+
if (isset($chrome[0])) {
|
345 |
+
$keys = $chrome;
|
346 |
+
} else {
|
347 |
+
$keys = array_keys($chrome);
|
348 |
+
}
|
349 |
+
if ($keys && is_array($keys)) {
|
350 |
+
array_walk($keys, array($this, 'setChromeOption'));
|
351 |
+
}
|
352 |
+
|
353 |
+
return $this;
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Possibly set a chrome array value from a valid passed chrome option
|
358 |
+
*
|
359 |
+
* @since 2.0.0
|
360 |
+
*
|
361 |
+
* @param string $chrome_option chrome option
|
362 |
+
*
|
363 |
+
* @return bool option set
|
364 |
+
*/
|
365 |
+
protected function setChromeOption($chrome_option)
|
366 |
+
{
|
367 |
+
if (is_string($chrome_option)) {
|
368 |
+
$chrome_option = strtolower(trim($chrome_option));
|
369 |
+
if ($chrome_option && static::isValidChromeOption($chrome_option) && ! isset($this->chrome[$chrome_option])) {
|
370 |
+
$this->chrome[$chrome_option] = true;
|
371 |
+
return true;
|
372 |
+
}
|
373 |
+
}
|
374 |
+
|
375 |
+
return false;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Do not include a header component of the embedded timeline
|
380 |
+
*
|
381 |
+
* Sites are expected to include their own header to introduce the datasource and link to its equivalent location on Twitter.com
|
382 |
+
*
|
383 |
+
* @since 2.0.0
|
384 |
+
*
|
385 |
+
* @return self support chaining
|
386 |
+
*/
|
387 |
+
public function hideHeader()
|
388 |
+
{
|
389 |
+
if (! isset($this->chrome[static::CHROME_NOHEADER])) {
|
390 |
+
$this->chrome[static::CHROME_NOHEADER] = true;
|
391 |
+
}
|
392 |
+
|
393 |
+
return $this;
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Include a header component of the embedded timeline (default option)
|
398 |
+
*
|
399 |
+
* @since 2.0.0
|
400 |
+
*
|
401 |
+
* @return self support chaining
|
402 |
+
*/
|
403 |
+
public function showHeader()
|
404 |
+
{
|
405 |
+
unset($this->chrome[static::CHROME_NOHEADER]);
|
406 |
+
|
407 |
+
return $this;
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Do not include a footer component of the embedded timeline
|
412 |
+
*
|
413 |
+
* @since 2.0.0
|
414 |
+
*
|
415 |
+
* @return self support chaining
|
416 |
+
*/
|
417 |
+
public function hideFooter()
|
418 |
+
{
|
419 |
+
if (! isset($this->chrome[static::CHROME_NOFOOTER])) {
|
420 |
+
$this->chrome[static::CHROME_NOFOOTER] = true;
|
421 |
+
}
|
422 |
+
|
423 |
+
return $this;
|
424 |
+
}
|
425 |
+
|
426 |
+
/**
|
427 |
+
* Include a footer component of the embedded timeline (default option)
|
428 |
+
*
|
429 |
+
* @since 2.0.0
|
430 |
+
*
|
431 |
+
* @return self support chaining
|
432 |
+
*/
|
433 |
+
public function showFooter()
|
434 |
+
{
|
435 |
+
unset($this->chrome[static::CHROME_NOFOOTER]);
|
436 |
+
|
437 |
+
return $this;
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* Do not include a border separating Tweets displayed in the embedded timeline
|
442 |
+
*
|
443 |
+
* @since 2.0.0
|
444 |
+
*
|
445 |
+
* @return self support chaining
|
446 |
+
*/
|
447 |
+
public function hideBorders()
|
448 |
+
{
|
449 |
+
if (! isset($this->chrome[static::CHROME_NOBORDERS])) {
|
450 |
+
$this->chrome[static::CHROME_NOBORDERS] = true;
|
451 |
+
}
|
452 |
+
|
453 |
+
return $this;
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Include a border separating Tweets displayed in the embedded timeline (default option)
|
458 |
+
*
|
459 |
+
* @since 2.0.0
|
460 |
+
*
|
461 |
+
* @return self support chaining
|
462 |
+
*/
|
463 |
+
public function showBorders()
|
464 |
+
{
|
465 |
+
unset($this->chrome[static::CHROME_NOBORDERS]);
|
466 |
+
|
467 |
+
return $this;
|
468 |
+
}
|
469 |
+
|
470 |
+
/**
|
471 |
+
* Do not include a footer component of the embedded timeline
|
472 |
+
*
|
473 |
+
* @since 2.0.0
|
474 |
+
*
|
475 |
+
* @return self support chaining
|
476 |
+
*/
|
477 |
+
public function hideScrollbar()
|
478 |
+
{
|
479 |
+
if (! isset($this->chrome[static::CHROME_NOSCROLLBAR])) {
|
480 |
+
$this->chrome[static::CHROME_NOSCROLLBAR] = true;
|
481 |
+
}
|
482 |
+
|
483 |
+
return $this;
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Include a visual scrollbar to assist navigating Tweets in an embedded timeline exceeding the visible widget area (default option)
|
488 |
+
*
|
489 |
+
* @since 2.0.0
|
490 |
+
*
|
491 |
+
* @return self support chaining
|
492 |
+
*/
|
493 |
+
public function showScrollbar()
|
494 |
+
{
|
495 |
+
unset($this->chrome[static::CHROME_NOSCROLLBAR]);
|
496 |
+
|
497 |
+
return $this;
|
498 |
+
}
|
499 |
+
|
500 |
+
/**
|
501 |
+
* Hide the widget theme's background by setting it to transparent
|
502 |
+
*
|
503 |
+
* @since 2.0.0
|
504 |
+
*
|
505 |
+
* @return self support chaining
|
506 |
+
*/
|
507 |
+
public function hideThemeBackground()
|
508 |
+
{
|
509 |
+
if (! isset($this->chrome[static::CHROME_TRANSPARENT])) {
|
510 |
+
$this->chrome[static::CHROME_TRANSPARENT] = true;
|
511 |
+
}
|
512 |
+
|
513 |
+
return $this;
|
514 |
+
}
|
515 |
+
|
516 |
+
/**
|
517 |
+
* Display an embedded timeline with the default background color for the chosen theme (default)
|
518 |
+
*
|
519 |
+
* @since 2.0.0
|
520 |
+
*
|
521 |
+
* @return self support chaining
|
522 |
+
*/
|
523 |
+
public function showThemeBackground()
|
524 |
+
{
|
525 |
+
unset($this->chrome[static::CHROME_TRANSPARENT]);
|
526 |
+
|
527 |
+
return $this;
|
528 |
+
}
|
529 |
+
|
530 |
+
/**
|
531 |
+
* Set an ARIA live region politeness value for the embedded timeline
|
532 |
+
*
|
533 |
+
* @since 2.0.0
|
534 |
+
*
|
535 |
+
* @param string $politeness ARIA live region politeness setting
|
536 |
+
*
|
537 |
+
* @return self support chaining
|
538 |
+
*/
|
539 |
+
public function setAriaLive($politeness)
|
540 |
+
{
|
541 |
+
if (is_string($politeness)) {
|
542 |
+
$politeness = strtolower(trim($politeness));
|
543 |
+
if ($politeness === static::ARIA_POLITE_ASSERTIVE) {
|
544 |
+
$this->setAriaLiveAssertive();
|
545 |
+
}
|
546 |
+
}
|
547 |
+
|
548 |
+
return $this;
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* New Tweets are important enough to be announced to the user as soon as possible, but it is not necessary to immediately interrupt the user
|
553 |
+
*
|
554 |
+
* @since 2.0.0
|
555 |
+
*
|
556 |
+
* @return self support chaining
|
557 |
+
*/
|
558 |
+
public function setAriaLiveAssertive()
|
559 |
+
{
|
560 |
+
$this->aria_politeness = static::ARIA_POLITE_ASSERTIVE;
|
561 |
+
|
562 |
+
return $this;
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Populate base options from a passed associative array
|
567 |
+
*
|
568 |
+
* @since 2.0.0
|
569 |
+
*
|
570 |
+
* @param array $options associative array of options {
|
571 |
+
* @type string option name
|
572 |
+
* @type string|int|bool option value
|
573 |
+
* }
|
574 |
+
*
|
575 |
+
* @return self support chaining
|
576 |
+
*/
|
577 |
+
public function setBaseOptions($options)
|
578 |
+
{
|
579 |
+
parent::setBaseOptions($options);
|
580 |
+
$this->setThemeOptions($options);
|
581 |
+
|
582 |
+
if (isset($options['width']) && $options['width']) {
|
583 |
+
$this->setWidth($options['width']);
|
584 |
+
}
|
585 |
+
|
586 |
+
if (isset($options['aria-polite']) && $options['aria-polite']) {
|
587 |
+
$this->setAriaLive($options['aria-polite']);
|
588 |
+
}
|
589 |
+
|
590 |
+
if (isset($options['limit']) && $options['limit']) {
|
591 |
+
$this->setLimit($options['limit']);
|
592 |
+
} elseif (isset($options['height']) && $options['height']) {
|
593 |
+
$this->setHeight($options['height']);
|
594 |
+
}
|
595 |
+
|
596 |
+
if (isset($options['chrome']) && is_array($options['chrome']) && !empty($options['chrome'])) {
|
597 |
+
$this->setChrome($options['chrome']);
|
598 |
+
}
|
599 |
+
|
600 |
+
return $this;
|
601 |
+
}
|
602 |
+
|
603 |
+
/**
|
604 |
+
* Convert the class object into an array, removing default field values
|
605 |
+
*
|
606 |
+
* @since 2.0.0
|
607 |
+
*
|
608 |
+
* @return array properties as associative array
|
609 |
+
*/
|
610 |
+
public function toArray()
|
611 |
+
{
|
612 |
+
$data = parent::toArray();
|
613 |
+
$data = array_merge($data, $this->themeToArray());
|
614 |
+
|
615 |
+
if (isset($this->width)) {
|
616 |
+
$data['width'] = $this->width;
|
617 |
+
}
|
618 |
+
|
619 |
+
// limit sets height
|
620 |
+
if (isset($this->limit)) {
|
621 |
+
$data['tweet-limit'] = $this->limit;
|
622 |
+
// scroll bar is not used on expanded timeline display triggered by limit
|
623 |
+
unset($this->chrome[static::CHROME_NOSCROLLBAR]);
|
624 |
+
$this->aria_politeness = null;
|
625 |
+
} elseif (isset($this->height)) {
|
626 |
+
$data['height'] = $this->height;
|
627 |
+
}
|
628 |
+
|
629 |
+
if (!empty($this->chrome)) {
|
630 |
+
$data['chrome'] = array_keys($this->chrome);
|
631 |
+
}
|
632 |
+
|
633 |
+
if ($this->aria_politeness && $this->aria_politeness !== static::ARIA_POLITE_POLITE) {
|
634 |
+
$data['aria-polite'] = $this->aria_politeness;
|
635 |
+
}
|
636 |
+
|
637 |
+
return $data;
|
638 |
+
}
|
639 |
+
|
640 |
+
/**
|
641 |
+
* Output timeline as an array suitable for use as oEmbed query parameters
|
642 |
+
*
|
643 |
+
* @since 2.0.0
|
644 |
+
*
|
645 |
+
* @return array profile timeline parameter array {
|
646 |
+
* @type string query parameter name
|
647 |
+
* @type string query parameter value
|
648 |
+
* }
|
649 |
+
*/
|
650 |
+
public function toOEmbedParameterArray()
|
651 |
+
{
|
652 |
+
$query_parameters = parent::toArray();
|
653 |
+
$query_parameters = array_merge($query_parameters, $this->themeToOEmbedParameterArray());
|
654 |
+
|
655 |
+
if (isset($this->width)) {
|
656 |
+
$query_parameters['maxwidth'] = $this->width;
|
657 |
+
}
|
658 |
+
|
659 |
+
if (isset($this->limit)) {
|
660 |
+
$query_parameters['limit'] = $this->limit;
|
661 |
+
// scroll bar is not used on expanded timeline display triggered by limit
|
662 |
+
unset($this->chrome[static::CHROME_NOSCROLLBAR]);
|
663 |
+
$this->aria_politeness = null;
|
664 |
+
} elseif (isset($this->height)) {
|
665 |
+
$query_parameters['maxheight'] = $this->height;
|
666 |
+
}
|
667 |
+
|
668 |
+
if (isset($this->chrome)) {
|
669 |
+
$query_parameters['chrome'] = implode(' ', array_keys($this->chrome));
|
670 |
+
}
|
671 |
+
|
672 |
+
if ($this->aria_politeness && $this->aria_politeness !== static::ARIA_POLITE_POLITE) {
|
673 |
+
$query_parameters['aria_polite'] = $this->aria_politeness;
|
674 |
+
}
|
675 |
+
|
676 |
+
return $query_parameters;
|
677 |
+
}
|
678 |
+
}
|
src/Twitter/Widgets/Embeds/Timeline/Collection.php
ADDED
@@ -0,0 +1,317 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display Tweets inside a collection
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Collection extends \Twitter\Widgets\Embeds\Timeline
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Construct a full Twitter URI by appending to base string
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const BASE_URL = 'https://twitter.com/_/timelines/';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Grid display template
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type string
|
50 |
+
*/
|
51 |
+
const WIDGET_TYPE_GRID = 'grid';
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Fields supported in a vertical template not supported in a grid template
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @type array data-* key, oEmbed value
|
59 |
+
*/
|
60 |
+
public static $FIELDS_NOT_SUPPORTED_IN_GRID = array(
|
61 |
+
'height' => 'maxheight', // auto-expands to limit
|
62 |
+
'aria-polite' => 'aria_polite', // grid is not a live region
|
63 |
+
'theme' => 'theme', // always light text on dark theme
|
64 |
+
'link-color' => 'link_color', // text color
|
65 |
+
'border-color' => 'border_color',
|
66 |
+
);
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Collection unique identifier
|
70 |
+
*
|
71 |
+
* @since 2.0.0
|
72 |
+
*
|
73 |
+
* @type string
|
74 |
+
*/
|
75 |
+
protected $id;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* The display template used to display Tweets in the collection
|
79 |
+
*
|
80 |
+
* @since 2.0.0
|
81 |
+
*
|
82 |
+
* @type string
|
83 |
+
*/
|
84 |
+
protected $widget_type;
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Create a new collection object
|
88 |
+
*
|
89 |
+
* @since 2.0.0
|
90 |
+
*
|
91 |
+
* @param string $id unique identifier of the collection
|
92 |
+
*/
|
93 |
+
public function __construct($id)
|
94 |
+
{
|
95 |
+
if (is_string($id) && $id) {
|
96 |
+
$this->setID($id);
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Test ID validity
|
102 |
+
*
|
103 |
+
* @since 2.0.0
|
104 |
+
*
|
105 |
+
* @link https://dev.twitter.com/overview/api/twitter-ids-json-and-snowflake
|
106 |
+
*
|
107 |
+
* @param string $id snowflake ID
|
108 |
+
*
|
109 |
+
* @return bool true if valid snowflake ID
|
110 |
+
*/
|
111 |
+
public static function isValidSnowflakeID($id)
|
112 |
+
{
|
113 |
+
if (is_string($id)) {
|
114 |
+
if (function_exists('ctype_digit')) {
|
115 |
+
return ctype_digit($id);
|
116 |
+
} else {
|
117 |
+
return (bool) (preg_match("/^[0-9]+$/", $id));
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
return false;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Get the unique collection identifier
|
126 |
+
*
|
127 |
+
* @since 2.0.0
|
128 |
+
*
|
129 |
+
* @return string the unique collection identifier or empty string if not set
|
130 |
+
*/
|
131 |
+
public function getID()
|
132 |
+
{
|
133 |
+
return $this->id ?: '';
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Set the unique identifier of the collection
|
138 |
+
*
|
139 |
+
* @since 2.0.0
|
140 |
+
*
|
141 |
+
* @param string $id unique identifier of the collection
|
142 |
+
*
|
143 |
+
* @return self support chaining
|
144 |
+
*/
|
145 |
+
public function setID($id)
|
146 |
+
{
|
147 |
+
if (is_string($id)) {
|
148 |
+
$id = trim($id);
|
149 |
+
if (static::isValidSnowflakeID($id)) {
|
150 |
+
$this->id = $id;
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
return $this;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Twitter collection URL
|
159 |
+
*
|
160 |
+
* @since 2.0.0
|
161 |
+
*
|
162 |
+
* @return string Twitter collection URL or empty string if no ID set
|
163 |
+
*/
|
164 |
+
public function getURL()
|
165 |
+
{
|
166 |
+
if ($this->id) {
|
167 |
+
return static::BASE_URL . $this->id;
|
168 |
+
}
|
169 |
+
|
170 |
+
return '';
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Use the grid display template
|
175 |
+
*
|
176 |
+
* @since 2.0.0
|
177 |
+
*
|
178 |
+
* @return self support chaining
|
179 |
+
*/
|
180 |
+
public function setGridTemplate()
|
181 |
+
{
|
182 |
+
$this->widget_type = static::WIDGET_TYPE_GRID;
|
183 |
+
|
184 |
+
return $this;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Create a collection object from an associative array
|
189 |
+
*
|
190 |
+
* @since 2.0.0
|
191 |
+
*
|
192 |
+
* @param array $options {
|
193 |
+
* @type string parameter name
|
194 |
+
* @type string|int|bool parameter value
|
195 |
+
* }
|
196 |
+
*
|
197 |
+
* @return self|null new Collection object with configured properties
|
198 |
+
*/
|
199 |
+
public static function fromArray($options)
|
200 |
+
{
|
201 |
+
// id required
|
202 |
+
if (! (is_array($options) && isset($options['id']))) {
|
203 |
+
return null;
|
204 |
+
}
|
205 |
+
|
206 |
+
if (! (is_string($options['id']) && $options['id'])) {
|
207 |
+
return null;
|
208 |
+
}
|
209 |
+
|
210 |
+
$class = get_called_class();
|
211 |
+
$timeline = new $class( $options['id'] );
|
212 |
+
unset($class);
|
213 |
+
unset($options['id']);
|
214 |
+
|
215 |
+
if (method_exists($timeline, 'setBaseOptions')) {
|
216 |
+
$timeline->setBaseOptions($options);
|
217 |
+
}
|
218 |
+
|
219 |
+
if (isset($options['widget_type']) && static::WIDGET_TYPE_GRID === $options['widget_type']) {
|
220 |
+
if (method_exists($timeline, 'setGridTemplate')) {
|
221 |
+
$timeline->setGridTemplate();
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
return $timeline;
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Return collection parameters suitable for conversion to data-*
|
230 |
+
*
|
231 |
+
* @since 2.0.0
|
232 |
+
*
|
233 |
+
* @return array collection parameter array {
|
234 |
+
* @type string dashed parameter name
|
235 |
+
* @type string parameter value
|
236 |
+
* }
|
237 |
+
*/
|
238 |
+
public function toArray()
|
239 |
+
{
|
240 |
+
$data = parent::toArray();
|
241 |
+
|
242 |
+
if ($this->id) {
|
243 |
+
$data['id'] = $this->id;
|
244 |
+
} else {
|
245 |
+
return array();
|
246 |
+
}
|
247 |
+
|
248 |
+
if ($this->widget_type) {
|
249 |
+
if (static::WIDGET_TYPE_GRID === $this->widget_type) {
|
250 |
+
$data['widget-type'] = $this->widget_type;
|
251 |
+
|
252 |
+
$unsupported_fields = array_keys(static::$FIELDS_NOT_SUPPORTED_IN_GRID);
|
253 |
+
|
254 |
+
foreach ($unsupported_fields as $key) {
|
255 |
+
unset($data[$key]);
|
256 |
+
}
|
257 |
+
|
258 |
+
// only footer applies. footer is transparent
|
259 |
+
if (array_key_exists(static::CHROME_NOFOOTER, $this->chrome)) {
|
260 |
+
$data['chrome'] = array(static::CHROME_NOFOOTER);
|
261 |
+
} else {
|
262 |
+
unset($data['chrome']);
|
263 |
+
}
|
264 |
+
|
265 |
+
// grid parameter differs from standard timeline parameter
|
266 |
+
if (array_key_exists('tweet-limit', $data)) {
|
267 |
+
$data['limit'] = $data['tweet-limit'];
|
268 |
+
unset($data['tweet-limit']);
|
269 |
+
}
|
270 |
+
}
|
271 |
+
}
|
272 |
+
|
273 |
+
return $data;
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Output timeline as an array suitable for use as oEmbed query parameters
|
278 |
+
*
|
279 |
+
* @since 2.0.0
|
280 |
+
*
|
281 |
+
* @return array collection parameter array {
|
282 |
+
* @type string query parameter name
|
283 |
+
* @type string query parameter value
|
284 |
+
* }
|
285 |
+
*/
|
286 |
+
public function toOEmbedParameterArray()
|
287 |
+
{
|
288 |
+
$query_parameters = parent::toOEmbedParameterArray();
|
289 |
+
|
290 |
+
$url = $this->getURL();
|
291 |
+
if (! $url) {
|
292 |
+
return array();
|
293 |
+
}
|
294 |
+
$query_parameters['url'] = $url;
|
295 |
+
|
296 |
+
if ($this->widget_type) {
|
297 |
+
if (static::WIDGET_TYPE_GRID === $this->widget_type) {
|
298 |
+
$query_parameters['widget_type'] = static::WIDGET_TYPE_GRID;
|
299 |
+
|
300 |
+
$unsupported_parameters = array_values(static::$FIELDS_NOT_SUPPORTED_IN_GRID);
|
301 |
+
foreach ($unsupported_parameters as $key) {
|
302 |
+
unset($query_parameters[$key]);
|
303 |
+
}
|
304 |
+
unset($unsupported_parameters);
|
305 |
+
|
306 |
+
// only footer applies. footer is transparent
|
307 |
+
if (array_key_exists(static::CHROME_NOFOOTER, $this->chrome)) {
|
308 |
+
$query_parameters['chrome'] = array(static::CHROME_NOFOOTER);
|
309 |
+
} else {
|
310 |
+
unset($query_parameters['chrome']);
|
311 |
+
}
|
312 |
+
}
|
313 |
+
}
|
314 |
+
|
315 |
+
return $query_parameters;
|
316 |
+
}
|
317 |
+
}
|
src/Twitter/Widgets/Embeds/Timeline/Profile.php
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display the latest Tweets from a Twitter user / profile
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Profile extends \Twitter\Widgets\Embeds\Timeline
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Construct a full Twitter URI by appending to base string
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const BASE_URL = 'https://twitter.com/';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Twitter handle
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type string
|
50 |
+
*/
|
51 |
+
protected $screen_name;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Create a new profile timeline for a given screen name
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @param string $screen_name Twitter handle
|
59 |
+
*/
|
60 |
+
public function __construct($screen_name)
|
61 |
+
{
|
62 |
+
$this->setScreenName($screen_name);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get the Twitter handle associated with the object
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @return string Twitter handle or empty string if not set
|
71 |
+
*/
|
72 |
+
public function getScreenName()
|
73 |
+
{
|
74 |
+
return $this->screen_name ?: '';
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Set the Twitter handle
|
79 |
+
*
|
80 |
+
* @since 2.0.0
|
81 |
+
*
|
82 |
+
* @param string $screen_name Twitter username / screen name
|
83 |
+
*
|
84 |
+
* @return self support chaining
|
85 |
+
*/
|
86 |
+
public function setScreenName($screen_name)
|
87 |
+
{
|
88 |
+
$screen_name = \Twitter\Helpers\Validators\ScreenName::sanitize($screen_name);
|
89 |
+
if ($screen_name) {
|
90 |
+
$this->screen_name = $screen_name;
|
91 |
+
}
|
92 |
+
|
93 |
+
return $this;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Twitter profile URL
|
98 |
+
*
|
99 |
+
* @since 2.0.0
|
100 |
+
*
|
101 |
+
* @return string Twitter profile URL or empty string if no screen_name set
|
102 |
+
*/
|
103 |
+
public function getURL()
|
104 |
+
{
|
105 |
+
if ($this->screen_name) {
|
106 |
+
return static::BASE_URL . $this->screen_name;
|
107 |
+
}
|
108 |
+
|
109 |
+
return '';
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Create a profile timeline object from an associative array
|
114 |
+
*
|
115 |
+
* @since 2.0.0
|
116 |
+
*
|
117 |
+
* @param array $options {
|
118 |
+
* @type string parameter name
|
119 |
+
* @type string|int|bool parameter value
|
120 |
+
* }
|
121 |
+
*
|
122 |
+
* @return self|null new Profile object with configured properties
|
123 |
+
*/
|
124 |
+
public static function fromArray($options)
|
125 |
+
{
|
126 |
+
// screen_name required
|
127 |
+
if (! (is_array($options) && isset($options['screen_name']))) {
|
128 |
+
return null;
|
129 |
+
}
|
130 |
+
|
131 |
+
if (! (is_string($options['screen_name']) && $options['screen_name'])) {
|
132 |
+
return null;
|
133 |
+
}
|
134 |
+
|
135 |
+
$class = get_called_class();
|
136 |
+
$timeline = new $class( $options['screen_name'] );
|
137 |
+
unset($class);
|
138 |
+
unset($options['screen_name']);
|
139 |
+
|
140 |
+
if (method_exists($timeline, 'setBaseOptions')) {
|
141 |
+
$timeline->setBaseOptions($options);
|
142 |
+
}
|
143 |
+
|
144 |
+
return $timeline;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Return profile timeline parameters suitable for conversion to data-*
|
149 |
+
*
|
150 |
+
* @since 2.0.0
|
151 |
+
*
|
152 |
+
* @return array profile timeline parameter array {
|
153 |
+
* @type string dashed parameter name
|
154 |
+
* @type string parameter value
|
155 |
+
* }
|
156 |
+
*/
|
157 |
+
public function toArray()
|
158 |
+
{
|
159 |
+
$data = parent::toArray();
|
160 |
+
|
161 |
+
if ($this->screen_name) {
|
162 |
+
$data['screen-name'] = $this->screen_name;
|
163 |
+
} else {
|
164 |
+
return array();
|
165 |
+
}
|
166 |
+
|
167 |
+
return $data;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Output timeline as an array suitable for use as oEmbed query parameters
|
172 |
+
*
|
173 |
+
* @since 2.0.0
|
174 |
+
*
|
175 |
+
* @return array profile timeline parameter array {
|
176 |
+
* @type string query parameter name
|
177 |
+
* @type string query parameter value
|
178 |
+
* }
|
179 |
+
*/
|
180 |
+
public function toOEmbedParameterArray()
|
181 |
+
{
|
182 |
+
$data = parent::toOEmbedParameterArray();
|
183 |
+
|
184 |
+
$url = $this->getURL();
|
185 |
+
if (! $url) {
|
186 |
+
return array();
|
187 |
+
}
|
188 |
+
$data['url'] = $url;
|
189 |
+
|
190 |
+
return $data;
|
191 |
+
}
|
192 |
+
}
|
src/Twitter/Widgets/Embeds/Timeline/Search.php
ADDED
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2017 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display Tweets published within the last ~7 days for a given widget ID
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Search extends \Twitter\Widgets\Embeds\Timeline
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* HTML class expected by the Twitter widget JS
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const HTML_CLASS = 'twitter-timeline';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Construct a full Twitter URI by appending to base string
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type string
|
50 |
+
*/
|
51 |
+
const BASE_URL = 'https://twitter.com/search';
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Twitter widgets setting URL including a widget ID as a path component
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @type string
|
59 |
+
*/
|
60 |
+
const SETTINGS_URL_REGEX = '#^https://twitter\.com/settings/widgets/([0-9]+)/edit$#i';
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Widget ID configured on Twitter.com
|
64 |
+
*
|
65 |
+
* @since 2.0.0
|
66 |
+
*
|
67 |
+
* @see https://twitter.com/settings/widgets/new/search Search widget configuration
|
68 |
+
*
|
69 |
+
* @type string
|
70 |
+
*/
|
71 |
+
protected $widget_id;
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Search terms set in the widget ID
|
75 |
+
*
|
76 |
+
* Used to construct a meaningful link to a search results page and relevant link text.
|
77 |
+
*
|
78 |
+
* @since 2.0.0
|
79 |
+
*
|
80 |
+
* @type string
|
81 |
+
*/
|
82 |
+
protected $search_terms;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Create a new search timeline widget with a required widget ID and optional search terms
|
86 |
+
*
|
87 |
+
* @since 2.0.0
|
88 |
+
*
|
89 |
+
* @param string $widget_id widget identifier
|
90 |
+
* @param string $search_terms (optional) search terms for display in link
|
91 |
+
*/
|
92 |
+
public function __construct($widget_id, $search_terms = '')
|
93 |
+
{
|
94 |
+
$this->setWidgetID($widget_id);
|
95 |
+
if ($search_terms) {
|
96 |
+
$this->setSearchTerms($search_terms);
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Extract a widget ID from a Twitter.com widgets setting URL
|
102 |
+
*
|
103 |
+
* @since 2.0.0
|
104 |
+
*
|
105 |
+
* @param string $url Twitter.com widgets setting URL
|
106 |
+
*
|
107 |
+
* @return string widget ID or empty string if none found
|
108 |
+
*/
|
109 |
+
public static function getWidgetIDFromSettingsURL($url)
|
110 |
+
{
|
111 |
+
if (! (is_string($url) && $url)) {
|
112 |
+
return '';
|
113 |
+
}
|
114 |
+
$url = trim($url);
|
115 |
+
$matches = array();
|
116 |
+
preg_match(static::SETTINGS_URL_REGEX, $url, $matches);
|
117 |
+
if (is_array($matches) && isset($matches[1]) && $matches[1]) {
|
118 |
+
return $matches[1];
|
119 |
+
}
|
120 |
+
|
121 |
+
return '';
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Test widget ID validity
|
126 |
+
*
|
127 |
+
* @since 2.0.0
|
128 |
+
*
|
129 |
+
* @param string $id widget ID
|
130 |
+
*
|
131 |
+
* @return bool true if valid widget ID
|
132 |
+
*/
|
133 |
+
public static function isValidWidgetID($id)
|
134 |
+
{
|
135 |
+
if (is_string($id)) {
|
136 |
+
if (function_exists('ctype_digit')) {
|
137 |
+
return ctype_digit($id);
|
138 |
+
} else {
|
139 |
+
return (bool) (preg_match("/^[0-9]+$/", $id));
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
return false;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Get a widget ID corresponding to a saved search
|
148 |
+
*
|
149 |
+
* @since 2.0.0
|
150 |
+
*
|
151 |
+
* @return string widget ID if set else empty string
|
152 |
+
*/
|
153 |
+
public function getWidgetID()
|
154 |
+
{
|
155 |
+
return $this->widget_id ?: '';
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Set a widget ID corresponding to a saved search
|
160 |
+
*
|
161 |
+
* @since 2.0.0
|
162 |
+
*
|
163 |
+
* @param string $widget_id widget identifier
|
164 |
+
*
|
165 |
+
* @return self support chaining
|
166 |
+
*/
|
167 |
+
public function setWidgetID($widget_id)
|
168 |
+
{
|
169 |
+
if (is_string($widget_id)) {
|
170 |
+
$widget_id = trim($widget_id);
|
171 |
+
if (static::isValidWidgetID($widget_id)) {
|
172 |
+
$this->widget_id = $widget_id;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
return $this;
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Get search terms for more meaningful fallback display
|
181 |
+
*
|
182 |
+
* Should match the search terms stored for the widget ID. Does not affect rendered widget
|
183 |
+
*
|
184 |
+
* @since 2.0.0
|
185 |
+
*
|
186 |
+
* @return string search terms or empty string if no search terms set
|
187 |
+
*/
|
188 |
+
public function getSearchTerms()
|
189 |
+
{
|
190 |
+
return $this->search_terms ?: '';
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Set search terms used by markup builder for more meaningful fallback display
|
195 |
+
*
|
196 |
+
* Should match search terms stored for the widget ID. Does not affect rendered widget.
|
197 |
+
*
|
198 |
+
* @since 2.0.0
|
199 |
+
*
|
200 |
+
* @param string $terms search terms
|
201 |
+
*
|
202 |
+
* @return self support chaining
|
203 |
+
*/
|
204 |
+
public function setSearchTerms($terms)
|
205 |
+
{
|
206 |
+
if (is_string($terms)) {
|
207 |
+
$terms = trim($terms);
|
208 |
+
if ($terms) {
|
209 |
+
$this->search_terms = $terms;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
|
213 |
+
return $this;
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Build a URL to a Twitter search page, with terms if set
|
218 |
+
*
|
219 |
+
* @since 2.0.0
|
220 |
+
*
|
221 |
+
* @return string Twitter search URL
|
222 |
+
*/
|
223 |
+
public function getURL()
|
224 |
+
{
|
225 |
+
$url = static::BASE_URL;
|
226 |
+
$search_terms = $this->getSearchTerms();
|
227 |
+
if ($search_terms) {
|
228 |
+
$url .= '?' . http_build_query(
|
229 |
+
array( 'q' => $search_terms ),
|
230 |
+
'',
|
231 |
+
'&',
|
232 |
+
PHP_QUERY_RFC3986
|
233 |
+
);
|
234 |
+
}
|
235 |
+
|
236 |
+
return $url;
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Create a search timeline object from an associative array
|
241 |
+
*
|
242 |
+
* @since 2.0.0
|
243 |
+
*
|
244 |
+
* @param array $options {
|
245 |
+
* @type string parameter name
|
246 |
+
* @type string|int|bool parameter value
|
247 |
+
* }
|
248 |
+
*
|
249 |
+
* @return self|null new Search object with configured properties or null if minimum requirements not met
|
250 |
+
*/
|
251 |
+
public static function fromArray($options)
|
252 |
+
{
|
253 |
+
// widget ID required
|
254 |
+
if (! (is_array($options) && isset($options['widget_id']))) {
|
255 |
+
return null;
|
256 |
+
}
|
257 |
+
|
258 |
+
if (! (is_string($options['widget_id']) && $options['widget_id'])) {
|
259 |
+
return null;
|
260 |
+
}
|
261 |
+
// parse a widget ID from a Twitter.com widget settings URL
|
262 |
+
if (strlen($options['widget_id']) > 7 && 0 === substr_compare('https://', $options['widget_id'], 0, 8, true)) {
|
263 |
+
$options['widget_id'] = static::getWidgetIDFromSettingsURL($options['widget_id']);
|
264 |
+
if (!$options['widget_id']) {
|
265 |
+
return null;
|
266 |
+
}
|
267 |
+
}
|
268 |
+
|
269 |
+
$search_terms = '';
|
270 |
+
if (isset($options['terms']) && is_string($options['terms']) && $options['terms']) {
|
271 |
+
$search_terms = $options['terms'];
|
272 |
+
}
|
273 |
+
|
274 |
+
$class = get_called_class();
|
275 |
+
$timeline = new $class( $options['widget_id'], $search_terms );
|
276 |
+
|
277 |
+
if (method_exists($timeline, 'setBaseOptions')) {
|
278 |
+
$timeline->setBaseOptions($options);
|
279 |
+
}
|
280 |
+
|
281 |
+
return $timeline;
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Convert the class object into an array, removing default field values
|
286 |
+
*
|
287 |
+
* @since 2.0.0
|
288 |
+
*
|
289 |
+
* @return array properties as associative array
|
290 |
+
*/
|
291 |
+
public function toArray()
|
292 |
+
{
|
293 |
+
$data = parent::toArray();
|
294 |
+
|
295 |
+
if ($this->widget_id) {
|
296 |
+
$data['widget-id'] = $this->widget_id;
|
297 |
+
}
|
298 |
+
|
299 |
+
// always include theme value. may override value stored with widget
|
300 |
+
if ($this->theme) {
|
301 |
+
$data['theme'] = $this->theme;
|
302 |
+
}
|
303 |
+
|
304 |
+
return $data;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Disabled. oEmbed is not supported for a search timeline widget
|
309 |
+
*
|
310 |
+
* @since 2.0.0
|
311 |
+
*
|
312 |
+
* @return array empty array
|
313 |
+
*/
|
314 |
+
public function toOEmbedParameterArray()
|
315 |
+
{
|
316 |
+
// not supported
|
317 |
+
return array();
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* Generate HTML as fallback markup for the Twitter for Websites JavaScript
|
322 |
+
*
|
323 |
+
* @since 2.0.0
|
324 |
+
*
|
325 |
+
* @param string $anchor_text inner text of the generated anchor element. Supports a single '%s' screen name passed through sprintf. Default: Follow %s
|
326 |
+
* @param string $html_builder_class callable HTML builder with a static anchorElement class
|
327 |
+
*
|
328 |
+
* @return string HTML markup or empty string if minimum requirements not met
|
329 |
+
*/
|
330 |
+
public function toHTML($anchor_text = 'Tweets about %s', $html_builder_class = '\Twitter\Helpers\HTMLBuilder')
|
331 |
+
{
|
332 |
+
if (! ( is_string($anchor_text) && $anchor_text )) {
|
333 |
+
return '';
|
334 |
+
}
|
335 |
+
|
336 |
+
// test for invalid passed class
|
337 |
+
if (! ( class_exists($html_builder_class) && method_exists($html_builder_class, 'anchorElement') )) {
|
338 |
+
return '';
|
339 |
+
}
|
340 |
+
|
341 |
+
$search_url = $this->getURL();
|
342 |
+
$search_terms = $this->getSearchTerms();
|
343 |
+
if ($search_terms) {
|
344 |
+
$anchor_text = sprintf($anchor_text, $search_terms);
|
345 |
+
} else {
|
346 |
+
$anchor_text = 'Twitter Search';
|
347 |
+
}
|
348 |
+
|
349 |
+
return $html_builder_class::anchorElement(
|
350 |
+
$search_url,
|
351 |
+
$anchor_text,
|
352 |
+
array(
|
353 |
+
'class' => static::HTML_CLASS,
|
354 |
+
),
|
355 |
+
$this->toArray()
|
356 |
+
);
|
357 |
+
}
|
358 |
+
}
|
src/Twitter/Widgets/Embeds/Timeline/TwitterList.php
ADDED
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2015 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display the latest Tweets from multiple Twitter users
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class TwitterList extends Profile
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Short name of the list. Unique by list owner
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
protected $slug;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Create a new list timeline for a given owner screen name and list slug
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @param string $screen_name Twitter handle
|
50 |
+
* @param string $slug Slug unique to the owner's account
|
51 |
+
*/
|
52 |
+
public function __construct($screen_name, $slug)
|
53 |
+
{
|
54 |
+
parent::__construct($screen_name);
|
55 |
+
|
56 |
+
if ($this->screen_name) {
|
57 |
+
$this->setSlug($slug);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Test a supplied slug string for expected characters and length
|
63 |
+
*
|
64 |
+
* @since 2.0.0
|
65 |
+
*
|
66 |
+
* @param string $slug unique text identifier
|
67 |
+
*
|
68 |
+
* @return bool true if valid list slug
|
69 |
+
*/
|
70 |
+
public static function isValidSlug($slug)
|
71 |
+
{
|
72 |
+
return (bool) preg_match('/^[a-z][a-z0-9_\\-]{0,24}$/i', $slug);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Get the list short name
|
77 |
+
*
|
78 |
+
* @since 2.0.0
|
79 |
+
*
|
80 |
+
* @return string list slug or empty string if no slug set
|
81 |
+
*/
|
82 |
+
public function getSlug()
|
83 |
+
{
|
84 |
+
return $this->slug ?: '';
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Set the unique identifier for the list
|
89 |
+
*
|
90 |
+
* @since 2.0.0
|
91 |
+
*
|
92 |
+
* @param string $slug unique text identifier
|
93 |
+
*
|
94 |
+
* @return self support chaining
|
95 |
+
*/
|
96 |
+
public function setSlug($slug)
|
97 |
+
{
|
98 |
+
if (is_string($slug) && $slug) {
|
99 |
+
$slug = trim($slug);
|
100 |
+
if (static::isValidSlug($slug)) {
|
101 |
+
$this->slug = $slug;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
return $this;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Twitter list URL
|
110 |
+
*
|
111 |
+
* @since 2.0.0
|
112 |
+
*
|
113 |
+
* @return string Twitter list URL or empty string if no screen_name or slug set
|
114 |
+
*/
|
115 |
+
public function getURL()
|
116 |
+
{
|
117 |
+
if ($this->screen_name && $this->slug) {
|
118 |
+
$url = parent::getURL();
|
119 |
+
if ($url) {
|
120 |
+
return $url . '/lists/' . $this->slug;
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
return '';
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Create a list timeline object from an associative array
|
129 |
+
*
|
130 |
+
* @since 2.0.0
|
131 |
+
*
|
132 |
+
* @param array $options {
|
133 |
+
* @type string parameter name
|
134 |
+
* @type string|int|bool parameter value
|
135 |
+
* }
|
136 |
+
*
|
137 |
+
* @return self|null new List object with configured properties
|
138 |
+
*/
|
139 |
+
public static function fromArray($options)
|
140 |
+
{
|
141 |
+
// screen-name required
|
142 |
+
if (! (is_array($options) && isset($options['screen_name']) && isset($options['slug']) )) {
|
143 |
+
return null;
|
144 |
+
}
|
145 |
+
|
146 |
+
$screen_name = null;
|
147 |
+
$slug = null;
|
148 |
+
if (is_string($options['screen_name']) && $options['screen_name']) {
|
149 |
+
$screen_name = $options['screen_name'];
|
150 |
+
if (is_string($options['slug']) && $options['slug']) {
|
151 |
+
$slug = $options['slug'];
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
if (! ($screen_name && $slug)) {
|
156 |
+
return null;
|
157 |
+
}
|
158 |
+
|
159 |
+
unset($options['screen_name']);
|
160 |
+
unset($options['slug']);
|
161 |
+
|
162 |
+
$class = __CLASS__;
|
163 |
+
$timeline = new $class( $screen_name, $slug );
|
164 |
+
unset($class);
|
165 |
+
|
166 |
+
if (method_exists($timeline, 'setBaseOptions')) {
|
167 |
+
$timeline->setBaseOptions($options);
|
168 |
+
}
|
169 |
+
|
170 |
+
return $timeline;
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Return list timeline parameters suitable for conversion to data-*
|
175 |
+
*
|
176 |
+
* @since 2.0.0
|
177 |
+
*
|
178 |
+
* @return array list timeline parameter array {
|
179 |
+
* @type string dashed parameter name
|
180 |
+
* @type string parameter value
|
181 |
+
* }
|
182 |
+
*/
|
183 |
+
public function toArray()
|
184 |
+
{
|
185 |
+
$data = parent::toArray();
|
186 |
+
|
187 |
+
if (!isset($data['screen-name'])) {
|
188 |
+
return array();
|
189 |
+
}
|
190 |
+
|
191 |
+
if ($this->slug) {
|
192 |
+
$data['slug'] = $this->slug;
|
193 |
+
} else {
|
194 |
+
return array();
|
195 |
+
}
|
196 |
+
|
197 |
+
return $data;
|
198 |
+
}
|
199 |
+
}
|
src/Twitter/Widgets/Embeds/Tweet.php
ADDED
@@ -0,0 +1,344 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a Tweet
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Tweet extends \Twitter\Widgets\Embeds\Tweet\Base
|
34 |
+
{
|
35 |
+
use \Twitter\Widgets\Embeds\Theme;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* The Tweet is not floated
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const ALIGN_NONE = 'none';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Tweet is floated to the left. Content flows on the right side of the Tweet
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const ALIGN_LEFT = 'left';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Tweet is floated to the right. Content flows on the left side of the Tweet
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type string
|
61 |
+
*/
|
62 |
+
const ALIGN_RIGHT = 'right';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Tweet is aligned center
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @type string
|
70 |
+
*/
|
71 |
+
const ALIGN_CENTER = 'center';
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Minimum allowed width
|
75 |
+
*
|
76 |
+
* @since 2.0.0
|
77 |
+
*
|
78 |
+
* @type int
|
79 |
+
*/
|
80 |
+
const MIN_WIDTH = 220;
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Maximum allowed width
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @type int
|
88 |
+
*/
|
89 |
+
const MAX_WIDTH = 550;
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Maximum width of the Tweet
|
93 |
+
*
|
94 |
+
* @since 2.0.0
|
95 |
+
*
|
96 |
+
* @type int
|
97 |
+
*/
|
98 |
+
protected $width;
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Display photos, videos, and link previews cited in the Tweet
|
102 |
+
*
|
103 |
+
* @since 2.0.0
|
104 |
+
*
|
105 |
+
* @type string
|
106 |
+
*/
|
107 |
+
protected $cards = true;
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Display the parent Tweet if the Tweet is in response to another Tweet
|
111 |
+
*
|
112 |
+
* @since 2.0.0
|
113 |
+
*
|
114 |
+
* @type string
|
115 |
+
*/
|
116 |
+
protected $conversation = true;
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Float the Tweet relative to the parent element
|
120 |
+
*
|
121 |
+
* @since 2.0.0
|
122 |
+
*
|
123 |
+
* @link https://www.w3.org/wiki/CSS/Properties/float float CSS property
|
124 |
+
*
|
125 |
+
* @type string
|
126 |
+
*/
|
127 |
+
protected $align = 'none';
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Allowed values for align property
|
131 |
+
*
|
132 |
+
* @since 2.0.0
|
133 |
+
*
|
134 |
+
* @type array
|
135 |
+
*/
|
136 |
+
public static $ALLOWED_ALIGN_VALUES = array(
|
137 |
+
self::ALIGN_LEFT => true,
|
138 |
+
self::ALIGN_RIGHT => true,
|
139 |
+
self::ALIGN_CENTER => true,
|
140 |
+
self::ALIGN_NONE => true,
|
141 |
+
);
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Set the fixed maximum used width of the widget display area
|
145 |
+
*
|
146 |
+
* @since 2.0.0
|
147 |
+
*
|
148 |
+
* @link https://www.w3.org/wiki/CSS/Properties/max-width CSS max-width
|
149 |
+
*
|
150 |
+
* @param int $width width of the embed
|
151 |
+
*
|
152 |
+
* @return \Twitter\Widgets\Embeds\Tweet support chaining
|
153 |
+
*/
|
154 |
+
public function setWidth($width)
|
155 |
+
{
|
156 |
+
if (is_int($width) && $width >= static::MIN_WIDTH && $width <= static::MAX_WIDTH) {
|
157 |
+
$this->width = $width;
|
158 |
+
}
|
159 |
+
|
160 |
+
return $this;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Show photos, videos, and link previews cited in the Tweet
|
165 |
+
*
|
166 |
+
* @since 2.0.0
|
167 |
+
*
|
168 |
+
* @return \Twitter\Widgets\Embeds\Tweet support chaining
|
169 |
+
*/
|
170 |
+
public function showCards()
|
171 |
+
{
|
172 |
+
$this->cards = true;
|
173 |
+
|
174 |
+
return $this;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Hide photos, videos, and link previews cited in the Tweet
|
179 |
+
*
|
180 |
+
* @since 2.0.0
|
181 |
+
*
|
182 |
+
* @return \Twitter\Widgets\Embeds\Tweet support chaining
|
183 |
+
*/
|
184 |
+
public function hideCards()
|
185 |
+
{
|
186 |
+
$this->cards = false;
|
187 |
+
|
188 |
+
return $this;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Show the parent Tweet if the Tweet is in response to another Tweet
|
193 |
+
*
|
194 |
+
* @since 2.0.0
|
195 |
+
*
|
196 |
+
* @return \Twitter\Widgets\Embeds\Tweet support chaining
|
197 |
+
*/
|
198 |
+
public function showParentTweet()
|
199 |
+
{
|
200 |
+
$this->conversation = true;
|
201 |
+
|
202 |
+
return $this;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Hide the parent Tweet if the Tweet is in response to another Tweet
|
207 |
+
*
|
208 |
+
* @since 2.0.0
|
209 |
+
*
|
210 |
+
* @return \Twitter\Widgets\Embeds\Tweet support chaining
|
211 |
+
*/
|
212 |
+
public function hideParentTweet()
|
213 |
+
{
|
214 |
+
$this->conversation = false;
|
215 |
+
|
216 |
+
return $this;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Set the float alignment of the Tweet
|
221 |
+
*
|
222 |
+
* @since 2.0.0
|
223 |
+
*
|
224 |
+
* @param string $align alignment of the Tweet embed in the container
|
225 |
+
*
|
226 |
+
* @return \Twitter\Widgets\Embeds\Tweet support chaining
|
227 |
+
*/
|
228 |
+
public function setAlign($align)
|
229 |
+
{
|
230 |
+
if (is_string($align)) {
|
231 |
+
$align = strtolower(trim($align));
|
232 |
+
if ($align && isset(static::$ALLOWED_ALIGN_VALUES[$align])) {
|
233 |
+
$this->align = $align;
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
return $this;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Create a new Tweet object from an associative array of properties
|
242 |
+
*
|
243 |
+
* @since 2.0.0
|
244 |
+
*
|
245 |
+
* @param array $options associative array of options {
|
246 |
+
* @type string option key
|
247 |
+
* @type string|bool option value
|
248 |
+
* }
|
249 |
+
*
|
250 |
+
* @return static|null Tweet object or null if minimum requirements not met
|
251 |
+
*/
|
252 |
+
public static function fromArray($options)
|
253 |
+
{
|
254 |
+
$tweet = parent::fromArray($options);
|
255 |
+
if (! $tweet) {
|
256 |
+
return null;
|
257 |
+
}
|
258 |
+
|
259 |
+
$tweet->setThemeOptions($options);
|
260 |
+
|
261 |
+
if (isset($options['width'])) {
|
262 |
+
$tweet->setWidth($options['width']);
|
263 |
+
}
|
264 |
+
|
265 |
+
if (isset($options['cards']) && ( false === $options['cards'] || 'false' === $options['cards'] || 0 == $options['cards'] )) {
|
266 |
+
$tweet->hideCards();
|
267 |
+
}
|
268 |
+
if (isset($options['conversation']) && ( false === $options['conversation'] || 'false' === $options['conversation'] || 0 == $options['conversation'] )) {
|
269 |
+
$tweet->hideParentTweet();
|
270 |
+
}
|
271 |
+
|
272 |
+
if (isset($options['align'])) {
|
273 |
+
$tweet->setAlign($options['align']);
|
274 |
+
}
|
275 |
+
|
276 |
+
return $tweet;
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Convert Tweet object into an array suitable for use as data-* attributes
|
281 |
+
*
|
282 |
+
* @since 2.0.0
|
283 |
+
*
|
284 |
+
* @return array associative array of data attribute values or empty if no id set
|
285 |
+
*/
|
286 |
+
public function toArray()
|
287 |
+
{
|
288 |
+
$data = parent::toArray();
|
289 |
+
|
290 |
+
if (empty($data)) {
|
291 |
+
return array();
|
292 |
+
}
|
293 |
+
$data = array_merge($data, $this->themeToArray());
|
294 |
+
|
295 |
+
if ($this->width) {
|
296 |
+
$data['width'] = $this->width;
|
297 |
+
}
|
298 |
+
if (false === $this->cards) {
|
299 |
+
$data['cards'] = 'false';
|
300 |
+
}
|
301 |
+
if (false === $this->conversation) {
|
302 |
+
$data['conversation'] = 'false';
|
303 |
+
}
|
304 |
+
if (static::ALIGN_NONE !== $this->align) {
|
305 |
+
$data['align'] = $this->align;
|
306 |
+
}
|
307 |
+
|
308 |
+
return $data;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Output Tweet as an array suitable for use as oEmbed query parameters
|
313 |
+
*
|
314 |
+
* @since 2.0.0
|
315 |
+
*
|
316 |
+
* @return array Tweet parameter array {
|
317 |
+
* @type string query parameter name
|
318 |
+
* @type string query parameter value
|
319 |
+
* }
|
320 |
+
*/
|
321 |
+
public function toOEmbedParameterArray()
|
322 |
+
{
|
323 |
+
$oembed = parent::toOEmbedParameterArray();
|
324 |
+
if (empty($oembed)) {
|
325 |
+
return array();
|
326 |
+
}
|
327 |
+
$oembed = array_merge($oembed, $this->themeToOEmbedParameterArray());
|
328 |
+
|
329 |
+
if ($this->width) {
|
330 |
+
$oembed['maxwidth'] = $this->width;
|
331 |
+
}
|
332 |
+
if (false === $this->cards) {
|
333 |
+
$oembed['hide_media'] = false;
|
334 |
+
}
|
335 |
+
if (false === $this->conversation) {
|
336 |
+
$oembed['hide_thread'] = false;
|
337 |
+
}
|
338 |
+
if (static::ALIGN_NONE !== $this->align) {
|
339 |
+
$oembed['align'] = $this->align;
|
340 |
+
}
|
341 |
+
|
342 |
+
return $oembed;
|
343 |
+
}
|
344 |
+
}
|
src/Twitter/Widgets/Embeds/Tweet/Base.php
ADDED
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds\Tweet;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Basics of a Tweet shared between all display templates
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
abstract class Base extends \Twitter\Widgets\Base
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Construct a full Twitter URI by appending to base string
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const BASE_URL = 'https://twitter.com/_/status/';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Tweet ID
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type string
|
50 |
+
*/
|
51 |
+
protected $id;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Initialize the Tweet object with a Tweet ID
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @param string $id Tweet identifier
|
59 |
+
*/
|
60 |
+
public function __construct($id)
|
61 |
+
{
|
62 |
+
$this->setID($id);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Test given Tweet ID for validity
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @param string $id Tweet identifier
|
71 |
+
*
|
72 |
+
* @return bool true if valid, else false
|
73 |
+
*/
|
74 |
+
public static function isValidID($id)
|
75 |
+
{
|
76 |
+
if (! (is_string($id) && $id)) {
|
77 |
+
return false;
|
78 |
+
}
|
79 |
+
if (function_exists('ctype_digit')) {
|
80 |
+
if (ctype_digit($id)) {
|
81 |
+
return true;
|
82 |
+
}
|
83 |
+
} else {
|
84 |
+
if (preg_match('/^[0-9]+$/', $id)) {
|
85 |
+
return true;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
return false;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Get the Tweet ID
|
94 |
+
*
|
95 |
+
* @since 2.0.0
|
96 |
+
*
|
97 |
+
* @return string Tweet ID, or empty string if not set
|
98 |
+
*/
|
99 |
+
public function getID()
|
100 |
+
{
|
101 |
+
return $this->id ?: '';
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Set the Tweet ID. Tests passed Tweet ID for validity before saving
|
106 |
+
*
|
107 |
+
* @since 2.0.0
|
108 |
+
*
|
109 |
+
* @param string $id Tweet identifier
|
110 |
+
*
|
111 |
+
* @return self support chaining
|
112 |
+
*/
|
113 |
+
public function setID($id)
|
114 |
+
{
|
115 |
+
if (is_string($id)) {
|
116 |
+
$id = trim($id);
|
117 |
+
if ($id && static::isValidID($id)) {
|
118 |
+
$this->id = $id;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
return $this;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Tweet URL
|
127 |
+
*
|
128 |
+
* The username component is purposely left as a placeholder value: `_`.
|
129 |
+
* The URL returned by this function will redirect to a full Tweet URL page complete with the current Twitter username of the Tweet author
|
130 |
+
*
|
131 |
+
* @since 2.0.0
|
132 |
+
*
|
133 |
+
* @return string absolute URL or empty string if ID not set
|
134 |
+
*/
|
135 |
+
public function getURL()
|
136 |
+
{
|
137 |
+
if ($this->id) {
|
138 |
+
return static::BASE_URL . $this->id;
|
139 |
+
} else {
|
140 |
+
return '';
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Create a new Tweet object from an associative array of properties
|
146 |
+
*
|
147 |
+
* @since 2.0.0
|
148 |
+
*
|
149 |
+
* @param array $options associative array of options {
|
150 |
+
* @type string option key
|
151 |
+
* @type string|bool option value
|
152 |
+
* }
|
153 |
+
*
|
154 |
+
* @return static|null new instance of calling class or null if minimum requirements not met
|
155 |
+
*/
|
156 |
+
public static function fromArray($options)
|
157 |
+
{
|
158 |
+
// Tweet ID required
|
159 |
+
if (! (is_array($options) && isset($options['id']) && $options['id'])) {
|
160 |
+
return null;
|
161 |
+
}
|
162 |
+
|
163 |
+
$class = get_called_class();
|
164 |
+
$tweet = new $class( $options['id'] );
|
165 |
+
unset($class);
|
166 |
+
if (method_exists($tweet, 'setBaseOptions')) {
|
167 |
+
$tweet->setBaseOptions($options);
|
168 |
+
}
|
169 |
+
|
170 |
+
return $tweet;
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Convert Tweet object into an array suitable for use as data-* attributes
|
175 |
+
*
|
176 |
+
* @since 2.0.0
|
177 |
+
*
|
178 |
+
* @return array associative array of data attribute values or empty if no id set
|
179 |
+
*/
|
180 |
+
public function toArray()
|
181 |
+
{
|
182 |
+
$data = parent::toArray();
|
183 |
+
|
184 |
+
if ($this->id) {
|
185 |
+
$data['id'] = $this->id;
|
186 |
+
} else {
|
187 |
+
return array();
|
188 |
+
}
|
189 |
+
|
190 |
+
return $data;
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Output Tweet as an array suitable for use as oEmbed query parameters
|
195 |
+
*
|
196 |
+
* @since 2.0.0
|
197 |
+
*
|
198 |
+
* @return array Tweet parameter array {
|
199 |
+
* @type string query parameter name
|
200 |
+
* @type string query parameter value
|
201 |
+
* }
|
202 |
+
*/
|
203 |
+
public function toOEmbedParameterArray()
|
204 |
+
{
|
205 |
+
$oembed = parent::toArray();
|
206 |
+
|
207 |
+
$url = $this->getURL();
|
208 |
+
if (! $url) {
|
209 |
+
return array();
|
210 |
+
}
|
211 |
+
$oembed['url'] = $url;
|
212 |
+
|
213 |
+
return $oembed;
|
214 |
+
}
|
215 |
+
}
|
src/Twitter/Widgets/Embeds/Tweet/Video.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds\Tweet;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a Tweetn with video in a video-focused template
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Video extends \Twitter\Widgets\Embeds\Tweet\Base
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Display template type passed to oEmbed endpoints for a Tweet URL
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const WIDGET_TYPE = 'video';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Convert Tweet object into an array suitable for use as data-* attributes
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @return array associative array of data attribute values or empty if no id set
|
50 |
+
*/
|
51 |
+
public function toArray()
|
52 |
+
{
|
53 |
+
$data = parent::toArray();
|
54 |
+
if (empty($data)) {
|
55 |
+
return array();
|
56 |
+
}
|
57 |
+
|
58 |
+
$data['widget-type'] = static::WIDGET_TYPE;
|
59 |
+
|
60 |
+
return $data;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Output Tweet as an array suitable for use as oEmbed query parameters
|
65 |
+
*
|
66 |
+
* @since 2.0.0
|
67 |
+
*
|
68 |
+
* @return array Tweet parameter array {
|
69 |
+
* @type string query parameter name
|
70 |
+
* @type string query parameter value
|
71 |
+
* }
|
72 |
+
*/
|
73 |
+
public function toOEmbedParameterArray()
|
74 |
+
{
|
75 |
+
$oembed = parent::toOEmbedParameterArray();
|
76 |
+
if (empty($oembed)) {
|
77 |
+
return array();
|
78 |
+
}
|
79 |
+
|
80 |
+
$oembed['widget_type'] = static::WIDGET_TYPE;
|
81 |
+
|
82 |
+
return $oembed;
|
83 |
+
}
|
84 |
+
}
|
src/Twitter/Widgets/Embeds/Vine.php
ADDED
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\Widgets\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a Vine simple embed
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Vine
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Construct a full Vine URI by appending to base string
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @type string
|
41 |
+
*/
|
42 |
+
const BASE_URL = 'https://vine.co/v/';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Minimum allowed width
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @type int
|
50 |
+
*/
|
51 |
+
const MIN_WIDTH = 100;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Maximum allowed width
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @type int
|
59 |
+
*/
|
60 |
+
const MAX_WIDTH = 600;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Vine ID
|
64 |
+
*
|
65 |
+
* @since 2.0.0
|
66 |
+
*
|
67 |
+
* @type string
|
68 |
+
*/
|
69 |
+
protected $id;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Width of the embed
|
73 |
+
*
|
74 |
+
* @since 2.0.0
|
75 |
+
*
|
76 |
+
* @type int
|
77 |
+
*/
|
78 |
+
protected $width;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Initialize the Vine object with a Vine ID
|
82 |
+
*
|
83 |
+
* @since 2.0.0
|
84 |
+
*
|
85 |
+
* @param string $id Vine identifier
|
86 |
+
*/
|
87 |
+
public function __construct($id)
|
88 |
+
{
|
89 |
+
$this->setID($id);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Get the Vine ID
|
94 |
+
*
|
95 |
+
* @since 2.0.0
|
96 |
+
*
|
97 |
+
* @return string Vine ID, or empty string if not set
|
98 |
+
*/
|
99 |
+
public function getID()
|
100 |
+
{
|
101 |
+
return $this->id ?: '';
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Set the Vine ID
|
106 |
+
*
|
107 |
+
* @since 2.0.0
|
108 |
+
*
|
109 |
+
* @param string $id Vine identifier
|
110 |
+
*
|
111 |
+
* @return self support chaining
|
112 |
+
*/
|
113 |
+
public function setID($id)
|
114 |
+
{
|
115 |
+
if (is_string($id)) {
|
116 |
+
$id = trim($id);
|
117 |
+
if ($id) {
|
118 |
+
$this->id = $id;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
return $this;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Vine URL
|
127 |
+
*
|
128 |
+
* @since 2.0.0
|
129 |
+
*
|
130 |
+
* @return string absolute URL or empty string if ID not set
|
131 |
+
*/
|
132 |
+
public function getURL()
|
133 |
+
{
|
134 |
+
if ($this->id) {
|
135 |
+
return static::BASE_URL . $this->id;
|
136 |
+
} else {
|
137 |
+
return '';
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Get the fixed width of the widget display area
|
143 |
+
*
|
144 |
+
* @since 2.0.0
|
145 |
+
*
|
146 |
+
* @return int|null specified width of the widget or null if none set
|
147 |
+
*/
|
148 |
+
public function getWidth()
|
149 |
+
{
|
150 |
+
return $this->width ?: null;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Set the fixed width of the widget display area
|
155 |
+
*
|
156 |
+
* @since 2.0.0
|
157 |
+
*
|
158 |
+
* @link https://www.w3.org/wiki/CSS/Properties/max-width CSS max-width
|
159 |
+
*
|
160 |
+
* @param int $width width of the embed
|
161 |
+
*
|
162 |
+
* @return self support chaining
|
163 |
+
*/
|
164 |
+
public function setWidth($width)
|
165 |
+
{
|
166 |
+
if (is_int($width) && $width >= static::MIN_WIDTH && $width <= static::MAX_WIDTH) {
|
167 |
+
$this->width = $width;
|
168 |
+
}
|
169 |
+
|
170 |
+
return $this;
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Create a new Vine object from an associative array of properties
|
175 |
+
*
|
176 |
+
* @since 2.0.0
|
177 |
+
*
|
178 |
+
* @param array $options associative array of options {
|
179 |
+
* @type string option key
|
180 |
+
* @type string|bool option value
|
181 |
+
* }
|
182 |
+
*
|
183 |
+
* @return self new instance of calling class
|
184 |
+
*/
|
185 |
+
public static function fromArray($options)
|
186 |
+
{
|
187 |
+
// Vine ID required
|
188 |
+
if (! (is_array($options) && isset($options['id']) && $options['id'])) {
|
189 |
+
return null;
|
190 |
+
}
|
191 |
+
|
192 |
+
$class = get_called_class();
|
193 |
+
$vine = new $class( $options['id'] );
|
194 |
+
unset($class);
|
195 |
+
|
196 |
+
if (isset($options['width']) && method_exists($vine, 'setWidth')) {
|
197 |
+
$vine->setWidth($options['width']);
|
198 |
+
}
|
199 |
+
|
200 |
+
return $vine;
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Output Vine as an array suitable for use as oEmbed query parameters
|
205 |
+
*
|
206 |
+
* @since 2.0.0
|
207 |
+
*
|
208 |
+
* @return array Vine parameter array {
|
209 |
+
* @type string query parameter name
|
210 |
+
* @type string query parameter value
|
211 |
+
* }
|
212 |
+
*/
|
213 |
+
public function toOEmbedParameterArray()
|
214 |
+
{
|
215 |
+
$url = $this->getURL();
|
216 |
+
if (! $url) {
|
217 |
+
return array();
|
218 |
+
}
|
219 |
+
$oembed = array('url' => $url);
|
220 |
+
|
221 |
+
if ($this->width) {
|
222 |
+
$oembed['maxwidth'] = $this->width;
|
223 |
+
}
|
224 |
+
|
225 |
+
return $oembed;
|
226 |
+
}
|
227 |
+
}
|
src/Twitter/Widgets/Language.php
CHANGED
@@ -83,6 +83,8 @@ class Language
|
|
83 |
*
|
84 |
* @since 1.0.0
|
85 |
*
|
|
|
|
|
86 |
* @return bool true if passed language exists in list of Twitter production language codes
|
87 |
*/
|
88 |
public static function isSupportedLanguage($lang)
|
83 |
*
|
84 |
* @since 1.0.0
|
85 |
*
|
86 |
+
* @param string $lang language code
|
87 |
+
*
|
88 |
* @return bool true if passed language exists in list of Twitter production language codes
|
89 |
*/
|
90 |
public static function isSupportedLanguage($lang)
|
src/Twitter/WordPress/Admin/Post/MetaBox.php
CHANGED
@@ -158,7 +158,7 @@ class MetaBox
|
|
158 |
*
|
159 |
* @since 1.0.0
|
160 |
*
|
161 |
-
* @param WP_Post $post WordPress post object
|
162 |
*
|
163 |
* @return void
|
164 |
*/
|
158 |
*
|
159 |
* @since 1.0.0
|
160 |
*
|
161 |
+
* @param \WP_Post $post WordPress post object
|
162 |
*
|
163 |
* @return void
|
164 |
*/
|
src/Twitter/WordPress/Admin/Post/TweetIntent.php
CHANGED
@@ -65,7 +65,7 @@ class TweetIntent
|
|
65 |
* Used by WordPress JSON API to expose programmatic editor beyond the post meta box display used in the HTML-based admin interface
|
66 |
*
|
67 |
* @since 1.0.0
|
68 |
-
* @uses
|
69 |
*
|
70 |
* @return void
|
71 |
*/
|
@@ -122,7 +122,9 @@ class TweetIntent
|
|
122 |
if ( 'https' === strtolower( parse_url( $post_url, PHP_URL_SCHEME ) ) ) {
|
123 |
$is_https = true;
|
124 |
}
|
125 |
-
} catch(Exception $e) {
|
|
|
|
|
126 |
if ( $is_https ) {
|
127 |
$url_length = absint( $config->short_url_length_https );
|
128 |
}
|
@@ -165,21 +167,33 @@ class TweetIntent
|
|
165 |
|
166 |
echo '<tr>';
|
167 |
echo '<th scope="row" class="left"><label for="tweet-text">' . esc_html( _x( 'Text', 'Share / Tweet text', 'twitter' ) ) . '</label></th>';
|
168 |
-
echo '<td><input id="tweet-text" name="' . esc_attr( static::META_KEY . '[' . static::TEXT_KEY . ']' ) . '" type="text" maxlength="'
|
|
|
|
|
|
|
169 |
if ( isset( $stored_values[ static::TEXT_KEY ] ) ) {
|
170 |
echo ' value="' . esc_attr( $stored_values[ static::TEXT_KEY ] ) . '"';
|
171 |
} else {
|
172 |
echo ' placeholder="' . esc_attr( get_the_title( $post ) ) . '"';
|
173 |
}
|
174 |
-
|
|
|
|
|
175 |
echo '</tr>';
|
176 |
echo '<tr>';
|
177 |
echo '<th scope="row" class="left"><label for="tweet-hashtags">' . esc_html( __( 'Hashtags', 'twitter' ) ) . '</label></th>';
|
178 |
-
echo '<td><input id="tweet-hashtags" name="' . esc_attr( static::META_KEY . '[' . static::HASHTAGS_KEY . ']' ) . '" type="text" maxlength="'
|
|
|
|
|
|
|
|
|
|
|
179 |
if ( isset( $stored_values[ static::HASHTAGS_KEY ] ) && is_array( $stored_values[ static::HASHTAGS_KEY ] ) ) {
|
180 |
echo ' value="' . esc_attr( implode( ',', $stored_values[ static::HASHTAGS_KEY ] ) ) . '"';
|
181 |
}
|
182 |
-
|
|
|
|
|
183 |
echo '</tr>';
|
184 |
|
185 |
echo '</tbody></table>';
|
@@ -266,7 +280,7 @@ class TweetIntent
|
|
266 |
*
|
267 |
* @since 1.0.0
|
268 |
*
|
269 |
-
* @param WP_Post $post WordPress post object
|
270 |
*
|
271 |
* @return void
|
272 |
*/
|
65 |
* Used by WordPress JSON API to expose programmatic editor beyond the post meta box display used in the HTML-based admin interface
|
66 |
*
|
67 |
* @since 1.0.0
|
68 |
+
* @uses register_meta
|
69 |
*
|
70 |
* @return void
|
71 |
*/
|
122 |
if ( 'https' === strtolower( parse_url( $post_url, PHP_URL_SCHEME ) ) ) {
|
123 |
$is_https = true;
|
124 |
}
|
125 |
+
} catch (\Exception $e) {
|
126 |
+
// assume not HTTPS if parse_url throws exception
|
127 |
+
}
|
128 |
if ( $is_https ) {
|
129 |
$url_length = absint( $config->short_url_length_https );
|
130 |
}
|
167 |
|
168 |
echo '<tr>';
|
169 |
echo '<th scope="row" class="left"><label for="tweet-text">' . esc_html( _x( 'Text', 'Share / Tweet text', 'twitter' ) ) . '</label></th>';
|
170 |
+
echo '<td><input id="tweet-text" name="' . esc_attr( static::META_KEY . '[' . static::TEXT_KEY . ']' ) . '" type="text" maxlength="';
|
171 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
172 |
+
echo $available_characters;
|
173 |
+
echo '" autocomplete="off"';
|
174 |
if ( isset( $stored_values[ static::TEXT_KEY ] ) ) {
|
175 |
echo ' value="' . esc_attr( $stored_values[ static::TEXT_KEY ] ) . '"';
|
176 |
} else {
|
177 |
echo ' placeholder="' . esc_attr( get_the_title( $post ) ) . '"';
|
178 |
}
|
179 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
180 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
181 |
+
echo '></td>';
|
182 |
echo '</tr>';
|
183 |
echo '<tr>';
|
184 |
echo '<th scope="row" class="left"><label for="tweet-hashtags">' . esc_html( __( 'Hashtags', 'twitter' ) ) . '</label></th>';
|
185 |
+
echo '<td><input id="tweet-hashtags" name="' . esc_attr( static::META_KEY . '[' . static::HASHTAGS_KEY . ']' ) . '" type="text" maxlength="';
|
186 |
+
// integer does not need escaping
|
187 |
+
// @codingStandardsIgnoreStart WordPress.XSS.EscapeOutput.OutputNotEscaped
|
188 |
+
echo ($available_characters - 2);
|
189 |
+
// @codingStandardsIgnoreEnd WordPress.XSS.EscapeOutput.OutputNotEscaped
|
190 |
+
echo '" autocomplete="off"';
|
191 |
if ( isset( $stored_values[ static::HASHTAGS_KEY ] ) && is_array( $stored_values[ static::HASHTAGS_KEY ] ) ) {
|
192 |
echo ' value="' . esc_attr( implode( ',', $stored_values[ static::HASHTAGS_KEY ] ) ) . '"';
|
193 |
}
|
194 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
195 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
196 |
+
echo '></td>';
|
197 |
echo '</tr>';
|
198 |
|
199 |
echo '</tbody></table>';
|
280 |
*
|
281 |
* @since 1.0.0
|
282 |
*
|
283 |
+
* @param \WP_Post $post WordPress post object
|
284 |
*
|
285 |
* @return void
|
286 |
*/
|
src/Twitter/WordPress/Admin/Post/TwitterCard.php
CHANGED
@@ -65,7 +65,7 @@ class TwitterCard
|
|
65 |
* Used by WordPress JSON API to expose programmatic editor beyond the post meta box display used in the HTML-based admin interface
|
66 |
*
|
67 |
* @since 1.0.0
|
68 |
-
* @uses
|
69 |
*
|
70 |
* @return void
|
71 |
*/
|
@@ -86,8 +86,8 @@ class TwitterCard
|
|
86 |
* @param string $post_type post type
|
87 |
*
|
88 |
* @return array associative array of supported fields {
|
89 |
-
* @type
|
90 |
-
* @type
|
91 |
* }
|
92 |
*/
|
93 |
public static function supportedCardFieldsByPostType( $post_type )
|
@@ -133,7 +133,10 @@ class TwitterCard
|
|
133 |
}
|
134 |
|
135 |
// separate Twitter Cards content from Intent content above
|
136 |
-
echo '<hr'
|
|
|
|
|
|
|
137 |
|
138 |
echo '<h3>' . esc_html( __( 'Twitter Card', 'twitter' ) ) . '</h3>';
|
139 |
|
@@ -151,7 +154,9 @@ class TwitterCard
|
|
151 |
echo ' placeholder="' . esc_attr( get_the_title( $post ) ) . '"';
|
152 |
}
|
153 |
|
154 |
-
|
|
|
|
|
155 |
echo '</tr>';
|
156 |
}
|
157 |
|
@@ -162,7 +167,9 @@ class TwitterCard
|
|
162 |
if ( isset( $stored_values[ static::DESCRIPTION_KEY ] ) ) {
|
163 |
echo ' value="' . esc_attr( $stored_values[ static::DESCRIPTION_KEY ] ) . '"';
|
164 |
}
|
165 |
-
|
|
|
|
|
166 |
echo '</tr>';
|
167 |
}
|
168 |
|
@@ -195,18 +202,18 @@ class TwitterCard
|
|
195 |
$cleaned_fields = array();
|
196 |
|
197 |
if ( isset( $fields[ static::TITLE_KEY ] ) ) {
|
198 |
-
$title = \Twitter\WordPress\Cards\Sanitize::sanitizePlainTextString( $fields[ static::TITLE_KEY ]
|
199 |
if ( $title ) {
|
200 |
$cleaned_fields[ static::TITLE_KEY ] = $title;
|
201 |
}
|
202 |
-
unset($title);
|
203 |
}
|
204 |
if ( isset( $fields[ static::DESCRIPTION_KEY ] ) ) {
|
205 |
-
$description = \Twitter\WordPress\Cards\Sanitize::sanitizePlainTextString( $fields[ static::DESCRIPTION_KEY ]
|
206 |
if ( $description ) {
|
207 |
$cleaned_fields[ static::DESCRIPTION_KEY ] = $description;
|
208 |
}
|
209 |
-
unset($description);
|
210 |
}
|
211 |
|
212 |
return $cleaned_fields;
|
@@ -219,7 +226,7 @@ class TwitterCard
|
|
219 |
*
|
220 |
* @since 1.0.0
|
221 |
*
|
222 |
-
* @param WP_Post $post WordPress post object
|
223 |
*
|
224 |
* @return void
|
225 |
*/
|
65 |
* Used by WordPress JSON API to expose programmatic editor beyond the post meta box display used in the HTML-based admin interface
|
66 |
*
|
67 |
* @since 1.0.0
|
68 |
+
* @uses register_meta
|
69 |
*
|
70 |
* @return void
|
71 |
*/
|
86 |
* @param string $post_type post type
|
87 |
*
|
88 |
* @return array associative array of supported fields {
|
89 |
+
* @type string field name (examples: title, description)
|
90 |
+
* @type bool exists boolean for easy key reference
|
91 |
* }
|
92 |
*/
|
93 |
public static function supportedCardFieldsByPostType( $post_type )
|
133 |
}
|
134 |
|
135 |
// separate Twitter Cards content from Intent content above
|
136 |
+
echo '<hr';
|
137 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
138 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
139 |
+
echo '>';
|
140 |
|
141 |
echo '<h3>' . esc_html( __( 'Twitter Card', 'twitter' ) ) . '</h3>';
|
142 |
|
154 |
echo ' placeholder="' . esc_attr( get_the_title( $post ) ) . '"';
|
155 |
}
|
156 |
|
157 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
158 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
159 |
+
echo '></td>';
|
160 |
echo '</tr>';
|
161 |
}
|
162 |
|
167 |
if ( isset( $stored_values[ static::DESCRIPTION_KEY ] ) ) {
|
168 |
echo ' value="' . esc_attr( $stored_values[ static::DESCRIPTION_KEY ] ) . '"';
|
169 |
}
|
170 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
171 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
172 |
+
echo '></td>';
|
173 |
echo '</tr>';
|
174 |
}
|
175 |
|
202 |
$cleaned_fields = array();
|
203 |
|
204 |
if ( isset( $fields[ static::TITLE_KEY ] ) ) {
|
205 |
+
$title = \Twitter\WordPress\Cards\Sanitize::sanitizePlainTextString( $fields[ static::TITLE_KEY ] );
|
206 |
if ( $title ) {
|
207 |
$cleaned_fields[ static::TITLE_KEY ] = $title;
|
208 |
}
|
209 |
+
unset( $title );
|
210 |
}
|
211 |
if ( isset( $fields[ static::DESCRIPTION_KEY ] ) ) {
|
212 |
+
$description = \Twitter\WordPress\Cards\Sanitize::sanitizePlainTextString( $fields[ static::DESCRIPTION_KEY ] );
|
213 |
if ( $description ) {
|
214 |
$cleaned_fields[ static::DESCRIPTION_KEY ] = $description;
|
215 |
}
|
216 |
+
unset( $description );
|
217 |
}
|
218 |
|
219 |
return $cleaned_fields;
|
226 |
*
|
227 |
* @since 1.0.0
|
228 |
*
|
229 |
+
* @param \WP_Post $post WordPress post object
|
230 |
*
|
231 |
* @return void
|
232 |
*/
|
src/Twitter/WordPress/Admin/Profile/PeriscopeUser.php
CHANGED
@@ -62,14 +62,14 @@ class PeriscopeUser
|
|
62 |
* @see wp_get_user_contact_methods()
|
63 |
*
|
64 |
* @param array $methods contact methods and their labels {
|
65 |
-
* @type
|
66 |
-
* @type
|
67 |
* }
|
68 |
-
* @param WP_User $user WP_User object.
|
69 |
*
|
70 |
* @return array contact methods and their labels {
|
71 |
-
* @type
|
72 |
-
* @type
|
73 |
* }
|
74 |
*/
|
75 |
public static function addContactMethod( $methods, $user )
|
62 |
* @see wp_get_user_contact_methods()
|
63 |
*
|
64 |
* @param array $methods contact methods and their labels {
|
65 |
+
* @type string contact method
|
66 |
+
* @type string label
|
67 |
* }
|
68 |
+
* @param \WP_User $user WP_User object.
|
69 |
*
|
70 |
* @return array contact methods and their labels {
|
71 |
+
* @type string contact method
|
72 |
+
* @type string label
|
73 |
* }
|
74 |
*/
|
75 |
public static function addContactMethod( $methods, $user )
|
src/Twitter/WordPress/Admin/Profile/User.php
CHANGED
@@ -62,14 +62,14 @@ class User
|
|
62 |
* @see wp_get_user_contact_methods()
|
63 |
*
|
64 |
* @param array $methods contact methods and their labels {
|
65 |
-
* @type
|
66 |
-
* @type
|
67 |
* }
|
68 |
-
* @param WP_User $user WP_User object.
|
69 |
*
|
70 |
* @return array contact methods and their labels {
|
71 |
-
* @type
|
72 |
-
* @type
|
73 |
* }
|
74 |
*/
|
75 |
public static function addContactMethod( $methods, $user )
|
62 |
* @see wp_get_user_contact_methods()
|
63 |
*
|
64 |
* @param array $methods contact methods and their labels {
|
65 |
+
* @type string contact method
|
66 |
+
* @type string label
|
67 |
* }
|
68 |
+
* @param \WP_User $user WP_User object.
|
69 |
*
|
70 |
* @return array contact methods and their labels {
|
71 |
+
* @type string contact method
|
72 |
+
* @type string label
|
73 |
* }
|
74 |
*/
|
75 |
public static function addContactMethod( $methods, $user )
|
src/Twitter/WordPress/Admin/Settings/{TweetButton.php → Buttons/Tweet.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Admin\Settings;
|
27 |
|
28 |
/**
|
29 |
* Store a Twitter username for attribution of site content
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
class
|
34 |
{
|
35 |
/**
|
36 |
* Define our option name
|
@@ -61,6 +61,15 @@ class TweetButton implements SettingsSection
|
|
61 |
*/
|
62 |
protected $hook_suffix;
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
/**
|
65 |
* Reference the feature by name
|
66 |
*
|
@@ -122,7 +131,7 @@ class TweetButton implements SettingsSection
|
|
122 |
$this->existing_options = $options;
|
123 |
|
124 |
add_action(
|
125 |
-
'
|
126 |
array( &$this, 'defineSection' ),
|
127 |
static::SECTION_PRIORITY,
|
128 |
0 // no parameters
|
@@ -186,8 +195,8 @@ class TweetButton implements SettingsSection
|
|
186 |
* @since 1.0.0
|
187 |
*
|
188 |
* @return array option values and labels {
|
189 |
-
* @type
|
190 |
-
* @type
|
191 |
* }
|
192 |
*/
|
193 |
public static function getPositionOptions()
|
@@ -196,7 +205,7 @@ class TweetButton implements SettingsSection
|
|
196 |
'' => ' ',
|
197 |
'before' => _x( 'before', 'before another piece of content', 'twitter' ),
|
198 |
'after' => _x( 'after', 'after another piece of content', 'twitter' ),
|
199 |
-
'both' => _x( 'before & after', 'before and after another piece of content', 'twitter' )
|
200 |
);
|
201 |
}
|
202 |
|
@@ -233,6 +242,8 @@ class TweetButton implements SettingsSection
|
|
233 |
}
|
234 |
$select .= '</select>';
|
235 |
|
|
|
|
|
236 |
echo sprintf( esc_html( _x( 'Display Tweet Button %s post content', 'display Tweet Button relative to the content of an article', 'twitter' ) ), $select );
|
237 |
}
|
238 |
|
@@ -255,7 +266,11 @@ class TweetButton implements SettingsSection
|
|
255 |
echo '="checked"';
|
256 |
}
|
257 |
}
|
258 |
-
|
|
|
|
|
|
|
|
|
259 |
}
|
260 |
|
261 |
/**
|
@@ -264,13 +279,13 @@ class TweetButton implements SettingsSection
|
|
264 |
* @since 1.0.0
|
265 |
*
|
266 |
* @param array $options submitted option {
|
267 |
-
* @type
|
268 |
-
* @type
|
269 |
* }
|
270 |
*
|
271 |
* @return array $options cleaned option {
|
272 |
-
* @type
|
273 |
-
* @type
|
274 |
* }
|
275 |
*/
|
276 |
public static function sanitizeOption( $options )
|
@@ -289,7 +304,7 @@ class TweetButton implements SettingsSection
|
|
289 |
}
|
290 |
unset( $position_options );
|
291 |
}
|
292 |
-
unset($key);
|
293 |
|
294 |
if ( isset( $options['size'] ) && 'large' === $options['size'] ) {
|
295 |
$clean_options['size'] = 'large';
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Admin\Settings\Buttons;
|
27 |
|
28 |
/**
|
29 |
* Store a Twitter username for attribution of site content
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
class Tweet implements \Twitter\WordPress\Admin\Settings\SettingsSection
|
34 |
{
|
35 |
/**
|
36 |
* Define our option name
|
61 |
*/
|
62 |
protected $hook_suffix;
|
63 |
|
64 |
+
/**
|
65 |
+
* Store existing options, if any exist
|
66 |
+
*
|
67 |
+
* @since 1.0.0
|
68 |
+
*
|
69 |
+
* @type array
|
70 |
+
*/
|
71 |
+
protected $existing_options;
|
72 |
+
|
73 |
/**
|
74 |
* Reference the feature by name
|
75 |
*
|
131 |
$this->existing_options = $options;
|
132 |
|
133 |
add_action(
|
134 |
+
'add_' . $this->hook_suffix . '_section',
|
135 |
array( &$this, 'defineSection' ),
|
136 |
static::SECTION_PRIORITY,
|
137 |
0 // no parameters
|
195 |
* @since 1.0.0
|
196 |
*
|
197 |
* @return array option values and labels {
|
198 |
+
* @type string option value
|
199 |
+
* @type string translated option label
|
200 |
* }
|
201 |
*/
|
202 |
public static function getPositionOptions()
|
205 |
'' => ' ',
|
206 |
'before' => _x( 'before', 'before another piece of content', 'twitter' ),
|
207 |
'after' => _x( 'after', 'after another piece of content', 'twitter' ),
|
208 |
+
'both' => _x( 'before & after', 'before and after another piece of content', 'twitter' ),
|
209 |
);
|
210 |
}
|
211 |
|
242 |
}
|
243 |
$select .= '</select>';
|
244 |
|
245 |
+
// <select> markup escaped when building the element
|
246 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
247 |
echo sprintf( esc_html( _x( 'Display Tweet Button %s post content', 'display Tweet Button relative to the content of an article', 'twitter' ) ), $select );
|
248 |
}
|
249 |
|
266 |
echo '="checked"';
|
267 |
}
|
268 |
}
|
269 |
+
|
270 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
271 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
272 |
+
|
273 |
+
echo '> ' . esc_html( __( 'Large button', 'twitter' ) ) . '</label>';
|
274 |
}
|
275 |
|
276 |
/**
|
279 |
* @since 1.0.0
|
280 |
*
|
281 |
* @param array $options submitted option {
|
282 |
+
* @type string option name
|
283 |
+
* @type mixed option value
|
284 |
* }
|
285 |
*
|
286 |
* @return array $options cleaned option {
|
287 |
+
* @type string option name
|
288 |
+
* @type string option value
|
289 |
* }
|
290 |
*/
|
291 |
public static function sanitizeOption( $options )
|
304 |
}
|
305 |
unset( $position_options );
|
306 |
}
|
307 |
+
unset( $key );
|
308 |
|
309 |
if ( isset( $options['size'] ) && 'large' === $options['size'] ) {
|
310 |
$clean_options['size'] = 'large';
|
src/Twitter/WordPress/Admin/Settings/{SiteAttribution.php → Cards/SiteAttribution.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Admin\Settings;
|
27 |
|
28 |
/**
|
29 |
* Store a Twitter username for attribution of site content
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
class SiteAttribution implements SettingsSection
|
34 |
{
|
35 |
/**
|
36 |
* Define our option name
|
@@ -73,6 +73,18 @@ class SiteAttribution implements SettingsSection
|
|
73 |
return _x( 'Site attribution', 'Attribute content on a website to a Twitter account', 'twitter' );
|
74 |
}
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
/**
|
77 |
* Add site attribution option and settings section to an existing settings page
|
78 |
*
|
@@ -91,7 +103,18 @@ class SiteAttribution implements SettingsSection
|
|
91 |
$settings = new static();
|
92 |
$settings->hook_suffix = $hook_suffix;
|
93 |
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
add_action(
|
96 |
'load-' . $hook_suffix,
|
97 |
array( &$settings, 'onload' ),
|
@@ -116,7 +139,7 @@ class SiteAttribution implements SettingsSection
|
|
116 |
}
|
117 |
|
118 |
add_action(
|
119 |
-
'
|
120 |
array( &$this, 'defineSection' ),
|
121 |
static::SECTION_PRIORITY,
|
122 |
0 // no parameters
|
@@ -124,7 +147,7 @@ class SiteAttribution implements SettingsSection
|
|
124 |
|
125 |
// contextual help
|
126 |
add_action(
|
127 |
-
'
|
128 |
array( __CLASS__, 'addHelpTab' ),
|
129 |
static::SECTION_PRIORITY,
|
130 |
1 // accept current screen as a parameter
|
@@ -172,7 +195,7 @@ class SiteAttribution implements SettingsSection
|
|
172 |
public static function sectionHeader()
|
173 |
{
|
174 |
echo '<p>';
|
175 |
-
echo esc_html(
|
176 |
echo '</p>';
|
177 |
}
|
178 |
|
@@ -186,16 +209,15 @@ class SiteAttribution implements SettingsSection
|
|
186 |
public function displaySiteAttributionUsername()
|
187 |
{
|
188 |
$html = '<input type="text" id="' . esc_attr( self::OPTION_NAME ) . '" name="' . esc_attr( self::OPTION_NAME ) . '" size="20"';
|
189 |
-
$site_username = get_option( self::OPTION_NAME );
|
190 |
if ( $site_username ) {
|
191 |
$html .= ' value="' . esc_attr( $site_username ) . '"';
|
192 |
}
|
193 |
$html .= \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement() . '>';
|
194 |
|
195 |
// escaped in markup builder
|
196 |
-
// @
|
197 |
echo $html;
|
198 |
-
// @codingStandardsIgnoreEnd WordPress.XSS.EscapeOutput
|
199 |
}
|
200 |
|
201 |
/**
|
@@ -203,7 +225,7 @@ class SiteAttribution implements SettingsSection
|
|
203 |
*
|
204 |
* @since 1.0.0
|
205 |
*
|
206 |
-
* @param WP_Screen $screen current screen
|
207 |
*
|
208 |
* @return void
|
209 |
*/
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Admin\Settings\Cards;
|
27 |
|
28 |
/**
|
29 |
* Store a Twitter username for attribution of site content
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
class SiteAttribution implements \Twitter\WordPress\Admin\Settings\SettingsSection
|
34 |
{
|
35 |
/**
|
36 |
* Define our option name
|
73 |
return _x( 'Site attribution', 'Attribute content on a website to a Twitter account', 'twitter' );
|
74 |
}
|
75 |
|
76 |
+
/**
|
77 |
+
* Describe the setting
|
78 |
+
*
|
79 |
+
* @since 2.0.0
|
80 |
+
*
|
81 |
+
* @return string description of the setting
|
82 |
+
*/
|
83 |
+
public static function getDescription()
|
84 |
+
{
|
85 |
+
return __( "Attribute shared content to your site's Twitter account", 'twitter' );
|
86 |
+
}
|
87 |
+
|
88 |
/**
|
89 |
* Add site attribution option and settings section to an existing settings page
|
90 |
*
|
103 |
$settings = new static();
|
104 |
$settings->hook_suffix = $hook_suffix;
|
105 |
|
106 |
+
$args = array(
|
107 |
+
'type' => 'string',
|
108 |
+
'description' => static::getDescription(),
|
109 |
+
'sanitize_callback' => array( get_called_class(), 'sanitize' ),
|
110 |
+
'default' => '',
|
111 |
+
'show_in_rest' => true,
|
112 |
+
);
|
113 |
+
// WordPress 4.7+ registered settings
|
114 |
+
if ( ! function_exists( 'get_registered_settings' ) ) {
|
115 |
+
$args = $args['sanitize_callback'];
|
116 |
+
}
|
117 |
+
register_setting( $hook_suffix, self::OPTION_NAME, $args );
|
118 |
add_action(
|
119 |
'load-' . $hook_suffix,
|
120 |
array( &$settings, 'onload' ),
|
139 |
}
|
140 |
|
141 |
add_action(
|
142 |
+
'add_' . $this->hook_suffix . '_section',
|
143 |
array( &$this, 'defineSection' ),
|
144 |
static::SECTION_PRIORITY,
|
145 |
0 // no parameters
|
147 |
|
148 |
// contextual help
|
149 |
add_action(
|
150 |
+
'add_' . $this->hook_suffix . '_help_tab',
|
151 |
array( __CLASS__, 'addHelpTab' ),
|
152 |
static::SECTION_PRIORITY,
|
153 |
1 // accept current screen as a parameter
|
195 |
public static function sectionHeader()
|
196 |
{
|
197 |
echo '<p>';
|
198 |
+
echo esc_html( static::getDescription() );
|
199 |
echo '</p>';
|
200 |
}
|
201 |
|
209 |
public function displaySiteAttributionUsername()
|
210 |
{
|
211 |
$html = '<input type="text" id="' . esc_attr( self::OPTION_NAME ) . '" name="' . esc_attr( self::OPTION_NAME ) . '" size="20"';
|
212 |
+
$site_username = get_option( self::OPTION_NAME, '' );
|
213 |
if ( $site_username ) {
|
214 |
$html .= ' value="' . esc_attr( $site_username ) . '"';
|
215 |
}
|
216 |
$html .= \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement() . '>';
|
217 |
|
218 |
// escaped in markup builder
|
219 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput
|
220 |
echo $html;
|
|
|
221 |
}
|
222 |
|
223 |
/**
|
225 |
*
|
226 |
* @since 1.0.0
|
227 |
*
|
228 |
+
* @param \WP_Screen $screen current screen
|
229 |
*
|
230 |
* @return void
|
231 |
*/
|
src/Twitter/WordPress/Admin/Settings/{Theme.php → Embeds/Theme.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Admin\Settings;
|
27 |
|
28 |
/**
|
29 |
* Site-level settings for Twitter widget themes
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
class Theme implements SettingsSection
|
34 |
{
|
35 |
/**
|
36 |
* Define our option array value.
|
@@ -61,6 +61,15 @@ class Theme implements SettingsSection
|
|
61 |
*/
|
62 |
protected $hook_suffix;
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
/**
|
65 |
* Reference the feature by name
|
66 |
*
|
@@ -84,7 +93,7 @@ class Theme implements SettingsSection
|
|
84 |
{
|
85 |
return array(
|
86 |
'light' => _x( 'light', 'Option for content to appear with a light background and dark text', 'twitter' ),
|
87 |
-
'dark' => _x( 'dark', 'Option for content to appear with a dark background and light text', 'twitter' )
|
88 |
);
|
89 |
}
|
90 |
|
@@ -156,14 +165,14 @@ class Theme implements SettingsSection
|
|
156 |
|
157 |
// theme
|
158 |
add_action(
|
159 |
-
'
|
160 |
array( &$this, 'defineSection' ),
|
161 |
static::SECTION_PRIORITY, // top of screen
|
162 |
0 // no parameters
|
163 |
);
|
164 |
// contextual help
|
165 |
add_action(
|
166 |
-
'
|
167 |
array( __CLASS__, 'addHelpTab' ),
|
168 |
static::SECTION_PRIORITY,
|
169 |
1
|
@@ -292,7 +301,7 @@ class Theme implements SettingsSection
|
|
292 |
echo '</p>';
|
293 |
}
|
294 |
|
295 |
-
|
296 |
* Choose a theme
|
297 |
*
|
298 |
* @since 1.0.0
|
@@ -314,8 +323,12 @@ class Theme implements SettingsSection
|
|
314 |
|
315 |
echo '<fieldset id="' . esc_attr( 'twitter-' . $key ) . '">';
|
316 |
foreach ( $choices as $value => $label ) {
|
317 |
-
echo '<div><label><input type="radio" name="' . $name_attribute . '" value="' . esc_attr( $value ) . '"' . checked( $existing_value, $value, false )
|
|
|
|
|
|
|
318 |
echo ' ' . esc_html( $label );
|
|
|
319 |
echo '</label></div>';
|
320 |
}
|
321 |
echo '</fieldset>';
|
@@ -336,7 +349,10 @@ class Theme implements SettingsSection
|
|
336 |
if ( isset( $this->existing_options[ $key ] ) ) {
|
337 |
echo ' value="' . esc_attr( '#' . $this->existing_options[ $key ] ) . '"';
|
338 |
}
|
339 |
-
|
|
|
|
|
|
|
340 |
|
341 |
echo '<p class="description">';
|
342 |
echo esc_html( __( 'Color of link text inside a Twitter widget.', 'twitter' ) );
|
@@ -358,7 +374,9 @@ class Theme implements SettingsSection
|
|
358 |
if ( isset( $this->existing_options[ $key ] ) ) {
|
359 |
echo ' value="' . esc_attr( '#' . $this->existing_options[ $key ] ) . '"';
|
360 |
}
|
361 |
-
|
|
|
|
|
362 |
|
363 |
echo '<p class="description">';
|
364 |
echo esc_html( __( 'Color of border surrounding a Twitter widget.', 'twitter' ) );
|
@@ -370,7 +388,7 @@ class Theme implements SettingsSection
|
|
370 |
*
|
371 |
* @since 1.0.0
|
372 |
*
|
373 |
-
* @param WP_Screen $screen current screen
|
374 |
*
|
375 |
* @return void
|
376 |
*/
|
@@ -420,13 +438,15 @@ class Theme implements SettingsSection
|
|
420 |
echo '<label>';
|
421 |
echo '<input type="checkbox" name="' . esc_attr( self::OPTION_NAME . '[' . $key . ']' ) . '" id="twitter-dnt" value="1"';
|
422 |
checked( isset( $this->existing_options[ $key ] ) );
|
423 |
-
|
|
|
|
|
424 |
echo esc_html( __( 'Do not use my website to tailor content and suggestions for Twitter users', 'twitter' ) );
|
425 |
echo '</label>';
|
426 |
|
427 |
echo '<p class="description">';
|
428 |
echo esc_html( __( 'Twitter may track website visitors for advertising targeting, suggested Twitter accounts, and other purposes.', 'twitter' ) );
|
429 |
-
echo '
|
430 |
echo '</p><p class="description">';
|
431 |
echo esc_html( __( 'Select this option if you wish to opt-out of Twitter tracking visitors when a Twitter button or widget appears on a webpage.', 'twitter' ) );
|
432 |
echo '</p>';
|
@@ -459,7 +479,9 @@ class Theme implements SettingsSection
|
|
459 |
|
460 |
echo '<label><input type="checkbox" name="' . esc_attr( self::OPTION_NAME . '[' . $key . ']' ) . '" value="1"';
|
461 |
checked( isset( $this->existing_options[ $key ] ) );
|
462 |
-
|
|
|
|
|
463 |
echo esc_html( __( 'Suppress Content Security Policy warnings', 'twitter' ) );
|
464 |
echo '</label>';
|
465 |
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Admin\Settings\Embeds;
|
27 |
|
28 |
/**
|
29 |
* Site-level settings for Twitter widget themes
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
class Theme implements \Twitter\WordPress\Admin\Settings\SettingsSection
|
34 |
{
|
35 |
/**
|
36 |
* Define our option array value.
|
61 |
*/
|
62 |
protected $hook_suffix;
|
63 |
|
64 |
+
/**
|
65 |
+
* Store existing options, if any exist
|
66 |
+
*
|
67 |
+
* @since 1.0.0
|
68 |
+
*
|
69 |
+
* @type array
|
70 |
+
*/
|
71 |
+
protected $existing_options;
|
72 |
+
|
73 |
/**
|
74 |
* Reference the feature by name
|
75 |
*
|
93 |
{
|
94 |
return array(
|
95 |
'light' => _x( 'light', 'Option for content to appear with a light background and dark text', 'twitter' ),
|
96 |
+
'dark' => _x( 'dark', 'Option for content to appear with a dark background and light text', 'twitter' ),
|
97 |
);
|
98 |
}
|
99 |
|
165 |
|
166 |
// theme
|
167 |
add_action(
|
168 |
+
'add_' . $this->hook_suffix . '_section',
|
169 |
array( &$this, 'defineSection' ),
|
170 |
static::SECTION_PRIORITY, // top of screen
|
171 |
0 // no parameters
|
172 |
);
|
173 |
// contextual help
|
174 |
add_action(
|
175 |
+
'add_' . $this->hook_suffix . '_help_tab',
|
176 |
array( __CLASS__, 'addHelpTab' ),
|
177 |
static::SECTION_PRIORITY,
|
178 |
1
|
301 |
echo '</p>';
|
302 |
}
|
303 |
|
304 |
+
/**
|
305 |
* Choose a theme
|
306 |
*
|
307 |
* @since 1.0.0
|
323 |
|
324 |
echo '<fieldset id="' . esc_attr( 'twitter-' . $key ) . '">';
|
325 |
foreach ( $choices as $value => $label ) {
|
326 |
+
echo '<div><label><input type="radio" name="' . $name_attribute . '" value="' . esc_attr( $value ) . '"' . checked( $existing_value, $value, false );
|
327 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
328 |
+
echo $close_void_element;
|
329 |
+
|
330 |
echo ' ' . esc_html( $label );
|
331 |
+
|
332 |
echo '</label></div>';
|
333 |
}
|
334 |
echo '</fieldset>';
|
349 |
if ( isset( $this->existing_options[ $key ] ) ) {
|
350 |
echo ' value="' . esc_attr( '#' . $this->existing_options[ $key ] ) . '"';
|
351 |
}
|
352 |
+
|
353 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
354 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
355 |
+
echo '>';
|
356 |
|
357 |
echo '<p class="description">';
|
358 |
echo esc_html( __( 'Color of link text inside a Twitter widget.', 'twitter' ) );
|
374 |
if ( isset( $this->existing_options[ $key ] ) ) {
|
375 |
echo ' value="' . esc_attr( '#' . $this->existing_options[ $key ] ) . '"';
|
376 |
}
|
377 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
378 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
379 |
+
echo '>';
|
380 |
|
381 |
echo '<p class="description">';
|
382 |
echo esc_html( __( 'Color of border surrounding a Twitter widget.', 'twitter' ) );
|
388 |
*
|
389 |
* @since 1.0.0
|
390 |
*
|
391 |
+
* @param \WP_Screen $screen current screen
|
392 |
*
|
393 |
* @return void
|
394 |
*/
|
438 |
echo '<label>';
|
439 |
echo '<input type="checkbox" name="' . esc_attr( self::OPTION_NAME . '[' . $key . ']' ) . '" id="twitter-dnt" value="1"';
|
440 |
checked( isset( $this->existing_options[ $key ] ) );
|
441 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
442 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
443 |
+
echo '>';
|
444 |
echo esc_html( __( 'Do not use my website to tailor content and suggestions for Twitter users', 'twitter' ) );
|
445 |
echo '</label>';
|
446 |
|
447 |
echo '<p class="description">';
|
448 |
echo esc_html( __( 'Twitter may track website visitors for advertising targeting, suggested Twitter accounts, and other purposes.', 'twitter' ) );
|
449 |
+
echo ' <a href="https://dev.twitter.com/web/overview/privacy" target="_blank">' . esc_html( _x( 'Read more', 'learn more about this topic', 'twitter' ) ) . '</a>';
|
450 |
echo '</p><p class="description">';
|
451 |
echo esc_html( __( 'Select this option if you wish to opt-out of Twitter tracking visitors when a Twitter button or widget appears on a webpage.', 'twitter' ) );
|
452 |
echo '</p>';
|
479 |
|
480 |
echo '<label><input type="checkbox" name="' . esc_attr( self::OPTION_NAME . '[' . $key . ']' ) . '" value="1"';
|
481 |
checked( isset( $this->existing_options[ $key ] ) );
|
482 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
483 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
484 |
+
echo '>';
|
485 |
echo esc_html( __( 'Suppress Content Security Policy warnings', 'twitter' ) );
|
486 |
echo '</label>';
|
487 |
|
src/Twitter/WordPress/Admin/Settings/Loader.php
CHANGED
@@ -57,7 +57,7 @@ class Loader
|
|
57 |
*/
|
58 |
public static function pluginActionLinks( $links, $file )
|
59 |
{
|
60 |
-
if (
|
61 |
array_unshift( $links, '<a href="' . esc_url( admin_url( 'admin.php' ) . '?' . http_build_query( array( 'page' => \Twitter\WordPress\Admin\Settings\SinglePage::PAGE_SLUG ) ) ) . '">' . __( 'Settings' ) . '</a>' );
|
62 |
}
|
63 |
|
57 |
*/
|
58 |
public static function pluginActionLinks( $links, $file )
|
59 |
{
|
60 |
+
if ( plugin_basename( \Twitter\WordPress\PluginLoader::getPluginMainFile() === $file ) ) {
|
61 |
array_unshift( $links, '<a href="' . esc_url( admin_url( 'admin.php' ) . '?' . http_build_query( array( 'page' => \Twitter\WordPress\Admin\Settings\SinglePage::PAGE_SLUG ) ) ) . '">' . __( 'Settings' ) . '</a>' );
|
62 |
}
|
63 |
|
src/Twitter/WordPress/Admin/Settings/SinglePage.php
CHANGED
@@ -61,7 +61,11 @@ class SinglePage
|
|
61 |
* @type string fully qualified class name
|
62 |
* }
|
63 |
*/
|
64 |
-
protected static $SETTINGS_COMPONENTS = array(
|
|
|
|
|
|
|
|
|
65 |
|
66 |
/**
|
67 |
* Reference the feature by name
|
@@ -86,16 +90,17 @@ class SinglePage
|
|
86 |
* @type string fully qualified class name
|
87 |
* }
|
88 |
*/
|
89 |
-
public static function getSettingsComponentsForEnabledFeatures()
|
|
|
90 |
$components = static::$SETTINGS_COMPONENTS;
|
91 |
-
$features
|
92 |
|
93 |
if ( ! isset( $features[ \Twitter\WordPress\Features::EMBED_TWEET ] ) ) {
|
94 |
-
unset( $components['\Twitter\WordPress\Admin\Settings\Theme'] );
|
95 |
}
|
96 |
|
97 |
if ( ! isset( $features[ \Twitter\WordPress\Features::TWEET_BUTTON ] ) ) {
|
98 |
-
unset( $components['\Twitter\WordPress\Admin\Settings\
|
99 |
}
|
100 |
|
101 |
return $components;
|
@@ -123,7 +128,7 @@ class SinglePage
|
|
123 |
|
124 |
// hook_suffix may be false if current viewer does not have the manage_options capability
|
125 |
if ( ! $hook_suffix ) {
|
126 |
-
return;
|
127 |
}
|
128 |
$settings->hook_suffix = $hook_suffix;
|
129 |
|
@@ -157,7 +162,7 @@ class SinglePage
|
|
157 |
return;
|
158 |
}
|
159 |
|
160 |
-
do_action( '
|
161 |
|
162 |
echo '<div class="wrap">';
|
163 |
|
@@ -190,6 +195,6 @@ class SinglePage
|
|
190 |
return;
|
191 |
}
|
192 |
|
193 |
-
do_action( '
|
194 |
}
|
195 |
}
|
61 |
* @type string fully qualified class name
|
62 |
* }
|
63 |
*/
|
64 |
+
protected static $SETTINGS_COMPONENTS = array(
|
65 |
+
'\Twitter\WordPress\Admin\Settings\Embeds\Theme',
|
66 |
+
'\Twitter\WordPress\Admin\Settings\Cards\SiteAttribution',
|
67 |
+
'\Twitter\WordPress\Admin\Settings\Buttons\Tweet',
|
68 |
+
);
|
69 |
|
70 |
/**
|
71 |
* Reference the feature by name
|
90 |
* @type string fully qualified class name
|
91 |
* }
|
92 |
*/
|
93 |
+
public static function getSettingsComponentsForEnabledFeatures()
|
94 |
+
{
|
95 |
$components = static::$SETTINGS_COMPONENTS;
|
96 |
+
$features = \Twitter\WordPress\Features::getEnabledFeatures();
|
97 |
|
98 |
if ( ! isset( $features[ \Twitter\WordPress\Features::EMBED_TWEET ] ) ) {
|
99 |
+
unset( $components['\Twitter\WordPress\Admin\Settings\Embeds\Theme'] );
|
100 |
}
|
101 |
|
102 |
if ( ! isset( $features[ \Twitter\WordPress\Features::TWEET_BUTTON ] ) ) {
|
103 |
+
unset( $components['\Twitter\WordPress\Admin\Settings\Buttons\Tweet'] );
|
104 |
}
|
105 |
|
106 |
return $components;
|
128 |
|
129 |
// hook_suffix may be false if current viewer does not have the manage_options capability
|
130 |
if ( ! $hook_suffix ) {
|
131 |
+
return null;
|
132 |
}
|
133 |
$settings->hook_suffix = $hook_suffix;
|
134 |
|
162 |
return;
|
163 |
}
|
164 |
|
165 |
+
do_action( 'add_' . $this->hook_suffix . '_section' );
|
166 |
|
167 |
echo '<div class="wrap">';
|
168 |
|
195 |
return;
|
196 |
}
|
197 |
|
198 |
+
do_action( 'add_' . $this->hook_suffix . '_help_tab', $screen );
|
199 |
}
|
200 |
}
|
src/Twitter/WordPress/Cards/Compatibility.php
CHANGED
@@ -26,7 +26,7 @@ THE SOFTWARE.
|
|
26 |
namespace Twitter\WordPress\Cards;
|
27 |
|
28 |
/**
|
29 |
-
*
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
26 |
namespace Twitter\WordPress\Cards;
|
27 |
|
28 |
/**
|
29 |
+
* Compatibility wrappers for popular WordPress plugins with existing Twitter Cards functionality
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
src/Twitter/WordPress/Cards/Generator.php
CHANGED
@@ -32,6 +32,7 @@ namespace Twitter\WordPress\Cards;
|
|
32 |
*/
|
33 |
class Generator
|
34 |
{
|
|
|
35 |
/**
|
36 |
* Card types supported by the Twitter plugin for WordPress
|
37 |
*
|
@@ -77,6 +78,8 @@ class Generator
|
|
77 |
if ( static::isSupportedCardType( $card_type ) ) {
|
78 |
return (new static::$SUPPORTED_CARDS[ $card_type ]);
|
79 |
}
|
|
|
|
|
80 |
}
|
81 |
|
82 |
/**
|
@@ -94,7 +97,7 @@ class Generator
|
|
94 |
public static function getCardObject( $query_type = null, $object_id = null, $card_type = 'summary' )
|
95 |
{
|
96 |
if ( ! static::isSupportedCardType( $card_type ) ) {
|
97 |
-
return;
|
98 |
}
|
99 |
if ( ! ( is_string( $query_type ) && $query_type ) ) {
|
100 |
$query_type = null;
|
@@ -115,10 +118,10 @@ class Generator
|
|
115 |
|
116 |
$card = static::getCardForType( $card_type );
|
117 |
if ( ! ( $card && is_a( $card, '\Twitter\Cards\Card' ) ) ) {
|
118 |
-
return;
|
119 |
}
|
120 |
|
121 |
-
return static::addSiteAttribution( $card, (
|
122 |
}
|
123 |
|
124 |
/**
|
@@ -129,12 +132,12 @@ class Generator
|
|
129 |
* @param \Twitter\Cards\Card $card Twitter Card object
|
130 |
* @param int|string $post_id WP_Post->ID or proprietary post identifier
|
131 |
*
|
132 |
-
* @return \Twitter\Cards\Card Twitter Card object
|
133 |
*/
|
134 |
public static function addSiteAttribution( $card, $post_id = null )
|
135 |
{
|
136 |
if ( ! is_a( $card, '\Twitter\Cards\Card' ) ) {
|
137 |
-
return;
|
138 |
}
|
139 |
if ( ! method_exists( $card, 'setSite' ) ) {
|
140 |
return $card;
|
@@ -166,6 +169,8 @@ class Generator
|
|
166 |
} else if ( is_archive() ) {
|
167 |
return static::buildArchiveCard();
|
168 |
}
|
|
|
|
|
169 |
}
|
170 |
|
171 |
/**
|
@@ -180,7 +185,7 @@ class Generator
|
|
180 |
$query_type = 'home';
|
181 |
$card = static::getCardObject( $query_type );
|
182 |
if ( ! $card ) {
|
183 |
-
return;
|
184 |
}
|
185 |
|
186 |
/**
|
@@ -237,13 +242,13 @@ class Generator
|
|
237 |
{
|
238 |
$author = get_queried_object();
|
239 |
if ( ! ( $author && isset( $author->ID ) ) ) {
|
240 |
-
return;
|
241 |
}
|
242 |
|
243 |
$query_type = 'author';
|
244 |
$card = static::getCardObject( $query_type, $author->ID );
|
245 |
if ( ! $card ) {
|
246 |
-
return;
|
247 |
}
|
248 |
|
249 |
/** This filter is documented in ::buildHomepageCard */
|
@@ -284,7 +289,7 @@ class Generator
|
|
284 |
$query_type = 'archive';
|
285 |
$card = static::getCardObject( $query_type );
|
286 |
if ( ! $card ) {
|
287 |
-
return;
|
288 |
}
|
289 |
|
290 |
// WP 4.1+ functions
|
@@ -320,41 +325,41 @@ class Generator
|
|
320 |
$post = get_post();
|
321 |
|
322 |
if ( ! $post || ! isset( $post->ID ) ) {
|
323 |
-
return;
|
324 |
}
|
325 |
setup_postdata( $post );
|
326 |
|
327 |
// do not publish card markup for password-protected posts
|
328 |
if ( ! empty( $post->post_password ) ) {
|
329 |
-
return;
|
330 |
}
|
331 |
|
332 |
// only publish card markup for public posts
|
333 |
$post_status_object = get_post_status_object( get_post_status( $post->ID ) );
|
334 |
if ( ! ( $post_status_object && isset( $post_status_object->public ) && $post_status_object->public ) ) {
|
335 |
-
return;
|
336 |
}
|
337 |
|
338 |
// only output Twitter Card markup for public post types
|
339 |
// don't waste page generation time if the page is not meant to be consumed by TwitterBot
|
340 |
$post_type = get_post_type( $post );
|
341 |
if ( ! $post_type ) {
|
342 |
-
return;
|
343 |
}
|
344 |
$post_type_object = get_post_type_object( $post_type );
|
345 |
if ( ! ( $post_type_object && isset( $post_type_object->public ) && $post_status_object->public ) ) {
|
346 |
-
return;
|
347 |
}
|
348 |
|
349 |
$query_type = 'post';
|
350 |
$card = static::getCardObject( $query_type, $post->ID, 'summary' );
|
351 |
if ( ! $card ) {
|
352 |
-
return;
|
353 |
}
|
354 |
|
355 |
$card_class = get_class( $card );
|
356 |
if ( ! $card_class ) {
|
357 |
-
return;
|
358 |
}
|
359 |
|
360 |
// get post-specific overrides
|
@@ -406,7 +411,6 @@ class Generator
|
|
406 |
if ( defined( $card_class . '::MIN_IMAGE_WIDTH' ) && defined( $card_class . '::MIN_IMAGE_HEIGHT' ) ) {
|
407 |
if ( method_exists( $card, 'setImage' ) ) {
|
408 |
// single image card type
|
409 |
-
|
410 |
$cards_image_handler = new \Twitter\WordPress\Cards\ImageHandler();
|
411 |
$cards_image_handler->setLimit( 1 );
|
412 |
$cards_image_handler->setMinWidth( $card::MIN_IMAGE_WIDTH );
|
32 |
*/
|
33 |
class Generator
|
34 |
{
|
35 |
+
|
36 |
/**
|
37 |
* Card types supported by the Twitter plugin for WordPress
|
38 |
*
|
78 |
if ( static::isSupportedCardType( $card_type ) ) {
|
79 |
return (new static::$SUPPORTED_CARDS[ $card_type ]);
|
80 |
}
|
81 |
+
|
82 |
+
return null;
|
83 |
}
|
84 |
|
85 |
/**
|
97 |
public static function getCardObject( $query_type = null, $object_id = null, $card_type = 'summary' )
|
98 |
{
|
99 |
if ( ! static::isSupportedCardType( $card_type ) ) {
|
100 |
+
return null;
|
101 |
}
|
102 |
if ( ! ( is_string( $query_type ) && $query_type ) ) {
|
103 |
$query_type = null;
|
118 |
|
119 |
$card = static::getCardForType( $card_type );
|
120 |
if ( ! ( $card && is_a( $card, '\Twitter\Cards\Card' ) ) ) {
|
121 |
+
return null;
|
122 |
}
|
123 |
|
124 |
+
return static::addSiteAttribution( $card, ( ('post' === $query_type) ? $object_id : null ) );
|
125 |
}
|
126 |
|
127 |
/**
|
132 |
* @param \Twitter\Cards\Card $card Twitter Card object
|
133 |
* @param int|string $post_id WP_Post->ID or proprietary post identifier
|
134 |
*
|
135 |
+
* @return \Twitter\Cards\Card|null Twitter Card object or null if passed card object is invalid
|
136 |
*/
|
137 |
public static function addSiteAttribution( $card, $post_id = null )
|
138 |
{
|
139 |
if ( ! is_a( $card, '\Twitter\Cards\Card' ) ) {
|
140 |
+
return null;
|
141 |
}
|
142 |
if ( ! method_exists( $card, 'setSite' ) ) {
|
143 |
return $card;
|
169 |
} else if ( is_archive() ) {
|
170 |
return static::buildArchiveCard();
|
171 |
}
|
172 |
+
|
173 |
+
return null;
|
174 |
}
|
175 |
|
176 |
/**
|
185 |
$query_type = 'home';
|
186 |
$card = static::getCardObject( $query_type );
|
187 |
if ( ! $card ) {
|
188 |
+
return null;
|
189 |
}
|
190 |
|
191 |
/**
|
242 |
{
|
243 |
$author = get_queried_object();
|
244 |
if ( ! ( $author && isset( $author->ID ) ) ) {
|
245 |
+
return null;
|
246 |
}
|
247 |
|
248 |
$query_type = 'author';
|
249 |
$card = static::getCardObject( $query_type, $author->ID );
|
250 |
if ( ! $card ) {
|
251 |
+
return null;
|
252 |
}
|
253 |
|
254 |
/** This filter is documented in ::buildHomepageCard */
|
289 |
$query_type = 'archive';
|
290 |
$card = static::getCardObject( $query_type );
|
291 |
if ( ! $card ) {
|
292 |
+
return null;
|
293 |
}
|
294 |
|
295 |
// WP 4.1+ functions
|
325 |
$post = get_post();
|
326 |
|
327 |
if ( ! $post || ! isset( $post->ID ) ) {
|
328 |
+
return null;
|
329 |
}
|
330 |
setup_postdata( $post );
|
331 |
|
332 |
// do not publish card markup for password-protected posts
|
333 |
if ( ! empty( $post->post_password ) ) {
|
334 |
+
return null;
|
335 |
}
|
336 |
|
337 |
// only publish card markup for public posts
|
338 |
$post_status_object = get_post_status_object( get_post_status( $post->ID ) );
|
339 |
if ( ! ( $post_status_object && isset( $post_status_object->public ) && $post_status_object->public ) ) {
|
340 |
+
return null;
|
341 |
}
|
342 |
|
343 |
// only output Twitter Card markup for public post types
|
344 |
// don't waste page generation time if the page is not meant to be consumed by TwitterBot
|
345 |
$post_type = get_post_type( $post );
|
346 |
if ( ! $post_type ) {
|
347 |
+
return null;
|
348 |
}
|
349 |
$post_type_object = get_post_type_object( $post_type );
|
350 |
if ( ! ( $post_type_object && isset( $post_type_object->public ) && $post_status_object->public ) ) {
|
351 |
+
return null;
|
352 |
}
|
353 |
|
354 |
$query_type = 'post';
|
355 |
$card = static::getCardObject( $query_type, $post->ID, 'summary' );
|
356 |
if ( ! $card ) {
|
357 |
+
return null;
|
358 |
}
|
359 |
|
360 |
$card_class = get_class( $card );
|
361 |
if ( ! $card_class ) {
|
362 |
+
return null;
|
363 |
}
|
364 |
|
365 |
// get post-specific overrides
|
411 |
if ( defined( $card_class . '::MIN_IMAGE_WIDTH' ) && defined( $card_class . '::MIN_IMAGE_HEIGHT' ) ) {
|
412 |
if ( method_exists( $card, 'setImage' ) ) {
|
413 |
// single image card type
|
|
|
414 |
$cards_image_handler = new \Twitter\WordPress\Cards\ImageHandler();
|
415 |
$cards_image_handler->setLimit( 1 );
|
416 |
$cards_image_handler->setMinWidth( $card::MIN_IMAGE_WIDTH );
|
src/Twitter/WordPress/Cards/ImageHandler.php
CHANGED
@@ -215,7 +215,7 @@ class ImageHandler
|
|
215 |
*
|
216 |
* @since 1.0.0
|
217 |
*
|
218 |
-
* @param WP_Post $post post of interest
|
219 |
*
|
220 |
* @return void
|
221 |
*/
|
@@ -313,9 +313,9 @@ class ImageHandler
|
|
313 |
$intermediate_size = apply_filters( 'twitter_card_intermediate_image_size', 'large', $attachment_id );
|
314 |
// check filtered intermediate size to avoid possible infinite loop
|
315 |
if ( ! $intermediate_size || 'full' === $intermediate_size || ! has_image_size( $intermediate_size ) ) {
|
316 |
-
return;
|
317 |
}
|
318 |
-
return $
|
319 |
}
|
320 |
unset( $bytes );
|
321 |
}
|
@@ -325,16 +325,22 @@ class ImageHandler
|
|
325 |
list( $url, $width, $height ) = wp_get_attachment_image_src( $attachment_id, $size );
|
326 |
|
327 |
if ( empty( $url ) ) {
|
328 |
-
return;
|
329 |
}
|
330 |
$image = new \Twitter\Cards\Components\Image( $url );
|
331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
if ( ! empty( $width ) ) {
|
333 |
$width = absint( $width );
|
334 |
if ( $width ) {
|
335 |
if ( $width < $this->min_width ) {
|
336 |
// reject if image width below required width
|
337 |
-
return;
|
338 |
}
|
339 |
$image->setWidth( $width );
|
340 |
}
|
@@ -344,7 +350,7 @@ class ImageHandler
|
|
344 |
if ( $height ) {
|
345 |
if ( $height < $this->min_height ) {
|
346 |
// reject if image height below required height
|
347 |
-
return;
|
348 |
}
|
349 |
$image->setHeight( $height );
|
350 |
}
|
215 |
*
|
216 |
* @since 1.0.0
|
217 |
*
|
218 |
+
* @param \WP_Post $post post of interest
|
219 |
*
|
220 |
* @return void
|
221 |
*/
|
313 |
$intermediate_size = apply_filters( 'twitter_card_intermediate_image_size', 'large', $attachment_id );
|
314 |
// check filtered intermediate size to avoid possible infinite loop
|
315 |
if ( ! $intermediate_size || 'full' === $intermediate_size || ! has_image_size( $intermediate_size ) ) {
|
316 |
+
return null;
|
317 |
}
|
318 |
+
return $this->attachmentToTwitterImage( $attachment_id, $intermediate_size );
|
319 |
}
|
320 |
unset( $bytes );
|
321 |
}
|
325 |
list( $url, $width, $height ) = wp_get_attachment_image_src( $attachment_id, $size );
|
326 |
|
327 |
if ( empty( $url ) ) {
|
328 |
+
return null;
|
329 |
}
|
330 |
$image = new \Twitter\Cards\Components\Image( $url );
|
331 |
|
332 |
+
$alt = trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) );
|
333 |
+
if ( $alt ) {
|
334 |
+
$image->setAlternativeText( $alt );
|
335 |
+
}
|
336 |
+
unset( $alt );
|
337 |
+
|
338 |
if ( ! empty( $width ) ) {
|
339 |
$width = absint( $width );
|
340 |
if ( $width ) {
|
341 |
if ( $width < $this->min_width ) {
|
342 |
// reject if image width below required width
|
343 |
+
return null;
|
344 |
}
|
345 |
$image->setWidth( $width );
|
346 |
}
|
350 |
if ( $height ) {
|
351 |
if ( $height < $this->min_height ) {
|
352 |
// reject if image height below required height
|
353 |
+
return null;
|
354 |
}
|
355 |
$image->setHeight( $height );
|
356 |
}
|
src/Twitter/WordPress/Content/{TweetButton.php → Buttons/Tweet.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Content;
|
27 |
|
28 |
/**
|
29 |
* Add a Tweet button to post content
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
class
|
34 |
{
|
35 |
/**
|
36 |
* Get the stored site option for Tweet button content
|
@@ -44,7 +44,7 @@ class TweetButton
|
|
44 |
*/
|
45 |
protected static function getOption()
|
46 |
{
|
47 |
-
return get_option( \Twitter\WordPress\Admin\Settings\
|
48 |
}
|
49 |
|
50 |
/**
|
@@ -69,7 +69,7 @@ class TweetButton
|
|
69 |
$position = $options['position'];
|
70 |
unset( $options['position'] );
|
71 |
|
72 |
-
$tweet_button = \Twitter\WordPress\Shortcodes\Share::shortcodeHandler( $options );
|
73 |
if ( $tweet_button ) {
|
74 |
// wrap in newlines to preserve content scanners looking for adjacent content on its own line
|
75 |
$tweet_button = "\n" . $tweet_button . "\n";
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Content\Buttons;
|
27 |
|
28 |
/**
|
29 |
* Add a Tweet button to post content
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
class Tweet
|
34 |
{
|
35 |
/**
|
36 |
* Get the stored site option for Tweet button content
|
44 |
*/
|
45 |
protected static function getOption()
|
46 |
{
|
47 |
+
return get_option( \Twitter\WordPress\Admin\Settings\Buttons\Tweet::OPTION_NAME, array() );
|
48 |
}
|
49 |
|
50 |
/**
|
69 |
$position = $options['position'];
|
70 |
unset( $options['position'] );
|
71 |
|
72 |
+
$tweet_button = \Twitter\WordPress\Shortcodes\Buttons\Share::shortcodeHandler( $options );
|
73 |
if ( $tweet_button ) {
|
74 |
// wrap in newlines to preserve content scanners looking for adjacent content on its own line
|
75 |
$tweet_button = "\n" . $tweet_button . "\n";
|
src/Twitter/WordPress/Features.php
CHANGED
@@ -79,24 +79,70 @@ class Features
|
|
79 |
const EMBED_VINE = 'embed-vine';
|
80 |
|
81 |
/**
|
82 |
-
* Embed a Twitter
|
83 |
*
|
84 |
-
* @since
|
85 |
*
|
86 |
-
* @link https://twitter.com/
|
87 |
*
|
88 |
* @type string
|
89 |
*/
|
90 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
/**
|
93 |
-
* Embed multiple Tweets in a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
*
|
95 |
* @since 1.3.0
|
96 |
*
|
|
|
|
|
97 |
* @type string
|
98 |
*/
|
99 |
-
const
|
100 |
|
101 |
/**
|
102 |
* Display a Twitter follow button using a shortcode
|
@@ -139,8 +185,8 @@ class Features
|
|
139 |
*
|
140 |
* @since 1.3.0
|
141 |
*
|
142 |
-
* @link https://business.twitter.com/help/
|
143 |
-
* @link https://business.twitter.com/help/conversion-tracking-for-websites Twitter conversion tracking for websites
|
144 |
*
|
145 |
* @type string
|
146 |
*/
|
@@ -156,16 +202,20 @@ class Features
|
|
156 |
* @type array
|
157 |
*/
|
158 |
public static $features = array(
|
159 |
-
self::CARDS
|
160 |
-
self::
|
161 |
-
self::
|
162 |
-
self::
|
163 |
-
self::
|
164 |
-
self::
|
165 |
-
self::
|
166 |
-
self::
|
167 |
-
self::
|
168 |
-
self::
|
|
|
|
|
|
|
|
|
169 |
);
|
170 |
|
171 |
/**
|
79 |
const EMBED_VINE = 'embed-vine';
|
80 |
|
81 |
/**
|
82 |
+
* Embed the latest Tweets from a Twitter profile by URL or shortcode
|
83 |
*
|
84 |
+
* @since 2.0.0
|
85 |
*
|
86 |
+
* @link https://dev.twitter.com/web/embedded-timelines/user Embedded Profile Timeline
|
87 |
*
|
88 |
* @type string
|
89 |
*/
|
90 |
+
const EMBED_PROFILE = 'embed-profile';
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Embed the latest Tweets from a list of Twitter accounts by URL or shortcode
|
94 |
+
*
|
95 |
+
* @since 2.0.0
|
96 |
+
*
|
97 |
+
* @link https://dev.twitter.com/web/embedded-timelines/list Embedded List Timeline
|
98 |
+
*
|
99 |
+
* @type string
|
100 |
+
*/
|
101 |
+
const EMBED_LIST = 'embed-list';
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Embed recent Tweets matching a search query configured at twitter.com/settings/widgets
|
105 |
+
*
|
106 |
+
* @since 2.0.0
|
107 |
+
*
|
108 |
+
* @link https://dev.twitter.com/web/embedded-timelines/search Embedded Search Timeline
|
109 |
+
*
|
110 |
+
* @type string
|
111 |
+
*/
|
112 |
+
const EMBED_SEARCH = 'embed-search';
|
113 |
|
114 |
/**
|
115 |
+
* Embed multiple Tweets in a vertical format by URL or shortcode
|
116 |
+
*
|
117 |
+
* @since 2.0.0
|
118 |
+
*
|
119 |
+
* @link https://dev.twitter.com/web/embedded-timelines/collection Embedded Collection
|
120 |
+
*
|
121 |
+
* @type string
|
122 |
+
*/
|
123 |
+
const EMBED_COLLECTION = 'embed-collection';
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Embed multiple Tweets in a vertical format by URL or shortcode
|
127 |
+
*
|
128 |
+
* @since 2.0.0
|
129 |
+
*
|
130 |
+
* @link https://dev.twitter.com/web/embedded-timelines/collection Embedded Collection
|
131 |
+
*
|
132 |
+
* @type string
|
133 |
+
*/
|
134 |
+
const EMBED_COLLECTION_GRID = 'embed-collection-grid';
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Embed a Twitter Moment by URL or shortcode
|
138 |
*
|
139 |
* @since 1.3.0
|
140 |
*
|
141 |
+
* @link https://dev.twitter.com/web/embedded-moments Embedded Moment
|
142 |
+
*
|
143 |
* @type string
|
144 |
*/
|
145 |
+
const EMBED_MOMENT = 'embed-moment';
|
146 |
|
147 |
/**
|
148 |
* Display a Twitter follow button using a shortcode
|
185 |
*
|
186 |
* @since 1.3.0
|
187 |
*
|
188 |
+
* @link https://business.twitter.com/en/help/campaign-setup/campaign-targeting/tailored-audiences-from-web.html Twitter website tag for remarketing
|
189 |
+
* @link https://business.twitter.com/en/help/campaign-measurement-and-analytics/conversion-tracking-for-websites.html Twitter conversion tracking for websites
|
190 |
*
|
191 |
* @type string
|
192 |
*/
|
202 |
* @type array
|
203 |
*/
|
204 |
public static $features = array(
|
205 |
+
self::CARDS => true, // Twitter Cards
|
206 |
+
self::EMBED_TWEET => true, // single Tweet
|
207 |
+
self::EMBED_TWEET_VIDEO => true, // single Tweet with video-specific display template
|
208 |
+
self::EMBED_VINE => true, // single Vine
|
209 |
+
self::EMBED_PROFILE => true, // Twitter profile
|
210 |
+
self::EMBED_LIST => true, // Twitter List
|
211 |
+
self::EMBED_SEARCH => true, // Twitter search
|
212 |
+
self::EMBED_COLLECTION => true, // multiple Tweets organized into a collection
|
213 |
+
self::EMBED_COLLECTION_GRID => true, // multiple Tweets organized into a collection displayed in a grid format
|
214 |
+
self::EMBED_MOMENT => true, // Twitter Moment
|
215 |
+
self::FOLLOW_BUTTON => true, // Twitter Follow button
|
216 |
+
self::TWEET_BUTTON => true, // Tweet button
|
217 |
+
self::PERISCOPE_ON_AIR => true, // Periscope On Air button
|
218 |
+
self::TRACKING_PIXEL => true, // audience and conversion pixel
|
219 |
);
|
220 |
|
221 |
/**
|
src/Twitter/WordPress/Head/AuthorshipLink.php
CHANGED
@@ -45,7 +45,12 @@ class AuthorshipLink
|
|
45 |
{
|
46 |
$site_username = \Twitter\WordPress\Site\Username::getViaAttribution( ( in_the_loop() ? get_the_ID() : null ) );
|
47 |
if ( $site_username ) {
|
48 |
-
echo '<link rel="me" href="' . esc_url( \Twitter\Helpers\TwitterURL::profile( $site_username ), array( 'https', 'http' ) ) . '"'
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
}
|
51 |
}
|
45 |
{
|
46 |
$site_username = \Twitter\WordPress\Site\Username::getViaAttribution( ( in_the_loop() ? get_the_ID() : null ) );
|
47 |
if ( $site_username ) {
|
48 |
+
echo '<link rel="me" href="' . esc_url( \Twitter\Helpers\TwitterURL::profile( $site_username ), array( 'https', 'http' ) ) . '"';
|
49 |
+
|
50 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
51 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
52 |
+
|
53 |
+
echo '>';
|
54 |
}
|
55 |
}
|
56 |
}
|
src/Twitter/WordPress/Head/CardsMetaElements.php
CHANGED
@@ -70,7 +70,10 @@ class CardsMetaElements
|
|
70 |
foreach ( $card_properties as $name => $content ) {
|
71 |
if ( is_array( $content ) && $name ) {
|
72 |
foreach ( $content as $structured_name => $structured_value ) {
|
73 |
-
$html .= \Twitter\WordPress\Head\MetaElement::fromNameContentPair(
|
|
|
|
|
|
|
74 |
}
|
75 |
} else {
|
76 |
$html .= \Twitter\WordPress\Head\MetaElement::fromNameContentPair( $name, $content );
|
@@ -88,6 +91,12 @@ class CardsMetaElements
|
|
88 |
*/
|
89 |
public static function outputMetaElements()
|
90 |
{
|
91 |
-
echo "\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
}
|
93 |
}
|
70 |
foreach ( $card_properties as $name => $content ) {
|
71 |
if ( is_array( $content ) && $name ) {
|
72 |
foreach ( $content as $structured_name => $structured_value ) {
|
73 |
+
$html .= \Twitter\WordPress\Head\MetaElement::fromNameContentPair(
|
74 |
+
( 'src' === $structured_name ) ? $name : $name . ':' . $structured_name,
|
75 |
+
$structured_value
|
76 |
+
);
|
77 |
}
|
78 |
} else {
|
79 |
$html .= \Twitter\WordPress\Head\MetaElement::fromNameContentPair( $name, $content );
|
91 |
*/
|
92 |
public static function outputMetaElements()
|
93 |
{
|
94 |
+
echo "\n";
|
95 |
+
|
96 |
+
// Escaped when building individual elements
|
97 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
98 |
+
echo static::buildMetaElements();
|
99 |
+
|
100 |
+
echo "\n";
|
101 |
}
|
102 |
}
|
src/Twitter/WordPress/Head/WidgetsMetaElements.php
CHANGED
@@ -41,7 +41,7 @@ class WidgetsMetaElements
|
|
41 |
*/
|
42 |
public static function getWidgetOptions()
|
43 |
{
|
44 |
-
return get_option( \Twitter\WordPress\Admin\Settings\Theme::OPTION_NAME );
|
45 |
}
|
46 |
|
47 |
/**
|
@@ -157,8 +157,7 @@ class WidgetsMetaElements
|
|
157 |
public static function outputMetaElements()
|
158 |
{
|
159 |
// escaped in markup builder
|
160 |
-
// @
|
161 |
echo static::buildMetaElements();
|
162 |
-
// @codingStandardsIgnoreEnd WordPress.XSS.EscapeOutput
|
163 |
}
|
164 |
}
|
41 |
*/
|
42 |
public static function getWidgetOptions()
|
43 |
{
|
44 |
+
return get_option( \Twitter\WordPress\Admin\Settings\Embeds\Theme::OPTION_NAME );
|
45 |
}
|
46 |
|
47 |
/**
|
157 |
public static function outputMetaElements()
|
158 |
{
|
159 |
// escaped in markup builder
|
160 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
161 |
echo static::buildMetaElements();
|
|
|
162 |
}
|
163 |
}
|
src/Twitter/WordPress/Helpers/HTMLBuilder.php
CHANGED
@@ -41,7 +41,7 @@ class HTMLBuilder extends \Twitter\Helpers\HTMLBuilder
|
|
41 |
*
|
42 |
* @param string $class possible HTML class
|
43 |
*
|
44 |
-
* @return class name stripped of invalid values or empty string
|
45 |
*/
|
46 |
public static function escapeClassName( $class )
|
47 |
{
|
41 |
*
|
42 |
* @param string $class possible HTML class
|
43 |
*
|
44 |
+
* @return string class name stripped of invalid values or empty string
|
45 |
*/
|
46 |
public static function escapeClassName( $class )
|
47 |
{
|
src/Twitter/WordPress/Helpers/TwitterAPI.php
CHANGED
@@ -104,9 +104,26 @@ class TwitterAPI
|
|
104 |
*/
|
105 |
public static function getUserAgent()
|
106 |
{
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
|
109 |
-
return apply_filters(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
}
|
111 |
|
112 |
/**
|
@@ -117,17 +134,17 @@ class TwitterAPI
|
|
117 |
* @param string $relative_path API path without the response type. e.g. statuses/show
|
118 |
* @param array $parameters query parameters
|
119 |
*
|
120 |
-
* @return stdClass|null json decoded result or null if no JSON returned or issues with parameters
|
121 |
*/
|
122 |
public static function getJSON( $relative_path, $parameters = null )
|
123 |
{
|
124 |
if ( ! $relative_path ) {
|
125 |
-
return;
|
126 |
}
|
127 |
|
128 |
$request_url = static::getAPIURL( $relative_path, $parameters );
|
129 |
if ( ! $request_url ) {
|
130 |
-
return;
|
131 |
}
|
132 |
|
133 |
$response = wp_safe_remote_get(
|
@@ -135,15 +152,15 @@ class TwitterAPI
|
|
135 |
array(
|
136 |
'redirection' => 0,
|
137 |
'httpversion' => '1.1',
|
138 |
-
'user-agent' => static::getUserAgent()
|
139 |
)
|
140 |
);
|
141 |
if ( is_wp_error( $response ) ) {
|
142 |
-
return;
|
143 |
}
|
144 |
$response_body = wp_remote_retrieve_body( $response );
|
145 |
if ( ! $response_body ) {
|
146 |
-
return;
|
147 |
}
|
148 |
|
149 |
$json_response = json_decode( $response_body );
|
@@ -152,5 +169,7 @@ class TwitterAPI
|
|
152 |
if ( $json_response ) {
|
153 |
return $json_response;
|
154 |
}
|
|
|
|
|
155 |
}
|
156 |
}
|
104 |
*/
|
105 |
public static function getUserAgent()
|
106 |
{
|
107 |
+
$wp_version = '';
|
108 |
+
if ( isset( $GLOBALS['wp_version'] ) ) {
|
109 |
+
$wp_version = trim( $GLOBALS['wp_version'] );
|
110 |
+
}
|
111 |
+
$wordpress = 'WordPress';
|
112 |
+
if ( $wp_version ) {
|
113 |
+
$wordpress .= '/' . $wp_version;
|
114 |
+
}
|
115 |
|
116 |
+
return apply_filters(
|
117 |
+
'http_headers_useragent',
|
118 |
+
implode(
|
119 |
+
'; ',
|
120 |
+
array(
|
121 |
+
$wordpress,
|
122 |
+
'TfWP/' . \Twitter\WordPress\PluginLoader::VERSION,
|
123 |
+
get_bloginfo( 'url' ),
|
124 |
+
)
|
125 |
+
)
|
126 |
+
);
|
127 |
}
|
128 |
|
129 |
/**
|
134 |
* @param string $relative_path API path without the response type. e.g. statuses/show
|
135 |
* @param array $parameters query parameters
|
136 |
*
|
137 |
+
* @return \stdClass|null json decoded result or null if no JSON returned or issues with parameters
|
138 |
*/
|
139 |
public static function getJSON( $relative_path, $parameters = null )
|
140 |
{
|
141 |
if ( ! $relative_path ) {
|
142 |
+
return null;
|
143 |
}
|
144 |
|
145 |
$request_url = static::getAPIURL( $relative_path, $parameters );
|
146 |
if ( ! $request_url ) {
|
147 |
+
return null;
|
148 |
}
|
149 |
|
150 |
$response = wp_safe_remote_get(
|
152 |
array(
|
153 |
'redirection' => 0,
|
154 |
'httpversion' => '1.1',
|
155 |
+
'user-agent' => static::getUserAgent(),
|
156 |
)
|
157 |
);
|
158 |
if ( is_wp_error( $response ) ) {
|
159 |
+
return null;
|
160 |
}
|
161 |
$response_body = wp_remote_retrieve_body( $response );
|
162 |
if ( ! $response_body ) {
|
163 |
+
return null;
|
164 |
}
|
165 |
|
166 |
$json_response = json_decode( $response_body );
|
169 |
if ( $json_response ) {
|
170 |
return $json_response;
|
171 |
}
|
172 |
+
|
173 |
+
return null;
|
174 |
}
|
175 |
}
|
src/Twitter/WordPress/JavaScriptLoaders/AsyncJavaScript.php
CHANGED
@@ -44,11 +44,42 @@ abstract class AsyncJavaScript
|
|
44 |
*/
|
45 |
public static function dnsPrefetch()
|
46 |
{
|
47 |
-
|
|
|
48 |
return;
|
49 |
}
|
50 |
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
}
|
53 |
|
54 |
/**
|
@@ -62,10 +93,12 @@ abstract class AsyncJavaScript
|
|
62 |
*/
|
63 |
public static function register()
|
64 |
{
|
|
|
|
|
65 |
global $wp_scripts;
|
66 |
|
67 |
$classname = get_called_class();
|
68 |
-
if ( ! ( defined( $classname . '::QUEUE_HANDLE' ) &&
|
69 |
return false;
|
70 |
}
|
71 |
|
@@ -83,7 +116,7 @@ abstract class AsyncJavaScript
|
|
83 |
}
|
84 |
|
85 |
// replace standard script element with async script element
|
86 |
-
add_filter( 'script_loader_src', array(
|
87 |
|
88 |
if ( defined( $classname . '::SCRIPT_EXTRA' ) && is_string( static::SCRIPT_EXTRA ) && static::SCRIPT_EXTRA ) {
|
89 |
$script = static::SCRIPT_EXTRA;
|
@@ -171,7 +204,7 @@ abstract class AsyncJavaScript
|
|
171 |
return '';
|
172 |
}
|
173 |
|
174 |
-
if ( ! ( is_string( $handle ) &&
|
175 |
return $tag;
|
176 |
}
|
177 |
|
@@ -187,15 +220,17 @@ abstract class AsyncJavaScript
|
|
187 |
*
|
188 |
* @param string $src script URL
|
189 |
* @param string $handle WordPress registered script handle
|
190 |
-
* @global WP_Scripts $wp_scripts match concatenation preferences
|
191 |
*
|
192 |
* @return string empty string if our queue handle requested, else give back the src variable
|
193 |
*/
|
194 |
public static function asyncScriptLoaderSrc( $src, $handle )
|
195 |
{
|
|
|
|
|
196 |
global $wp_scripts;
|
197 |
|
198 |
-
if ( ! ( is_string( $handle ) && defined( get_called_class() . '::QUEUE_HANDLE' ) &&
|
199 |
return $src;
|
200 |
}
|
201 |
|
@@ -204,6 +239,8 @@ abstract class AsyncJavaScript
|
|
204 |
if ( isset( $wp_scripts ) && $wp_scripts->do_concat ) {
|
205 |
$wp_scripts->print_html .= $html;
|
206 |
} else {
|
|
|
|
|
207 |
echo $html;
|
208 |
}
|
209 |
|
@@ -229,7 +266,7 @@ abstract class AsyncJavaScript
|
|
229 |
return '';
|
230 |
}
|
231 |
|
232 |
-
$script = '(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(d.getElementById(id))return;js=d.createElement(s);js.id=id;js.src=' .
|
233 |
|
234 |
if ( $include_script_element_wrapper ) {
|
235 |
return '<script>' . $script . '</script>';
|
44 |
*/
|
45 |
public static function dnsPrefetch()
|
46 |
{
|
47 |
+
$classname = get_called_class();
|
48 |
+
if ( ! ( defined( $classname . '::FQDN' ) && $classname::FQDN ) ) {
|
49 |
return;
|
50 |
}
|
51 |
|
52 |
+
// Output a resource hint link element at a priority later than wp_resource_hints
|
53 |
+
add_action( 'wp_head', array( $classname, 'printDNSPrefetchElement' ) );
|
54 |
+
|
55 |
+
// Use wp_resource_hints if available
|
56 |
+
add_filter( 'wp_resource_hints',
|
57 |
+
(static function ( $urls, $relation_type ) use ( $classname ) {
|
58 |
+
if ( 'dns-prefetch' === $relation_type ) {
|
59 |
+
$urls[] = $classname::FQDN;
|
60 |
+
|
61 |
+
// WordPress will output the resource hint link
|
62 |
+
remove_action( 'wp_head', array( $classname, 'printDNSPrefetchElement' ) );
|
63 |
+
}
|
64 |
+
return $urls;
|
65 |
+
}),
|
66 |
+
10,
|
67 |
+
2 );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Proactively resolve FQDN DNS using a resource hint link
|
72 |
+
*
|
73 |
+
* @since 1.5.0
|
74 |
+
*
|
75 |
+
* @return void
|
76 |
+
*/
|
77 |
+
public static function printDNSPrefetchElement()
|
78 |
+
{
|
79 |
+
echo '<link rel="dns-prefetch" href="//' . esc_attr( static::FQDN ) . '"';
|
80 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
81 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
82 |
+
echo '>' . "\n";
|
83 |
}
|
84 |
|
85 |
/**
|
93 |
*/
|
94 |
public static function register()
|
95 |
{
|
96 |
+
// match global use in Core
|
97 |
+
// @codingStandardsIgnoreLine Squiz.PHP.GlobalKeyword.NotAllowed
|
98 |
global $wp_scripts;
|
99 |
|
100 |
$classname = get_called_class();
|
101 |
+
if ( ! ( defined( $classname . '::QUEUE_HANDLE' ) && $classname::QUEUE_HANDLE && defined( $classname . '::URI' ) && $classname::URI ) ) {
|
102 |
return false;
|
103 |
}
|
104 |
|
116 |
}
|
117 |
|
118 |
// replace standard script element with async script element
|
119 |
+
add_filter( 'script_loader_src', array( $classname, 'asyncScriptLoaderSrc' ), 1, 2 );
|
120 |
|
121 |
if ( defined( $classname . '::SCRIPT_EXTRA' ) && is_string( static::SCRIPT_EXTRA ) && static::SCRIPT_EXTRA ) {
|
122 |
$script = static::SCRIPT_EXTRA;
|
204 |
return '';
|
205 |
}
|
206 |
|
207 |
+
if ( ! ( is_string( $handle ) && static::QUEUE_HANDLE === $handle ) ) {
|
208 |
return $tag;
|
209 |
}
|
210 |
|
220 |
*
|
221 |
* @param string $src script URL
|
222 |
* @param string $handle WordPress registered script handle
|
223 |
+
* @global \WP_Scripts $wp_scripts match concatenation preferences
|
224 |
*
|
225 |
* @return string empty string if our queue handle requested, else give back the src variable
|
226 |
*/
|
227 |
public static function asyncScriptLoaderSrc( $src, $handle )
|
228 |
{
|
229 |
+
// match global use in Core
|
230 |
+
// @codingStandardsIgnoreLine Squiz.PHP.GlobalKeyword.NotAllowed
|
231 |
global $wp_scripts;
|
232 |
|
233 |
+
if ( ! ( is_string( $handle ) && defined( get_called_class() . '::QUEUE_HANDLE' ) && static::QUEUE_HANDLE === $handle ) ) {
|
234 |
return $src;
|
235 |
}
|
236 |
|
239 |
if ( isset( $wp_scripts ) && $wp_scripts->do_concat ) {
|
240 |
$wp_scripts->print_html .= $html;
|
241 |
} else {
|
242 |
+
// escaped when building element
|
243 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
244 |
echo $html;
|
245 |
}
|
246 |
|
266 |
return '';
|
267 |
}
|
268 |
|
269 |
+
$script = '(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(d.getElementById(id))return;js=d.createElement(s);js.id=id;js.src=' . wp_json_encode( static::URI ) . ';fjs.parentNode.insertBefore(js,fjs);}(document,"script",' . wp_json_encode( static::QUEUE_HANDLE ) . '));';
|
270 |
|
271 |
if ( $include_script_element_wrapper ) {
|
272 |
return '<script>' . $script . '</script>';
|
src/Twitter/WordPress/JavaScriptLoaders/Tracking.php
CHANGED
@@ -30,7 +30,7 @@ namespace Twitter\WordPress\JavaScriptLoaders;
|
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
class Tracking
|
34 |
{
|
35 |
/**
|
36 |
* Twitter tracking JavaScript handle
|
@@ -44,60 +44,59 @@ class Tracking
|
|
44 |
const QUEUE_HANDLE = 'twitter-tracking';
|
45 |
|
46 |
/**
|
47 |
-
* Twitter advertising
|
48 |
*
|
49 |
-
*
|
|
|
|
|
50 |
*
|
51 |
* @type string
|
52 |
*/
|
53 |
-
const
|
54 |
|
55 |
/**
|
56 |
-
*
|
57 |
-
*
|
58 |
-
* @since 1.0.0
|
59 |
*
|
60 |
-
* @
|
61 |
-
* @link https://developer.mozilla.org/en-US/docs/Controlling_DNS_prefetching Firefox prefetch behavior
|
62 |
*
|
63 |
-
* @
|
64 |
*/
|
65 |
-
|
66 |
-
{
|
67 |
-
echo '<link rel="dns-prefetch" href="//platform.twitter.com"';
|
68 |
-
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
69 |
-
echo '>' . "\n";
|
70 |
-
}
|
71 |
|
72 |
/**
|
73 |
-
*
|
74 |
*
|
75 |
-
*
|
|
|
|
|
|
|
|
|
76 |
*
|
77 |
-
* @
|
78 |
*/
|
79 |
-
|
80 |
-
{
|
81 |
-
wp_register_script(
|
82 |
-
self::QUEUE_HANDLE,
|
83 |
-
self::URI,
|
84 |
-
array(), // no dependencies
|
85 |
-
null, // no not add extra query parameters for cache busting
|
86 |
-
true // in footer
|
87 |
-
);
|
88 |
-
}
|
89 |
|
90 |
/**
|
91 |
-
*
|
92 |
*
|
93 |
-
*
|
|
|
|
|
94 |
*
|
95 |
-
* @
|
96 |
*
|
97 |
-
* @return
|
98 |
*/
|
99 |
-
public static function
|
100 |
{
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
}
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
class Tracking extends AsyncJavaScript
|
34 |
{
|
35 |
/**
|
36 |
* Twitter tracking JavaScript handle
|
44 |
const QUEUE_HANDLE = 'twitter-tracking';
|
45 |
|
46 |
/**
|
47 |
+
* Twitter advertising widget fully-qualified domain name
|
48 |
*
|
49 |
+
* Used to prefetch DNS lookup
|
50 |
+
*
|
51 |
+
* @since 2.0.0
|
52 |
*
|
53 |
* @type string
|
54 |
*/
|
55 |
+
const FQDN = 'static.ads-twitter.com';
|
56 |
|
57 |
/**
|
58 |
+
* Twitter advertising JavaScript absolute URI
|
|
|
|
|
59 |
*
|
60 |
+
* @since 1.2.0
|
|
|
61 |
*
|
62 |
+
* @type string
|
63 |
*/
|
64 |
+
const URI = 'https://static.ads-twitter.com/uwt.js';
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
/**
|
67 |
+
* Extra JavaScript to be loaded with external JS
|
68 |
*
|
69 |
+
* Initialize the twttr variable to attach ready events before JS loaded
|
70 |
+
*
|
71 |
+
* @see WP_Scripts::print_extra_script()
|
72 |
+
*
|
73 |
+
* @since 2.0.0
|
74 |
*
|
75 |
+
* @type string
|
76 |
*/
|
77 |
+
const SCRIPT_EXTRA = 'window.twq=(function(w){t=w.twq||function(){window.twq.exe?window.twq.exe(window.twq,arguments):window.twq.queue.push(arguments)};t.version="1.1";t.queue=[];return t}(window));';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
/**
|
80 |
+
* Load Twitter ad tracking JS using an inline script block
|
81 |
*
|
82 |
+
* Suitable for unknown render environments where a script block may not be included in a standard enqueue output such as the wp_print_footer_scripts action.
|
83 |
+
*
|
84 |
+
* @since 2.0.0
|
85 |
*
|
86 |
+
* @param bool $include_script_element_wrapper wrap the returned JavaScript string in a script element wrapper
|
87 |
*
|
88 |
+
* @return string HTML script element containing loader script
|
89 |
*/
|
90 |
+
public static function asyncScriptLoaderInline( $include_script_element_wrapper = true )
|
91 |
{
|
92 |
+
$script = '!function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments);
|
93 |
+
},s.version=\'1.1\',s.queue=[],u=t.createElement(n),u.async=!0,u.src=' . wp_json_encode( self::URI ) . ',
|
94 |
+
a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,"script");';
|
95 |
+
|
96 |
+
if ( $include_script_element_wrapper ) {
|
97 |
+
return '<script>' . $script . '</script>';
|
98 |
+
}
|
99 |
+
|
100 |
+
return $script;
|
101 |
}
|
102 |
}
|
src/Twitter/WordPress/JavaScriptLoaders/Widgets.php
CHANGED
@@ -88,8 +88,9 @@ class Widgets extends AsyncJavaScript
|
|
88 |
*
|
89 |
* @return string HTML script element containing loader script
|
90 |
*/
|
91 |
-
public static function asyncScriptLoaderInline( $include_script_element_wrapper = true )
|
92 |
-
|
|
|
93 |
|
94 |
if ( $include_script_element_wrapper ) {
|
95 |
return '<script>' . $script . '</script>';
|
88 |
*
|
89 |
* @return string HTML script element containing loader script
|
90 |
*/
|
91 |
+
public static function asyncScriptLoaderInline( $include_script_element_wrapper = true )
|
92 |
+
{
|
93 |
+
$script = 'window.twttr=(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return t;js=d.createElement(s);js.id=id;js.src=' . wp_json_encode( self::URI ) . ';fjs.parentNode.insertBefore(js,fjs);t._e=[];t.ready=function(f){t._e.push(f);};return t;}(document,"script",' . wp_json_encode( self::QUEUE_HANDLE ) . '));';
|
94 |
|
95 |
if ( $include_script_element_wrapper ) {
|
96 |
return '<script>' . $script . '</script>';
|
src/Twitter/WordPress/PluginLoader.php
CHANGED
@@ -41,7 +41,7 @@ class PluginLoader
|
|
41 |
*
|
42 |
* @type string
|
43 |
*/
|
44 |
-
const VERSION = '
|
45 |
|
46 |
/**
|
47 |
* Unique domain of the plugin's translated text
|
@@ -124,6 +124,29 @@ class PluginLoader
|
|
124 |
load_plugin_textdomain( static::TEXT_DOMAIN );
|
125 |
}
|
126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
/**
|
128 |
* Register widgets
|
129 |
*
|
@@ -134,13 +157,12 @@ class PluginLoader
|
|
134 |
public static function widgetsInit()
|
135 |
{
|
136 |
$features = \Twitter\WordPress\Features::getEnabledFeatures();
|
|
|
137 |
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
if ( isset( $features[ \Twitter\WordPress\Features::PERISCOPE_ON_AIR ] ) ) {
|
143 |
-
register_widget( '\Twitter\WordPress\Widgets\PeriscopeOnAir' );
|
144 |
}
|
145 |
}
|
146 |
|
@@ -162,9 +184,8 @@ class PluginLoader
|
|
162 |
// Twitter settings menu
|
163 |
\Twitter\WordPress\Admin\Settings\Loader::init();
|
164 |
|
165 |
-
if (
|
166 |
-
isset( $features[ \Twitter\WordPress\Features::
|
167 |
-
isset( $features[ \Twitter\WordPress\Features::TWEET_BUTTON ] )
|
168 |
) {
|
169 |
// Edit post meta box
|
170 |
add_action( 'admin_init', array( '\Twitter\WordPress\Admin\Post\MetaBox', 'init' ) );
|
@@ -188,13 +209,13 @@ class PluginLoader
|
|
188 |
$features = \Twitter\WordPress\Features::getEnabledFeatures();
|
189 |
|
190 |
// load widgets JS if a Twitter widget is active
|
191 |
-
if (
|
192 |
-
( isset( $features[ \Twitter\WordPress\Features::
|
193 |
-
( isset( $features[ \Twitter\WordPress\Features::PERISCOPE_ON_AIR ] ) && is_active_widget( false, false, \Twitter\WordPress\Widgets\PeriscopeOnAir::BASE_ID, true ) )
|
194 |
) {
|
195 |
// enqueue after the script is registered in wp_enqueue_scripts action priority 1
|
196 |
add_action( 'wp_enqueue_scripts', array( '\Twitter\WordPress\JavaScriptLoaders\Widgets', 'enqueue' ) );
|
197 |
-
|
|
|
198 |
}
|
199 |
|
200 |
// do not add content filters to HTTP 404 response
|
@@ -220,7 +241,7 @@ class PluginLoader
|
|
220 |
// possibly add Tweet button(s)
|
221 |
add_filter(
|
222 |
'the_content',
|
223 |
-
array( '\Twitter\WordPress\Content\
|
224 |
$twitter_content_priority
|
225 |
);
|
226 |
}
|
@@ -241,11 +262,14 @@ class PluginLoader
|
|
241 |
if ( wp_http_supports( array( 'ssl' => true ) ) ) {
|
242 |
foreach (
|
243 |
array(
|
244 |
-
\Twitter\WordPress\Features::EMBED_TWEET
|
245 |
-
\Twitter\WordPress\Features::EMBED_TWEET_VIDEO
|
246 |
-
\Twitter\WordPress\Features::EMBED_VINE
|
247 |
-
\Twitter\WordPress\Features::
|
248 |
-
\Twitter\WordPress\Features::
|
|
|
|
|
|
|
249 |
) as $feature => $shortcode_class
|
250 |
) {
|
251 |
if ( ! isset( $features[ $feature ] ) ) {
|
@@ -254,20 +278,21 @@ class PluginLoader
|
|
254 |
|
255 |
add_action(
|
256 |
'plugins_loaded',
|
257 |
-
array( $shortcode_namespace . $shortcode_class, 'init' ),
|
258 |
5,
|
259 |
0
|
260 |
);
|
261 |
}
|
262 |
}
|
263 |
|
264 |
-
// initialize buttons and ad pixel if not disabled
|
265 |
foreach (
|
266 |
array(
|
267 |
-
\Twitter\WordPress\Features::FOLLOW_BUTTON => 'Follow',
|
268 |
-
\Twitter\WordPress\Features::TWEET_BUTTON => 'Share',
|
269 |
-
\Twitter\WordPress\Features::PERISCOPE_ON_AIR => '
|
270 |
-
\Twitter\WordPress\Features::
|
|
|
271 |
) as $feature => $shortcode_class
|
272 |
) {
|
273 |
if ( ! isset( $features[ $feature ] ) ) {
|
41 |
*
|
42 |
* @type string
|
43 |
*/
|
44 |
+
const VERSION = '2.0.0';
|
45 |
|
46 |
/**
|
47 |
* Unique domain of the plugin's translated text
|
124 |
load_plugin_textdomain( static::TEXT_DOMAIN );
|
125 |
}
|
126 |
|
127 |
+
/**
|
128 |
+
* Plugin features and corresponding widget class
|
129 |
+
*
|
130 |
+
* @since 2.0.0
|
131 |
+
*
|
132 |
+
* @return array plugin feature and widget class{
|
133 |
+
* @type string plugin feature identifier
|
134 |
+
* @type string WP_Widget class to register
|
135 |
+
* }
|
136 |
+
*/
|
137 |
+
public static function getAvailableWidgets()
|
138 |
+
{
|
139 |
+
return array(
|
140 |
+
\Twitter\WordPress\Features::FOLLOW_BUTTON => '\Twitter\WordPress\Widgets\Buttons\Follow',
|
141 |
+
\Twitter\WordPress\Features::PERISCOPE_ON_AIR => '\Twitter\WordPress\Widgets\Buttons\Periscope\OnAir',
|
142 |
+
\Twitter\WordPress\Features::EMBED_PROFILE => '\Twitter\WordPress\Widgets\Embeds\Timeline\Profile',
|
143 |
+
\Twitter\WordPress\Features::EMBED_LIST => '\Twitter\WordPress\Widgets\Embeds\Timeline\TwitterList',
|
144 |
+
\Twitter\WordPress\Features::EMBED_SEARCH => '\Twitter\WordPress\Widgets\Embeds\Timeline\Search',
|
145 |
+
\Twitter\WordPress\Features::EMBED_COLLECTION => '\Twitter\WordPress\Widgets\Embeds\Timeline\Collection',
|
146 |
+
\Twitter\WordPress\Features::TRACKING_PIXEL => '\Twitter\WordPress\Widgets\Advertising\Tracking',
|
147 |
+
);
|
148 |
+
}
|
149 |
+
|
150 |
/**
|
151 |
* Register widgets
|
152 |
*
|
157 |
public static function widgetsInit()
|
158 |
{
|
159 |
$features = \Twitter\WordPress\Features::getEnabledFeatures();
|
160 |
+
$widgets = static::getAvailableWidgets();
|
161 |
|
162 |
+
foreach ( $widgets as $feature => $widget_class ) {
|
163 |
+
if ( isset( $features[ $feature ] ) ) {
|
164 |
+
register_widget( $widget_class );
|
165 |
+
}
|
|
|
|
|
166 |
}
|
167 |
}
|
168 |
|
184 |
// Twitter settings menu
|
185 |
\Twitter\WordPress\Admin\Settings\Loader::init();
|
186 |
|
187 |
+
if ( isset( $features[ \Twitter\WordPress\Features::CARDS ] )
|
188 |
+
|| isset( $features[ \Twitter\WordPress\Features::TWEET_BUTTON ] )
|
|
|
189 |
) {
|
190 |
// Edit post meta box
|
191 |
add_action( 'admin_init', array( '\Twitter\WordPress\Admin\Post\MetaBox', 'init' ) );
|
209 |
$features = \Twitter\WordPress\Features::getEnabledFeatures();
|
210 |
|
211 |
// load widgets JS if a Twitter widget is active
|
212 |
+
if ( ( isset( $features[ \Twitter\WordPress\Features::FOLLOW_BUTTON ] ) && is_active_widget( false, false, \Twitter\WordPress\Widgets\Buttons\Follow::BASE_ID, true ) )
|
213 |
+
|| ( isset( $features[ \Twitter\WordPress\Features::PERISCOPE_ON_AIR ] ) && is_active_widget( false, false, \Twitter\WordPress\Widgets\Buttons\Periscope\OnAir::BASE_ID, true ) )
|
|
|
214 |
) {
|
215 |
// enqueue after the script is registered in wp_enqueue_scripts action priority 1
|
216 |
add_action( 'wp_enqueue_scripts', array( '\Twitter\WordPress\JavaScriptLoaders\Widgets', 'enqueue' ) );
|
217 |
+
// register DNS prefetch before WordPress resource hints run at wp_head priority 2
|
218 |
+
add_action( 'wp_head', array( '\Twitter\WordPress\JavaScriptLoaders\Widgets', 'dnsPrefetch' ), 1 );
|
219 |
}
|
220 |
|
221 |
// do not add content filters to HTTP 404 response
|
241 |
// possibly add Tweet button(s)
|
242 |
add_filter(
|
243 |
'the_content',
|
244 |
+
array( '\Twitter\WordPress\Content\Buttons\Tweet', 'contentFilter' ),
|
245 |
$twitter_content_priority
|
246 |
);
|
247 |
}
|
262 |
if ( wp_http_supports( array( 'ssl' => true ) ) ) {
|
263 |
foreach (
|
264 |
array(
|
265 |
+
\Twitter\WordPress\Features::EMBED_TWEET => 'Tweet',
|
266 |
+
\Twitter\WordPress\Features::EMBED_TWEET_VIDEO => 'Tweet\\Video',
|
267 |
+
\Twitter\WordPress\Features::EMBED_VINE => 'Vine',
|
268 |
+
\Twitter\WordPress\Features::EMBED_PROFILE => 'Timeline\\Profile',
|
269 |
+
\Twitter\WordPress\Features::EMBED_LIST => 'Timeline\\TwitterList',
|
270 |
+
\Twitter\WordPress\Features::EMBED_COLLECTION => 'Timeline\\Collection',
|
271 |
+
\Twitter\WordPress\Features::EMBED_COLLECTION_GRID => 'Timeline\\CollectionGrid',
|
272 |
+
\Twitter\WordPress\Features::EMBED_MOMENT => 'Moment',
|
273 |
) as $feature => $shortcode_class
|
274 |
) {
|
275 |
if ( ! isset( $features[ $feature ] ) ) {
|
278 |
|
279 |
add_action(
|
280 |
'plugins_loaded',
|
281 |
+
array( $shortcode_namespace . 'Embeds\\' . $shortcode_class, 'init' ),
|
282 |
5,
|
283 |
0
|
284 |
);
|
285 |
}
|
286 |
}
|
287 |
|
288 |
+
// initialize buttons, search timeline, and ad pixel if not disabled
|
289 |
foreach (
|
290 |
array(
|
291 |
+
\Twitter\WordPress\Features::FOLLOW_BUTTON => 'Buttons\\Follow',
|
292 |
+
\Twitter\WordPress\Features::TWEET_BUTTON => 'Buttons\\Share',
|
293 |
+
\Twitter\WordPress\Features::PERISCOPE_ON_AIR => 'Buttons\\Periscope\\OnAir',
|
294 |
+
\Twitter\WordPress\Features::EMBED_SEARCH => 'Embeds\\Timeline\\Search',
|
295 |
+
\Twitter\WordPress\Features::TRACKING_PIXEL => 'Advertising\\Tracking',
|
296 |
) as $feature => $shortcode_class
|
297 |
) {
|
298 |
if ( ! isset( $features[ $feature ] ) ) {
|
src/Twitter/WordPress/Shortcodes/{Tracking.php → Advertising/Tracking.php}
RENAMED
@@ -23,20 +23,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
|
28 |
/**
|
29 |
* Track a Twitter conversion and/or remarketing audience
|
30 |
*
|
31 |
-
* @since
|
32 |
*/
|
33 |
-
class Tracking implements ShortcodeInterface
|
34 |
{
|
35 |
|
36 |
/**
|
37 |
* Shortcode tag to be matched
|
38 |
*
|
39 |
-
* @since
|
40 |
*
|
41 |
* @type string
|
42 |
*/
|
@@ -45,7 +45,7 @@ class Tracking implements ShortcodeInterface
|
|
45 |
/**
|
46 |
* Accepted shortcode attributes and their default values
|
47 |
*
|
48 |
-
* @since
|
49 |
*
|
50 |
* @type array
|
51 |
*/
|
@@ -54,7 +54,7 @@ class Tracking implements ShortcodeInterface
|
|
54 |
/**
|
55 |
* Stored tracking ids
|
56 |
*
|
57 |
-
* @since
|
58 |
*
|
59 |
* @type array
|
60 |
*/
|
@@ -63,23 +63,36 @@ class Tracking implements ShortcodeInterface
|
|
63 |
/**
|
64 |
* Register shortcode macro and handler
|
65 |
*
|
66 |
-
* @since
|
67 |
*
|
68 |
* @return void
|
69 |
*/
|
70 |
public static function init()
|
71 |
{
|
72 |
-
|
|
|
73 |
|
74 |
// Shortcode UI, if supported
|
75 |
add_action(
|
76 |
'register_shortcode_ui',
|
77 |
-
array(
|
78 |
5,
|
79 |
0
|
80 |
);
|
81 |
}
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
/**
|
84 |
* Describe shortcode for Shortcake UI
|
85 |
*
|
@@ -99,7 +112,7 @@ class Tracking implements ShortcodeInterface
|
|
99 |
shortcode_ui_register_for_shortcode(
|
100 |
static::SHORTCODE_TAG,
|
101 |
array(
|
102 |
-
'label' => esc_html(
|
103 |
'listItemImage' => 'dashicons-twitter',
|
104 |
'attrs' => array(
|
105 |
array(
|
@@ -117,34 +130,76 @@ class Tracking implements ShortcodeInterface
|
|
117 |
}
|
118 |
|
119 |
/**
|
120 |
-
*
|
121 |
*
|
122 |
-
* @since
|
123 |
*
|
124 |
-
* @
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
*
|
127 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
*/
|
129 |
-
public static function
|
130 |
{
|
131 |
$options = shortcode_atts(
|
132 |
-
static
|
133 |
$attributes,
|
134 |
static::SHORTCODE_TAG
|
135 |
);
|
136 |
|
137 |
-
$
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
141 |
|
142 |
\Twitter\WordPress\JavaScriptLoaders\Tracking::enqueue();
|
143 |
-
static::$tracking_ids[ $
|
|
|
144 |
|
145 |
-
if ( false === has_action( 'wp_footer', array(
|
146 |
// execute script after wp_print_footer_scripts action completes at priority 20
|
147 |
-
|
|
|
148 |
}
|
149 |
|
150 |
// execute all trackers just before </body>
|
@@ -152,9 +207,9 @@ class Tracking implements ShortcodeInterface
|
|
152 |
}
|
153 |
|
154 |
/**
|
155 |
-
* Track a Twitter advertising event
|
156 |
*
|
157 |
-
* @since
|
158 |
*
|
159 |
* @param string $tracking_id Twitter ads tracking ID
|
160 |
*
|
@@ -162,13 +217,13 @@ class Tracking implements ShortcodeInterface
|
|
162 |
*/
|
163 |
protected static function trackEventUsingJavaScript( $tracking_id )
|
164 |
{
|
165 |
-
echo '
|
166 |
}
|
167 |
|
168 |
/**
|
169 |
* Track a Twitter advertising event using 1x1 images
|
170 |
*
|
171 |
-
* @since
|
172 |
*
|
173 |
* @param string $tracking_id Twitter ads tracking ID
|
174 |
*
|
@@ -178,14 +233,21 @@ class Tracking implements ShortcodeInterface
|
|
178 |
{
|
179 |
$query_parameters = http_build_query( array( 'txn_id' => $tracking_id, 'p_id' => 'Twitter' ), '', '&' );
|
180 |
|
181 |
-
echo '<img height="1" width="1" alt=" " src="' . esc_url( 'https://analytics.twitter.com/i/adsct?' . $query_parameters, array( 'https', 'http' ) )
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
}
|
184 |
|
185 |
/**
|
186 |
* Record tracking ID actions
|
187 |
*
|
188 |
-
* @since
|
189 |
*
|
190 |
* @return void
|
191 |
*/
|
@@ -196,15 +258,16 @@ class Tracking implements ShortcodeInterface
|
|
196 |
}
|
197 |
|
198 |
$tracking_ids = array_keys( static::$tracking_ids );
|
|
|
199 |
|
200 |
// JavaScript available
|
201 |
-
echo '<script type="text/javascript">';
|
202 |
-
array_walk( $tracking_ids, array(
|
203 |
-
echo '</script>';
|
204 |
|
205 |
// JavaScript unavailable
|
206 |
echo '<noscript>';
|
207 |
-
array_walk( $tracking_ids, array(
|
208 |
echo '</noscript>';
|
209 |
}
|
210 |
}
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Advertising;
|
27 |
|
28 |
/**
|
29 |
* Track a Twitter conversion and/or remarketing audience
|
30 |
*
|
31 |
+
* @since 2.0.0
|
32 |
*/
|
33 |
+
class Tracking implements \Twitter\WordPress\Shortcodes\ShortcodeInterface
|
34 |
{
|
35 |
|
36 |
/**
|
37 |
* Shortcode tag to be matched
|
38 |
*
|
39 |
+
* @since 2.0.0
|
40 |
*
|
41 |
* @type string
|
42 |
*/
|
45 |
/**
|
46 |
* Accepted shortcode attributes and their default values
|
47 |
*
|
48 |
+
* @since 2.0.0
|
49 |
*
|
50 |
* @type array
|
51 |
*/
|
54 |
/**
|
55 |
* Stored tracking ids
|
56 |
*
|
57 |
+
* @since 2.0.0
|
58 |
*
|
59 |
* @type array
|
60 |
*/
|
63 |
/**
|
64 |
* Register shortcode macro and handler
|
65 |
*
|
66 |
+
* @since 2.0.0
|
67 |
*
|
68 |
* @return void
|
69 |
*/
|
70 |
public static function init()
|
71 |
{
|
72 |
+
$class = get_called_class();
|
73 |
+
add_shortcode( static::SHORTCODE_TAG, array( $class, 'shortcodeHandler' ) );
|
74 |
|
75 |
// Shortcode UI, if supported
|
76 |
add_action(
|
77 |
'register_shortcode_ui',
|
78 |
+
array( $class, 'shortcodeUI' ),
|
79 |
5,
|
80 |
0
|
81 |
);
|
82 |
}
|
83 |
|
84 |
+
/**
|
85 |
+
* Reference the feature by name
|
86 |
+
*
|
87 |
+
* @since 2.0.0
|
88 |
+
*
|
89 |
+
* @return string translated feature name
|
90 |
+
*/
|
91 |
+
public static function featureName()
|
92 |
+
{
|
93 |
+
return __( 'Twitter Advertising Tracker', 'twitter' );
|
94 |
+
}
|
95 |
+
|
96 |
/**
|
97 |
* Describe shortcode for Shortcake UI
|
98 |
*
|
112 |
shortcode_ui_register_for_shortcode(
|
113 |
static::SHORTCODE_TAG,
|
114 |
array(
|
115 |
+
'label' => esc_html( static::featureName() ),
|
116 |
'listItemImage' => 'dashicons-twitter',
|
117 |
'attrs' => array(
|
118 |
array(
|
130 |
}
|
131 |
|
132 |
/**
|
133 |
+
* Shortcode allowed attributes and default values
|
134 |
*
|
135 |
+
* @since 2.0.0
|
136 |
*
|
137 |
+
* @return array shortcode allowed attributes and default values
|
138 |
+
*/
|
139 |
+
public static function getShortcodeDefaults()
|
140 |
+
{
|
141 |
+
return static::$SHORTCODE_DEFAULTS;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Process shortcode attributes received from the shortcode API
|
146 |
*
|
147 |
+
* @since 2.0.0
|
148 |
+
*
|
149 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
150 |
+
*
|
151 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
152 |
+
*
|
153 |
+
* @return array array processed by shortcode_atts, prepped for Tweet object
|
154 |
*/
|
155 |
+
public static function getShortcodeAttributes( $attributes )
|
156 |
{
|
157 |
$options = shortcode_atts(
|
158 |
+
static::getShortcodeDefaults(),
|
159 |
$attributes,
|
160 |
static::SHORTCODE_TAG
|
161 |
);
|
162 |
|
163 |
+
if ( ! is_array( $options ) || empty( $options ) ) {
|
164 |
+
return array();
|
165 |
+
}
|
166 |
+
|
167 |
+
if ( isset( $options['id'] ) ) {
|
168 |
+
$options['id'] = \Twitter\Helpers\Validators\WebsiteTag::sanitize( $options['id'] );
|
169 |
+
if ( ! $options['id'] ) {
|
170 |
+
unset( $options['id'] );
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
return $options;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Handle shortcode macro
|
179 |
+
*
|
180 |
+
* @since 2.0.0
|
181 |
+
*
|
182 |
+
* @param array $attributes shortcode attributes
|
183 |
+
* @param string $content shortcode content. no effect
|
184 |
+
*
|
185 |
+
* @return string empty string. markup is queued for inclusion in wp_footer output
|
186 |
+
*/
|
187 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
188 |
+
{
|
189 |
+
$options = static::getShortcodeAttributes( $attributes );
|
190 |
+
|
191 |
+
if ( ! isset( $options['id'] ) ) {
|
192 |
+
return '';
|
193 |
}
|
194 |
|
195 |
\Twitter\WordPress\JavaScriptLoaders\Tracking::enqueue();
|
196 |
+
static::$tracking_ids[ $options['id'] ] = true;
|
197 |
+
$class = get_called_class();
|
198 |
|
199 |
+
if ( false === has_action( 'wp_footer', array( $class, 'trackerJavaScript' ) ) ) {
|
200 |
// execute script after wp_print_footer_scripts action completes at priority 20
|
201 |
+
// async function queue should be inserted with footer scripts
|
202 |
+
add_action( 'wp_footer', array( $class, 'trackerJavaScript' ), 25 );
|
203 |
}
|
204 |
|
205 |
// execute all trackers just before </body>
|
207 |
}
|
208 |
|
209 |
/**
|
210 |
+
* Track a Twitter advertising event as a UWT PageView
|
211 |
*
|
212 |
+
* @since 2.0.0
|
213 |
*
|
214 |
* @param string $tracking_id Twitter ads tracking ID
|
215 |
*
|
217 |
*/
|
218 |
protected static function trackEventUsingJavaScript( $tracking_id )
|
219 |
{
|
220 |
+
echo 'twq("init",' . wp_json_encode( $tracking_id ) . ');twq("track","PageView");';
|
221 |
}
|
222 |
|
223 |
/**
|
224 |
* Track a Twitter advertising event using 1x1 images
|
225 |
*
|
226 |
+
* @since 2.0.0
|
227 |
*
|
228 |
* @param string $tracking_id Twitter ads tracking ID
|
229 |
*
|
233 |
{
|
234 |
$query_parameters = http_build_query( array( 'txn_id' => $tracking_id, 'p_id' => 'Twitter' ), '', '&' );
|
235 |
|
236 |
+
echo '<img height="1" width="1" alt=" " src="' . esc_url( 'https://analytics.twitter.com/i/adsct?' . $query_parameters, array( 'https', 'http' ) ) . '"';
|
237 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
238 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
239 |
+
|
240 |
+
echo '><img height="1" width="1" alt=" " src="' . esc_url( 'https://t.co/i/adsct?' . $query_parameters, array( 'https', 'http' ) ) . '"';
|
241 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
242 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
243 |
+
|
244 |
+
echo '>';
|
245 |
}
|
246 |
|
247 |
/**
|
248 |
* Record tracking ID actions
|
249 |
*
|
250 |
+
* @since 2.0.0
|
251 |
*
|
252 |
* @return void
|
253 |
*/
|
258 |
}
|
259 |
|
260 |
$tracking_ids = array_keys( static::$tracking_ids );
|
261 |
+
$class = get_called_class();
|
262 |
|
263 |
// JavaScript available
|
264 |
+
echo '<script type="text/javascript">if(typeof window.twq !== "undefined"){';
|
265 |
+
array_walk( $tracking_ids, array( $class, 'trackEventUsingJavaScript' ) );
|
266 |
+
echo '}</script>';
|
267 |
|
268 |
// JavaScript unavailable
|
269 |
echo '<noscript>';
|
270 |
+
array_walk( $tracking_ids, array( $class, 'trackEventUsingFallbackImages' ) );
|
271 |
echo '</noscript>';
|
272 |
}
|
273 |
}
|
src/Twitter/WordPress/Shortcodes/AuthorContext.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add author context for the current post
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
trait AuthorContext
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Get the Twitter screen name of the author of the current post
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @return string Twitter screen name or empty if no screen name stored
|
41 |
+
*/
|
42 |
+
public static function getScreenName()
|
43 |
+
{
|
44 |
+
$screen_name = \Twitter\WordPress\User\Meta::getTwitterUsername( get_the_author_meta( 'ID' ) );
|
45 |
+
if ( ! $screen_name ) {
|
46 |
+
return '';
|
47 |
+
}
|
48 |
+
|
49 |
+
return $screen_name;
|
50 |
+
}
|
51 |
+
}
|
src/Twitter/WordPress/Shortcodes/Buttons/Follow.php
ADDED
@@ -0,0 +1,244 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2015 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Buttons;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a Follow button
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
*/
|
33 |
+
class Follow implements \Twitter\WordPress\Shortcodes\ShortcodeInterface
|
34 |
+
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\AuthorContext;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 1.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'twitter_follow';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* HTML class to be used in div wrapper
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const HTML_CLASS = 'twitter-follow';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Accepted shortcode attributes and their default values
|
57 |
+
*
|
58 |
+
* @since 1.0.0
|
59 |
+
*
|
60 |
+
* @type array
|
61 |
+
*/
|
62 |
+
public static $SHORTCODE_DEFAULTS = array( 'screen_name' => '', 'show_count' => true, 'show_screen_name' => true, 'size' => 'medium' );
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Attach handlers for a follow button
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @return void
|
70 |
+
*/
|
71 |
+
public static function init()
|
72 |
+
{
|
73 |
+
$classname = get_called_class();
|
74 |
+
|
75 |
+
// register our shortcode and its handler
|
76 |
+
add_shortcode( static::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
77 |
+
|
78 |
+
// Shortcode UI, if supported
|
79 |
+
add_action(
|
80 |
+
'register_shortcode_ui',
|
81 |
+
array( $classname, 'shortcodeUI' ),
|
82 |
+
5,
|
83 |
+
0
|
84 |
+
);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Reference the feature by name
|
89 |
+
*
|
90 |
+
* @since 2.0.0
|
91 |
+
*
|
92 |
+
* @return string translated feature name
|
93 |
+
*/
|
94 |
+
public static function featureName()
|
95 |
+
{
|
96 |
+
return __( 'Follow Button', 'twitter' );
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Describe shortcode for Shortcake UI
|
101 |
+
*
|
102 |
+
* @since 1.1.0
|
103 |
+
*
|
104 |
+
* @link https://github.com/fusioneng/Shortcake Shortcake UI
|
105 |
+
*
|
106 |
+
* @return void
|
107 |
+
*/
|
108 |
+
public static function shortcodeUI()
|
109 |
+
{
|
110 |
+
// Shortcake required
|
111 |
+
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
112 |
+
return;
|
113 |
+
}
|
114 |
+
|
115 |
+
shortcode_ui_register_for_shortcode(
|
116 |
+
static::SHORTCODE_TAG,
|
117 |
+
array(
|
118 |
+
'label' => esc_html( static::featureName() ),
|
119 |
+
'listItemImage' => 'dashicons-twitter',
|
120 |
+
'attrs' => array(
|
121 |
+
array(
|
122 |
+
'attr' => 'screen_name',
|
123 |
+
'label' => esc_html( __( 'Twitter @username', 'twitter' ) ),
|
124 |
+
'type' => 'text',
|
125 |
+
'meta' => array(
|
126 |
+
'placeholder' => 'WordPress',
|
127 |
+
'pattern' => \Twitter\Helpers\Validators\ScreenName::getPattern(),
|
128 |
+
),
|
129 |
+
),
|
130 |
+
array(
|
131 |
+
'attr' => 'size',
|
132 |
+
'label' => esc_html( __( 'Button size:', 'twitter' ) ),
|
133 |
+
'type' => 'radio',
|
134 |
+
'value' => '',
|
135 |
+
'options' => array(
|
136 |
+
'' => esc_html( _x( 'medium', 'medium size button', 'twitter' ) ),
|
137 |
+
'large' => esc_html( _x( 'large', 'large size button', 'twitter' ) ),
|
138 |
+
),
|
139 |
+
),
|
140 |
+
),
|
141 |
+
)
|
142 |
+
);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Shortcode allowed attributes and default values
|
147 |
+
*
|
148 |
+
* @since 2.0.0
|
149 |
+
*
|
150 |
+
* @return array shortcode allowed attributes and default values
|
151 |
+
*/
|
152 |
+
public static function getShortcodeDefaults()
|
153 |
+
{
|
154 |
+
return static::$SHORTCODE_DEFAULTS;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Process shortcode attributes received from the shortcode API
|
159 |
+
*
|
160 |
+
* @since 2.0.0
|
161 |
+
*
|
162 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
163 |
+
*
|
164 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
165 |
+
*
|
166 |
+
* @return array array processed by shortcode_atts, prepped for Tweet object
|
167 |
+
*/
|
168 |
+
public static function getShortcodeAttributes( $attributes )
|
169 |
+
{
|
170 |
+
$options = shortcode_atts(
|
171 |
+
static::getShortcodeDefaults(),
|
172 |
+
$attributes,
|
173 |
+
static::SHORTCODE_TAG
|
174 |
+
);
|
175 |
+
|
176 |
+
if ( ! is_array( $options ) || empty( $options ) ) {
|
177 |
+
return array();
|
178 |
+
}
|
179 |
+
|
180 |
+
if ( isset( $attributes['screen_name'] ) ) {
|
181 |
+
$attributes['screen_name'] = \Twitter\Helpers\Validators\ScreenName::trim( $attributes['screen_name'] );
|
182 |
+
if ( ! $attributes['screen_name'] ) {
|
183 |
+
unset( $attributes['screen_name'] );
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
$attributes = \Twitter\WordPress\Shortcodes\Helpers\Attributes::booleanOption(
|
188 |
+
$attributes,
|
189 |
+
array( 'show_count', 'show_screen_name' )
|
190 |
+
);
|
191 |
+
|
192 |
+
// large is the only option
|
193 |
+
if ( isset( $attributes['size'] ) ) {
|
194 |
+
if ( is_string( $attributes['size'] ) && in_array( strtolower( $attributes['size'] ), array( 'large', 'l' ), /* strict */ true ) ) {
|
195 |
+
$attributes['size'] = 'large';
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
return $attributes;
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Handle shortcode macro
|
204 |
+
*
|
205 |
+
* @since 1.0.0
|
206 |
+
*
|
207 |
+
* @param array $attributes shortcode attributes
|
208 |
+
* @param string $content shortcode content. no effect
|
209 |
+
*
|
210 |
+
* @return string Follow button HTML or empty string
|
211 |
+
*/
|
212 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
213 |
+
{
|
214 |
+
$options = static::getShortcodeAttributes( $attributes );
|
215 |
+
|
216 |
+
if ( ! isset( $options['screen_name'] ) ) {
|
217 |
+
$options['screen_name'] = static::getScreenName();
|
218 |
+
}
|
219 |
+
|
220 |
+
// follow target required
|
221 |
+
if ( ! $options['screen_name'] ) {
|
222 |
+
return '';
|
223 |
+
}
|
224 |
+
|
225 |
+
$follow = \Twitter\Widgets\Buttons\Follow::fromArray( $options );
|
226 |
+
if ( ! $follow ) {
|
227 |
+
return '';
|
228 |
+
}
|
229 |
+
|
230 |
+
$html = $follow->toHTML( _x( 'Follow %s', 'Follow a Twitter user', 'twitter' ), '\Twitter\WordPress\Helpers\HTMLBuilder' );
|
231 |
+
if ( ! $html ) {
|
232 |
+
return '';
|
233 |
+
}
|
234 |
+
|
235 |
+
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
236 |
+
|
237 |
+
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
238 |
+
if ( $inline_js ) {
|
239 |
+
return $html . $inline_js;
|
240 |
+
}
|
241 |
+
|
242 |
+
return $html;
|
243 |
+
}
|
244 |
+
}
|
src/Twitter/WordPress/Shortcodes/{PeriscopeOnAir.php → Buttons/Periscope/OnAir.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
|
28 |
/**
|
29 |
* Display a Periscope On Air button
|
30 |
*
|
31 |
* @since 1.3.0
|
32 |
*/
|
33 |
-
class
|
34 |
{
|
35 |
|
36 |
/**
|
@@ -42,6 +42,15 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
42 |
*/
|
43 |
const SHORTCODE_TAG = 'periscope_on_air';
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
/**
|
46 |
* Regex used to match a Periscope profile URL in text
|
47 |
*
|
@@ -88,6 +97,18 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
88 |
);
|
89 |
}
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
/**
|
92 |
* Describe shortcode for Shortcake UI
|
93 |
*
|
@@ -107,7 +128,7 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
107 |
shortcode_ui_register_for_shortcode(
|
108 |
static::SHORTCODE_TAG,
|
109 |
array(
|
110 |
-
'label' => esc_html(
|
111 |
'listItemImage' => 'dashicons-video-alt',
|
112 |
'attrs' => array(
|
113 |
array(
|
@@ -126,7 +147,7 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
126 |
'value' => '',
|
127 |
'options' => array(
|
128 |
'' => esc_html( _x( 'small', 'small size button', 'twitter' ) ),
|
129 |
-
'large' => esc_html( _x( 'large',
|
130 |
),
|
131 |
),
|
132 |
),
|
@@ -139,14 +160,11 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
139 |
*
|
140 |
* @since 1.3.0
|
141 |
*
|
142 |
-
* @param array
|
143 |
-
* @param array $attr Embed attributes. Not used.
|
144 |
-
* @param string $url The original URL that was matched by the regex. Not used.
|
145 |
-
* @param array $rawattr The original unmodified attributes. Not used.
|
146 |
*
|
147 |
* @return string HTML markup for the Periscope On Air button or an empty string if requirements not met
|
148 |
*/
|
149 |
-
public static function linkHandler( $matches
|
150 |
{
|
151 |
if ( ! ( is_array( $matches ) && isset( $matches[2] ) && $matches[2] ) ) {
|
152 |
return '';
|
@@ -156,65 +174,72 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
156 |
}
|
157 |
|
158 |
/**
|
159 |
-
*
|
160 |
*
|
161 |
* @since 1.3.0
|
162 |
*
|
163 |
-
* @
|
164 |
-
* @type string shortcode attribute name
|
165 |
-
* @type mixed shortcode attribute value
|
166 |
-
* }
|
167 |
-
*
|
168 |
-
* @return array simplified shortcode values with defaults removed {
|
169 |
-
* @type string shortcode attribute name
|
170 |
-
* @type bool|string shortcode attribute value
|
171 |
-
* }
|
172 |
*/
|
173 |
-
public static function
|
174 |
{
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
$options = array();
|
180 |
-
|
181 |
-
if ( isset( $attributes['username'] ) ) {
|
182 |
-
$username = \Twitter\Helpers\Validators\PeriscopeUsername::trim( $attributes['username'] );
|
183 |
-
if ( $username ) {
|
184 |
-
$options['username'] = $username;
|
185 |
-
}
|
186 |
-
unset( $username );
|
187 |
}
|
188 |
|
189 |
-
|
190 |
-
|
191 |
-
if ( is_string( $attributes['size'] ) && in_array( strtolower( $attributes['size'] ), array( 'large', 'l' ) ) ) {
|
192 |
-
$options['size'] = 'large';
|
193 |
-
}
|
194 |
-
}
|
195 |
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
}
|
198 |
|
199 |
/**
|
200 |
-
*
|
201 |
*
|
202 |
-
* @since
|
203 |
*
|
204 |
-
* @
|
|
|
|
|
|
|
|
|
205 |
*/
|
206 |
-
public static function
|
207 |
{
|
208 |
-
|
209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
}
|
211 |
|
212 |
-
|
213 |
-
|
214 |
-
|
|
|
|
|
215 |
}
|
216 |
|
217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
}
|
219 |
|
220 |
/**
|
@@ -229,37 +254,18 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
229 |
*/
|
230 |
public static function shortcodeHandler( $attributes, $content = '' )
|
231 |
{
|
232 |
-
|
233 |
-
// apply the same filter as shortcode_atts
|
234 |
-
/** This filter is documented in wp-includes/shortcodes.php */
|
235 |
-
$options = apply_filters(
|
236 |
-
'shortcode_atts_' . self::SHORTCODE_TAG,
|
237 |
-
array_merge(
|
238 |
-
static::$SHORTCODE_DEFAULTS,
|
239 |
-
static::sanitizeShortcodeParameters( (array) $attributes )
|
240 |
-
),
|
241 |
-
static::$SHORTCODE_DEFAULTS,
|
242 |
-
$attributes
|
243 |
-
);
|
244 |
|
245 |
-
$username
|
246 |
-
|
247 |
-
$username = $options['username'];
|
248 |
-
unset( $options['username'] );
|
249 |
-
}
|
250 |
-
if ( ! $username ) {
|
251 |
-
$username = static::getUsername();
|
252 |
-
// user target required
|
253 |
-
if ( ! $username ) {
|
254 |
-
return '';
|
255 |
-
}
|
256 |
}
|
257 |
|
258 |
-
//
|
259 |
-
$options['username']
|
260 |
-
|
|
|
261 |
|
262 |
-
$on_air = \Twitter\Widgets\
|
263 |
if ( ! $on_air ) {
|
264 |
return '';
|
265 |
}
|
@@ -269,7 +275,7 @@ class PeriscopeOnAir implements ShortcodeInterface
|
|
269 |
return '';
|
270 |
}
|
271 |
|
272 |
-
$html = '<div class="
|
273 |
|
274 |
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
275 |
if ( $inline_js ) {
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Buttons\Periscope;
|
27 |
|
28 |
/**
|
29 |
* Display a Periscope On Air button
|
30 |
*
|
31 |
* @since 1.3.0
|
32 |
*/
|
33 |
+
class OnAir implements \Twitter\WordPress\Shortcodes\ShortcodeInterface
|
34 |
{
|
35 |
|
36 |
/**
|
42 |
*/
|
43 |
const SHORTCODE_TAG = 'periscope_on_air';
|
44 |
|
45 |
+
/**
|
46 |
+
* HTML class to be used in div wrapper
|
47 |
+
*
|
48 |
+
* @since 2.0.0
|
49 |
+
*
|
50 |
+
* @type string
|
51 |
+
*/
|
52 |
+
const HTML_CLASS = 'periscope-on-air';
|
53 |
+
|
54 |
/**
|
55 |
* Regex used to match a Periscope profile URL in text
|
56 |
*
|
97 |
);
|
98 |
}
|
99 |
|
100 |
+
/**
|
101 |
+
* Reference the feature by name
|
102 |
+
*
|
103 |
+
* @since 2.0.0
|
104 |
+
*
|
105 |
+
* @return string translated feature name
|
106 |
+
*/
|
107 |
+
public static function featureName()
|
108 |
+
{
|
109 |
+
return __( 'Periscope On Air Button', 'twitter' );
|
110 |
+
}
|
111 |
+
|
112 |
/**
|
113 |
* Describe shortcode for Shortcake UI
|
114 |
*
|
128 |
shortcode_ui_register_for_shortcode(
|
129 |
static::SHORTCODE_TAG,
|
130 |
array(
|
131 |
+
'label' => esc_html( static::featureName() ),
|
132 |
'listItemImage' => 'dashicons-video-alt',
|
133 |
'attrs' => array(
|
134 |
array(
|
147 |
'value' => '',
|
148 |
'options' => array(
|
149 |
'' => esc_html( _x( 'small', 'small size button', 'twitter' ) ),
|
150 |
+
'large' => esc_html( _x( 'large', 'large size button', 'twitter' ) ),
|
151 |
),
|
152 |
),
|
153 |
),
|
160 |
*
|
161 |
* @since 1.3.0
|
162 |
*
|
163 |
+
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
|
|
|
|
|
|
164 |
*
|
165 |
* @return string HTML markup for the Periscope On Air button or an empty string if requirements not met
|
166 |
*/
|
167 |
+
public static function linkHandler( $matches )
|
168 |
{
|
169 |
if ( ! ( is_array( $matches ) && isset( $matches[2] ) && $matches[2] ) ) {
|
170 |
return '';
|
174 |
}
|
175 |
|
176 |
/**
|
177 |
+
* Get the Periscope username of the author of the current post
|
178 |
*
|
179 |
* @since 1.3.0
|
180 |
*
|
181 |
+
* @return string Periscope username or empty if no screen name stored
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
*/
|
183 |
+
public static function getUsername()
|
184 |
{
|
185 |
+
$username = \Twitter\WordPress\User\Meta::getPeriscopeUsername( get_the_author_meta( 'ID' ) );
|
186 |
+
if ( ! $username ) {
|
187 |
+
return '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
}
|
189 |
|
190 |
+
return $username;
|
191 |
+
}
|
|
|
|
|
|
|
|
|
192 |
|
193 |
+
/**
|
194 |
+
* Shortcode allowed attributes and default values
|
195 |
+
*
|
196 |
+
* @since 2.0.0
|
197 |
+
*
|
198 |
+
* @return array shortcode allowed attributes and default values
|
199 |
+
*/
|
200 |
+
public static function getShortcodeDefaults()
|
201 |
+
{
|
202 |
+
return static::$SHORTCODE_DEFAULTS;
|
203 |
}
|
204 |
|
205 |
/**
|
206 |
+
* Process shortcode attributes received from the shortcode API
|
207 |
*
|
208 |
+
* @since 2.0.0
|
209 |
*
|
210 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
211 |
+
*
|
212 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
213 |
+
*
|
214 |
+
* @return array array processed by shortcode_atts, prepped for Tweet object
|
215 |
*/
|
216 |
+
public static function getShortcodeAttributes( $attributes )
|
217 |
{
|
218 |
+
$options = shortcode_atts(
|
219 |
+
static::getShortcodeDefaults(),
|
220 |
+
$attributes,
|
221 |
+
static::SHORTCODE_TAG
|
222 |
+
);
|
223 |
+
|
224 |
+
if ( ! is_array( $options ) || empty( $options ) ) {
|
225 |
+
return array();
|
226 |
}
|
227 |
|
228 |
+
if ( isset( $options['username'] ) ) {
|
229 |
+
$options['username'] = \Twitter\Helpers\Validators\PeriscopeUsername::trim( $options['username'] );
|
230 |
+
if ( ! $options['username'] ) {
|
231 |
+
unset( $options['username'] );
|
232 |
+
}
|
233 |
}
|
234 |
|
235 |
+
$options = \Twitter\WordPress\Shortcodes\Helpers\Attributes::lowercaseStringOption( $options, array( 'size' ) );
|
236 |
+
|
237 |
+
// allow abbreviated size value
|
238 |
+
if ( isset( $options['size'] ) && 'l' === $options['size'] ) {
|
239 |
+
$options['size'] = 'large';
|
240 |
+
}
|
241 |
+
|
242 |
+
return $options;
|
243 |
}
|
244 |
|
245 |
/**
|
254 |
*/
|
255 |
public static function shortcodeHandler( $attributes, $content = '' )
|
256 |
{
|
257 |
+
$options = static::getShortcodeAttributes( $attributes );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
|
259 |
+
if ( ! isset( $options['username'] ) ) {
|
260 |
+
$options['username'] = static::getUsername();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
}
|
262 |
|
263 |
+
// on air target required
|
264 |
+
if ( ! $options['username'] ) {
|
265 |
+
return '';
|
266 |
+
}
|
267 |
|
268 |
+
$on_air = \Twitter\Widgets\Buttons\Periscope\OnAir::fromArray( $options );
|
269 |
if ( ! $on_air ) {
|
270 |
return '';
|
271 |
}
|
275 |
return '';
|
276 |
}
|
277 |
|
278 |
+
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
279 |
|
280 |
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
281 |
if ( $inline_js ) {
|
src/Twitter/WordPress/Shortcodes/{Share.php → Buttons/Share.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
|
28 |
/**
|
29 |
* Display a Tweet Web Intent and queue JavaScript for conversion to a Tweet button
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
-
class Share implements ShortcodeInterface
|
34 |
{
|
35 |
|
36 |
/**
|
@@ -42,6 +42,15 @@ class Share implements ShortcodeInterface
|
|
42 |
*/
|
43 |
const SHORTCODE_TAG = 'twitter_share';
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
/**
|
46 |
* Accepted shortcode attributes and their default values
|
47 |
*
|
@@ -71,6 +80,18 @@ class Share implements ShortcodeInterface
|
|
71 |
);
|
72 |
}
|
73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
/**
|
75 |
* Describe shortcode for Shortcake UI
|
76 |
*
|
@@ -90,7 +111,7 @@ class Share implements ShortcodeInterface
|
|
90 |
shortcode_ui_register_for_shortcode(
|
91 |
static::SHORTCODE_TAG,
|
92 |
array(
|
93 |
-
'label' => esc_html(
|
94 |
'listItemImage' => 'dashicons-twitter',
|
95 |
'attrs' => array(
|
96 |
array(
|
@@ -110,7 +131,7 @@ class Share implements ShortcodeInterface
|
|
110 |
'value' => '',
|
111 |
'options' => array(
|
112 |
'' => esc_html( _x( 'medium', 'medium size button', 'twitter' ) ),
|
113 |
-
'large' => esc_html( _x( 'large',
|
114 |
),
|
115 |
),
|
116 |
),
|
@@ -217,7 +238,7 @@ class Share implements ShortcodeInterface
|
|
217 |
$options = array();
|
218 |
|
219 |
if ( isset( $attributes['in_reply_to'] ) ) {
|
220 |
-
$tweet_id = \Twitter\WordPress\Shortcodes\
|
221 |
if ( $tweet_id ) {
|
222 |
$options['in_reply_to'] = $tweet_id;
|
223 |
}
|
@@ -270,7 +291,7 @@ class Share implements ShortcodeInterface
|
|
270 |
|
271 |
// large is the only option
|
272 |
if ( isset( $attributes['size'] ) ) {
|
273 |
-
if ( is_string( $attributes['size'] ) && in_array( strtolower( $attributes['size'] ), array( 'large', 'l' ) ) ) {
|
274 |
$options['size'] = 'large';
|
275 |
}
|
276 |
}
|
@@ -283,11 +304,11 @@ class Share implements ShortcodeInterface
|
|
283 |
*
|
284 |
* @since 1.0.0
|
285 |
*
|
286 |
-
* @param array
|
287 |
* @type string option name
|
288 |
* @type string|bool option value
|
289 |
* }
|
290 |
-
* @param WP_Post $post post of interest
|
291 |
*
|
292 |
* @return array Tweet button options with possible additions based on post data {
|
293 |
* @type string option name
|
@@ -340,21 +361,22 @@ class Share implements ShortcodeInterface
|
|
340 |
}
|
341 |
|
342 |
/**
|
343 |
-
*
|
344 |
*
|
345 |
-
* @since
|
346 |
*
|
347 |
-
* @
|
348 |
-
* @param string $content shortcode content. no effect
|
349 |
*
|
350 |
-
* @
|
|
|
|
|
351 |
*/
|
352 |
-
public static function
|
353 |
{
|
354 |
// clean up attribute to shortcode option mappings before passing to filter
|
355 |
// apply the same filter as shortcode_atts
|
356 |
/** This filter is documented in wp-includes/shortcodes.php */
|
357 |
-
|
358 |
'shortcode_atts_' . self::SHORTCODE_TAG,
|
359 |
array_merge(
|
360 |
static::$SHORTCODE_DEFAULTS,
|
@@ -363,11 +385,26 @@ class Share implements ShortcodeInterface
|
|
363 |
static::$SHORTCODE_DEFAULTS,
|
364 |
$attributes
|
365 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
|
367 |
// add options shared to post meta
|
368 |
$options = static::addPostMetaOptions( $options );
|
369 |
|
370 |
-
//
|
371 |
if ( in_the_loop() ) {
|
372 |
$post = get_post();
|
373 |
|
@@ -398,7 +435,7 @@ class Share implements ShortcodeInterface
|
|
398 |
unset( $via_username );
|
399 |
}
|
400 |
|
401 |
-
$button = \Twitter\Widgets\
|
402 |
if ( ! $button ) {
|
403 |
return '';
|
404 |
}
|
@@ -408,7 +445,7 @@ class Share implements ShortcodeInterface
|
|
408 |
return '';
|
409 |
}
|
410 |
|
411 |
-
$html = '<div class="
|
412 |
|
413 |
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
414 |
if ( $inline_js ) {
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Buttons;
|
27 |
|
28 |
/**
|
29 |
* Display a Tweet Web Intent and queue JavaScript for conversion to a Tweet button
|
30 |
*
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
+
class Share implements \Twitter\WordPress\Shortcodes\ShortcodeInterface
|
34 |
{
|
35 |
|
36 |
/**
|
42 |
*/
|
43 |
const SHORTCODE_TAG = 'twitter_share';
|
44 |
|
45 |
+
/**
|
46 |
+
* HTML class to be used in div wrapper
|
47 |
+
*
|
48 |
+
* @since 2.0.0
|
49 |
+
*
|
50 |
+
* @type string
|
51 |
+
*/
|
52 |
+
const HTML_CLASS = 'twitter-share';
|
53 |
+
|
54 |
/**
|
55 |
* Accepted shortcode attributes and their default values
|
56 |
*
|
80 |
);
|
81 |
}
|
82 |
|
83 |
+
/**
|
84 |
+
* Reference the feature by name
|
85 |
+
*
|
86 |
+
* @since 2.0.0
|
87 |
+
*
|
88 |
+
* @return string translated feature name
|
89 |
+
*/
|
90 |
+
public static function featureName()
|
91 |
+
{
|
92 |
+
return __( 'Tweet Button', 'twitter' );
|
93 |
+
}
|
94 |
+
|
95 |
/**
|
96 |
* Describe shortcode for Shortcake UI
|
97 |
*
|
111 |
shortcode_ui_register_for_shortcode(
|
112 |
static::SHORTCODE_TAG,
|
113 |
array(
|
114 |
+
'label' => esc_html( static::featureName() ),
|
115 |
'listItemImage' => 'dashicons-twitter',
|
116 |
'attrs' => array(
|
117 |
array(
|
131 |
'value' => '',
|
132 |
'options' => array(
|
133 |
'' => esc_html( _x( 'medium', 'medium size button', 'twitter' ) ),
|
134 |
+
'large' => esc_html( _x( 'large', 'large size button', 'twitter' ) ),
|
135 |
),
|
136 |
),
|
137 |
),
|
238 |
$options = array();
|
239 |
|
240 |
if ( isset( $attributes['in_reply_to'] ) ) {
|
241 |
+
$tweet_id = \Twitter\WordPress\Shortcodes\Embeds\Tweet::sanitizeTweetID( (string) $attributes['in_reply_to'] );
|
242 |
if ( $tweet_id ) {
|
243 |
$options['in_reply_to'] = $tweet_id;
|
244 |
}
|
291 |
|
292 |
// large is the only option
|
293 |
if ( isset( $attributes['size'] ) ) {
|
294 |
+
if ( is_string( $attributes['size'] ) && in_array( strtolower( $attributes['size'] ), array( 'large', 'l' ), /* strict */ true ) ) {
|
295 |
$options['size'] = 'large';
|
296 |
}
|
297 |
}
|
304 |
*
|
305 |
* @since 1.0.0
|
306 |
*
|
307 |
+
* @param array $options Tweet button options {
|
308 |
* @type string option name
|
309 |
* @type string|bool option value
|
310 |
* }
|
311 |
+
* @param \WP_Post $post post of interest
|
312 |
*
|
313 |
* @return array Tweet button options with possible additions based on post data {
|
314 |
* @type string option name
|
361 |
}
|
362 |
|
363 |
/**
|
364 |
+
* Process shortcode attributes received from the shortcode API
|
365 |
*
|
366 |
+
* @since 2.0.0
|
367 |
*
|
368 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
|
|
369 |
*
|
370 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
371 |
+
*
|
372 |
+
* @return array array processed by shortcode_atts, prepped for Tweet object
|
373 |
*/
|
374 |
+
public static function getShortcodeAttributes( $attributes )
|
375 |
{
|
376 |
// clean up attribute to shortcode option mappings before passing to filter
|
377 |
// apply the same filter as shortcode_atts
|
378 |
/** This filter is documented in wp-includes/shortcodes.php */
|
379 |
+
return apply_filters(
|
380 |
'shortcode_atts_' . self::SHORTCODE_TAG,
|
381 |
array_merge(
|
382 |
static::$SHORTCODE_DEFAULTS,
|
385 |
static::$SHORTCODE_DEFAULTS,
|
386 |
$attributes
|
387 |
);
|
388 |
+
}
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Handle shortcode macro
|
392 |
+
*
|
393 |
+
* @since 1.0.0
|
394 |
+
*
|
395 |
+
* @param array $attributes shortcode attributes
|
396 |
+
* @param string $content shortcode content. no effect
|
397 |
+
*
|
398 |
+
* @return string Tweet button HTML or empty string
|
399 |
+
*/
|
400 |
+
public static function shortcodeHandler( $attributes, $content = null )
|
401 |
+
{
|
402 |
+
$options = static::getShortcodeAttributes( $attributes );
|
403 |
|
404 |
// add options shared to post meta
|
405 |
$options = static::addPostMetaOptions( $options );
|
406 |
|
407 |
+
// add parameters based on per-post render context
|
408 |
if ( in_the_loop() ) {
|
409 |
$post = get_post();
|
410 |
|
435 |
unset( $via_username );
|
436 |
}
|
437 |
|
438 |
+
$button = \Twitter\Widgets\Buttons\Tweet::fromArray( $options );
|
439 |
if ( ! $button ) {
|
440 |
return '';
|
441 |
}
|
445 |
return '';
|
446 |
}
|
447 |
|
448 |
+
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
449 |
|
450 |
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
451 |
if ( $inline_js ) {
|
src/Twitter/WordPress/Shortcodes/EmbeddedTweet.php
DELETED
@@ -1,434 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
The MIT License (MIT)
|
4 |
-
|
5 |
-
Copyright (c) 2015 Twitter Inc.
|
6 |
-
|
7 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
-
of this software and associated documentation files (the "Software"), to deal
|
9 |
-
in the Software without restriction, including without limitation the rights
|
10 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
-
copies of the Software, and to permit persons to whom the Software is
|
12 |
-
furnished to do so, subject to the following conditions:
|
13 |
-
|
14 |
-
The above copyright notice and this permission notice shall be included in
|
15 |
-
all copies or substantial portions of the Software.
|
16 |
-
|
17 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
-
THE SOFTWARE.
|
24 |
-
*/
|
25 |
-
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Display a Tweet
|
30 |
-
*
|
31 |
-
* @since 1.0.0
|
32 |
-
*/
|
33 |
-
class EmbeddedTweet implements ShortcodeInterface, PublishOEmbedEndpoint
|
34 |
-
{
|
35 |
-
use OEmbedTrait;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Shortcode tag to be matched
|
39 |
-
*
|
40 |
-
* @since 1.0.0
|
41 |
-
*
|
42 |
-
* @type string
|
43 |
-
*/
|
44 |
-
const SHORTCODE_TAG = 'tweet';
|
45 |
-
|
46 |
-
/**
|
47 |
-
* oEmbed regex registered by WordPress Core
|
48 |
-
*
|
49 |
-
* @since 1.0.0
|
50 |
-
*
|
51 |
-
* @type string
|
52 |
-
*/
|
53 |
-
const OEMBED_CORE_REGEX = '#https?://(www\.)?twitter\.com/.+?/status(es)?/.*#i';
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Regex used to match a Tweet in text
|
57 |
-
*
|
58 |
-
* More specific than WordPress Core regex
|
59 |
-
*
|
60 |
-
* @since 1.0.0
|
61 |
-
*
|
62 |
-
* @type string
|
63 |
-
*/
|
64 |
-
const TWEET_URL_REGEX = '#^https?://(www\.)?twitter\.com/[a-z0-9_]{1,20}/status(es)?/([0-9]+)#i';
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Base URL used to reconstruct a Tweet URL
|
68 |
-
*
|
69 |
-
* @since 1.3.0
|
70 |
-
*
|
71 |
-
* @type string
|
72 |
-
*/
|
73 |
-
const BASE_URL = 'https://twitter.com/_/status/';
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Accepted values for the align parameter
|
77 |
-
*
|
78 |
-
* @since 1.0.0
|
79 |
-
*
|
80 |
-
* @type array
|
81 |
-
*/
|
82 |
-
public static $ALIGN_OPTIONS = array( 'left' => true, 'center' => true, 'right' => true );
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Accepted shortcode attributes and their default values
|
86 |
-
*
|
87 |
-
* @since 1.0.0
|
88 |
-
*
|
89 |
-
* @type array
|
90 |
-
*/
|
91 |
-
public static $SHORTCODE_DEFAULTS = array( 'id' => '', 'conversation' => true, 'cards' => true, 'align' => '' );
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Attach handlers for embedded Tweets
|
95 |
-
*
|
96 |
-
* @since 1.0.0
|
97 |
-
*
|
98 |
-
* @return void
|
99 |
-
*/
|
100 |
-
public static function init()
|
101 |
-
{
|
102 |
-
$classname = get_called_class();
|
103 |
-
|
104 |
-
// register our shortcode and its handler
|
105 |
-
add_shortcode( self::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
106 |
-
|
107 |
-
// Shortcode UI, if supported
|
108 |
-
add_action(
|
109 |
-
'register_shortcode_ui',
|
110 |
-
array( $classname, 'shortcodeUI' ),
|
111 |
-
5,
|
112 |
-
0
|
113 |
-
);
|
114 |
-
|
115 |
-
if ( ! is_admin() ) {
|
116 |
-
// unhook the WordPress Core oEmbed handler
|
117 |
-
wp_oembed_remove_provider( static::OEMBED_CORE_REGEX );
|
118 |
-
// pass a Tweet detail URL through the Tweet shortcode handler
|
119 |
-
wp_embed_register_handler(
|
120 |
-
self::SHORTCODE_TAG,
|
121 |
-
static::TWEET_URL_REGEX,
|
122 |
-
array( $classname, 'linkHandler' ),
|
123 |
-
1
|
124 |
-
);
|
125 |
-
}
|
126 |
-
}
|
127 |
-
|
128 |
-
/**
|
129 |
-
* Describe shortcode for Shortcake UI
|
130 |
-
*
|
131 |
-
* @since 1.1.0
|
132 |
-
*
|
133 |
-
* @link https://github.com/fusioneng/Shortcake Shortcake UI
|
134 |
-
*
|
135 |
-
* @return void
|
136 |
-
*/
|
137 |
-
public static function shortcodeUI()
|
138 |
-
{
|
139 |
-
// Shortcake required
|
140 |
-
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
141 |
-
return;
|
142 |
-
}
|
143 |
-
|
144 |
-
// id only
|
145 |
-
// avoids an unchecked Shortcake input checkbox requiring a shortcode output
|
146 |
-
shortcode_ui_register_for_shortcode(
|
147 |
-
self::SHORTCODE_TAG,
|
148 |
-
array(
|
149 |
-
'label' => esc_html( __( 'Embedded Tweet', 'twitter' ) ),
|
150 |
-
'listItemImage' => 'dashicons-twitter',
|
151 |
-
'attrs' => array(
|
152 |
-
array(
|
153 |
-
'attr' => 'id',
|
154 |
-
'label' => 'ID',
|
155 |
-
'type' => 'text',
|
156 |
-
'meta' => array(
|
157 |
-
'required' => true,
|
158 |
-
'pattern' => '[0-9]+',
|
159 |
-
'placeholder' => '560070183650213889',
|
160 |
-
),
|
161 |
-
),
|
162 |
-
),
|
163 |
-
)
|
164 |
-
);
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Handle a URL matched by an embed handler
|
169 |
-
*
|
170 |
-
* @since 1.0.0
|
171 |
-
*
|
172 |
-
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
173 |
-
* @param array $attr Embed attributes. Not used.
|
174 |
-
* @param string $url The original URL that was matched by the regex. Not used.
|
175 |
-
* @param array $rawattr The original unmodified attributes. Not used.
|
176 |
-
*
|
177 |
-
* @return string HTML markup for the Tweet or an empty string if requirements not met
|
178 |
-
*/
|
179 |
-
public static function linkHandler( $matches, $attr, $url, $rawattr )
|
180 |
-
{
|
181 |
-
if ( ! ( is_array( $matches ) && isset( $matches[3] ) && $matches[3] ) ) {
|
182 |
-
return '';
|
183 |
-
}
|
184 |
-
|
185 |
-
return static::shortcodeHandler( array( 'id' => $matches[3] ) );
|
186 |
-
}
|
187 |
-
|
188 |
-
/**
|
189 |
-
* Convert a Tweet ID in ID or URL form into a trimmed ID
|
190 |
-
*
|
191 |
-
* @since 1.0.0
|
192 |
-
*
|
193 |
-
* @param string $tweet_id Tweet identifier
|
194 |
-
*
|
195 |
-
* @return string $tweet_id Tweet identifier or empty string if minimum requirements not met
|
196 |
-
*/
|
197 |
-
public static function sanitizeTweetID( $tweet_id )
|
198 |
-
{
|
199 |
-
if ( ! is_string( $tweet_id ) ) {
|
200 |
-
return '';
|
201 |
-
}
|
202 |
-
|
203 |
-
$tweet_id = trim( $tweet_id );
|
204 |
-
if ( ! $tweet_id ) {
|
205 |
-
return '';
|
206 |
-
}
|
207 |
-
$tweet_id = trim( rtrim( trim( $tweet_id ), '/' ) );
|
208 |
-
if ( ! $tweet_id ) {
|
209 |
-
return '';
|
210 |
-
}
|
211 |
-
|
212 |
-
$last_slash = strrpos( $tweet_id, '/' );
|
213 |
-
if ( false !== $last_slash ) {
|
214 |
-
$tweet_id = substr( $tweet_id, $last_slash + 1 );
|
215 |
-
}
|
216 |
-
|
217 |
-
return $tweet_id;
|
218 |
-
}
|
219 |
-
|
220 |
-
/**
|
221 |
-
* Convert shortcode parameters, attributes, and defaults into a clean set of Tweet parameters
|
222 |
-
*
|
223 |
-
* @since 1.0.0
|
224 |
-
*
|
225 |
-
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
226 |
-
* @type string|int attribute name or positional int
|
227 |
-
* @type mixed shortcode value
|
228 |
-
* }
|
229 |
-
*
|
230 |
-
* @return array cleaned up options ready for comparison {
|
231 |
-
* @type string option name
|
232 |
-
* @type string|bool option value
|
233 |
-
* }
|
234 |
-
*/
|
235 |
-
public static function sanitizeShortcodeParameters( $attributes = array() )
|
236 |
-
{
|
237 |
-
if ( ! is_array( $attributes ) ) {
|
238 |
-
return array();
|
239 |
-
}
|
240 |
-
|
241 |
-
$options = array();
|
242 |
-
|
243 |
-
if ( isset( $attributes['id'] ) ) {
|
244 |
-
$tweet_id = static::sanitizeTweetID( (string) $attributes['id'] );
|
245 |
-
if ( $tweet_id ) {
|
246 |
-
$options['id'] = $tweet_id;
|
247 |
-
}
|
248 |
-
unset( $tweet_id );
|
249 |
-
} else if ( isset( $attributes[0] ) ) {
|
250 |
-
// compatibility with WordPress.com positional shortcode
|
251 |
-
$tweet_id = static::sanitizeTweetID( (string) $attributes[0] );
|
252 |
-
if ( $tweet_id ) {
|
253 |
-
$options['id'] = $tweet_id;
|
254 |
-
}
|
255 |
-
unset( $tweet_id );
|
256 |
-
}
|
257 |
-
|
258 |
-
foreach ( array( 'cards' => 'hide_media', 'conversation' => 'hide_thread' ) as $falsey_option => $alternate_naming ) {
|
259 |
-
// check for falsey values passed to shortcode
|
260 |
-
if ( isset( $attributes[ $falsey_option ] ) ) {
|
261 |
-
if ( false === $attributes[ $falsey_option ] || '0' == $attributes[ $falsey_option ] || ( is_string( $attributes[ $falsey_option ] ) && in_array( strtolower( $attributes[ $falsey_option ] ), array( 'false', 'no', 'off' ) ) ) ) {
|
262 |
-
$options[ $falsey_option ] = false;
|
263 |
-
}
|
264 |
-
} else if ( isset( $attributes[ $alternate_naming ] ) ) {
|
265 |
-
// test for an oEmbed-style parameter provided in the shortcode if the equivalent parameter was not defined
|
266 |
-
if ( true === $attributes[ $alternate_naming ] || '1' == $attributes[ $alternate_naming ] || ( is_string( $attributes[ $alternate_naming ] ) && in_array( strtolower( $attributes[ $alternate_naming ] ), array( 'true', 'yes', 'on' ) ) ) ) {
|
267 |
-
// test alternate attribute used by other shortcodes
|
268 |
-
$options[ $falsey_option ] = false;
|
269 |
-
}
|
270 |
-
}
|
271 |
-
}
|
272 |
-
|
273 |
-
if ( isset( $attributes['align'] ) && $attributes['align'] ) {
|
274 |
-
$attributes['align'] = trim( strtolower( $attributes['align'] ) );
|
275 |
-
if ( array_key_exists( $attributes['align'], static::$ALIGN_OPTIONS ) ) {
|
276 |
-
$options['align'] = $attributes['align'];
|
277 |
-
}
|
278 |
-
}
|
279 |
-
|
280 |
-
return $options;
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* Handle shortcode macro
|
285 |
-
*
|
286 |
-
* @since 1.0.0
|
287 |
-
*
|
288 |
-
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
289 |
-
* @type string|int attribute name or positional int
|
290 |
-
* @type mixed shortcode value
|
291 |
-
* }
|
292 |
-
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
293 |
-
*
|
294 |
-
* @return string HTML markup. empty string if parameter requirement not met or no Tweet info found
|
295 |
-
*/
|
296 |
-
public static function shortcodeHandler( $attributes, $content = '' )
|
297 |
-
{
|
298 |
-
// clean up attribute to shortcode option mappings before passing to filter
|
299 |
-
// apply the same filter as shortcode_atts
|
300 |
-
/** This filter is documented in wp-includes/shortcodes.php */
|
301 |
-
$options = apply_filters(
|
302 |
-
'shortcode_atts_' . self::SHORTCODE_TAG,
|
303 |
-
array_merge(
|
304 |
-
static::$SHORTCODE_DEFAULTS,
|
305 |
-
static::sanitizeShortcodeParameters( (array) $attributes )
|
306 |
-
),
|
307 |
-
static::$SHORTCODE_DEFAULTS,
|
308 |
-
$attributes
|
309 |
-
);
|
310 |
-
|
311 |
-
if ( ! $options['id'] ) {
|
312 |
-
return '';
|
313 |
-
}
|
314 |
-
$tweet_id = $options['id'];
|
315 |
-
unset( $options['id'] );
|
316 |
-
|
317 |
-
$oembed_params = static::shortcodeParamsToOEmbedParams( $tweet_id, $options );
|
318 |
-
if ( empty( $oembed_params ) ) {
|
319 |
-
return '';
|
320 |
-
}
|
321 |
-
|
322 |
-
// fetch HTML markup from Twitter oEmbed endpoint for the given parameters
|
323 |
-
$html = trim( static::getOEmbedMarkup( $oembed_params ) );
|
324 |
-
if ( ! $html ) {
|
325 |
-
return '';
|
326 |
-
}
|
327 |
-
|
328 |
-
$html = '<div class="twitter-tweet">' . $html . '</div>';
|
329 |
-
|
330 |
-
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
331 |
-
if ( $inline_js ) {
|
332 |
-
return $html . $inline_js;
|
333 |
-
}
|
334 |
-
|
335 |
-
return $html;
|
336 |
-
}
|
337 |
-
|
338 |
-
/**
|
339 |
-
* Convert shortcode parameters into query parameters supported by the Twitter oEmbed endpoint
|
340 |
-
*
|
341 |
-
* @since 1.0.0
|
342 |
-
*
|
343 |
-
* @param string $tweet_id Tweet identifier
|
344 |
-
* @param array $shortcode_options customizations specified in the shortcode
|
345 |
-
*
|
346 |
-
* @return array associative array of query parameters ready for http_build_query {
|
347 |
-
* @type string query parameter name
|
348 |
-
* @type string|bool query parameter value
|
349 |
-
* }
|
350 |
-
*/
|
351 |
-
public static function shortcodeParamsToOEmbedParams( $tweet_id, $shortcode_options = array() )
|
352 |
-
{
|
353 |
-
$query_parameters = static::getBaseOEmbedParams( $tweet_id );
|
354 |
-
if ( empty( $query_parameters ) ) {
|
355 |
-
return array();
|
356 |
-
}
|
357 |
-
|
358 |
-
// test for valid align value
|
359 |
-
if ( isset( $shortcode_options['align'] ) && $shortcode_options['align'] && array_key_exists( $shortcode_options['align'], static::$ALIGN_OPTIONS ) ) {
|
360 |
-
$query_parameters['align'] = $shortcode_options['align'];
|
361 |
-
}
|
362 |
-
|
363 |
-
// oembed parameters are the opposite of widget parameters
|
364 |
-
// hide_* in oEmbed API
|
365 |
-
foreach ( array( 'cards' => 'hide_media', 'conversation' => 'hide_thread' ) as $bool_option => $oembed_parameter ) {
|
366 |
-
if ( isset( $shortcode_options[ $bool_option ] ) && false === $shortcode_options[ $bool_option ] ) {
|
367 |
-
$query_parameters[ $oembed_parameter ] = true;
|
368 |
-
}
|
369 |
-
}
|
370 |
-
|
371 |
-
return $query_parameters;
|
372 |
-
}
|
373 |
-
|
374 |
-
/**
|
375 |
-
* Generate a unique string representing oEmbed result customizations set by shortcode parameters
|
376 |
-
*
|
377 |
-
* @since 1.0.0
|
378 |
-
*
|
379 |
-
* @param array $query_parameters associative array of query parameters sent to the oEmbed endpoint {
|
380 |
-
* @type string query parameter name
|
381 |
-
* @type string|bool query parameter value
|
382 |
-
* }
|
383 |
-
*
|
384 |
-
* @return string cache key component
|
385 |
-
*/
|
386 |
-
public static function getOEmbedCacheKeyCustomParameters( array $query_parameters )
|
387 |
-
{
|
388 |
-
$customizations = '';
|
389 |
-
|
390 |
-
if ( isset( $query_parameters['hide_media'] ) && $query_parameters['hide_media'] ) {
|
391 |
-
$customizations .= 'm';
|
392 |
-
}
|
393 |
-
if ( isset( $query_parameters['hide_thread'] ) && $query_parameters['hide_thread'] ) {
|
394 |
-
$customizations .= 't';
|
395 |
-
}
|
396 |
-
// left, right, center
|
397 |
-
if ( isset( $query_parameters['align'] ) && $query_parameters['align'] && array_key_exists( $query_parameters['align'], static::$ALIGN_OPTIONS ) ) {
|
398 |
-
$customizations .= substr( $query_parameters['align'], 0, 1 );
|
399 |
-
}
|
400 |
-
|
401 |
-
return $customizations;
|
402 |
-
}
|
403 |
-
|
404 |
-
/**
|
405 |
-
* Construct a cache key for the oEmbed response. Account for query parameters needing to bust cache
|
406 |
-
*
|
407 |
-
* @since 1.0.0
|
408 |
-
*
|
409 |
-
* @link https://dev.twitter.com/rest/reference/get/statuses/oembed oEmbed doc
|
410 |
-
* @param array $query_parameters oEmbed API query parameters
|
411 |
-
*
|
412 |
-
* @return string cache key
|
413 |
-
*/
|
414 |
-
public static function oEmbedCacheKey( array $query_parameters )
|
415 |
-
{
|
416 |
-
if ( ! ( isset( $query_parameters['id'] ) && $query_parameters['id'] ) ) {
|
417 |
-
return '';
|
418 |
-
}
|
419 |
-
|
420 |
-
$key_pieces = array( self::SHORTCODE_TAG, $query_parameters['id'] );
|
421 |
-
|
422 |
-
// separate cache for each explicitly-defined display language
|
423 |
-
if ( isset( $query_parameters['lang'] ) && $query_parameters['lang'] ) {
|
424 |
-
$key_pieces[] = $query_parameters['lang'];
|
425 |
-
}
|
426 |
-
|
427 |
-
$customizations = static::getOEmbedCacheKeyCustomParameters( $query_parameters );
|
428 |
-
if ( $customizations ) {
|
429 |
-
$key_pieces[] = $customizations;
|
430 |
-
}
|
431 |
-
|
432 |
-
return implode( '_', $key_pieces );
|
433 |
-
}
|
434 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/Twitter/WordPress/Shortcodes/{Moment.php → Embeds/Moment.php}
RENAMED
@@ -23,14 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
|
28 |
/**
|
29 |
* Display a Moment
|
30 |
*
|
31 |
* @since 1.2.0
|
32 |
*/
|
33 |
-
class Moment extends
|
34 |
{
|
35 |
|
36 |
/**
|
@@ -43,7 +43,7 @@ class Moment extends TweetGrid
|
|
43 |
const SHORTCODE_TAG = 'twitter_moment';
|
44 |
|
45 |
/**
|
46 |
-
* oEmbed regex registered by WordPress Core
|
47 |
*
|
48 |
* @since 1.5.0
|
49 |
*
|
@@ -89,4 +89,33 @@ class Moment extends TweetGrid
|
|
89 |
{
|
90 |
return __( 'Twitter Moment', 'twitter' );
|
91 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
}
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds;
|
27 |
|
28 |
/**
|
29 |
* Display a Moment
|
30 |
*
|
31 |
* @since 1.2.0
|
32 |
*/
|
33 |
+
class Moment extends Timeline\CollectionGrid
|
34 |
{
|
35 |
|
36 |
/**
|
43 |
const SHORTCODE_TAG = 'twitter_moment';
|
44 |
|
45 |
/**
|
46 |
+
* The oEmbed regex registered by WordPress Core
|
47 |
*
|
48 |
* @since 1.5.0
|
49 |
*
|
89 |
{
|
90 |
return __( 'Twitter Moment', 'twitter' );
|
91 |
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Handle shortcode macro
|
95 |
+
*
|
96 |
+
* @since 2.0.0
|
97 |
+
*
|
98 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
99 |
+
* @type string|int attribute name or positional int
|
100 |
+
* @type mixed shortcode value
|
101 |
+
* }
|
102 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
103 |
+
*
|
104 |
+
* @return string HTML markup. empty string if parameter requirement not met or no collection info found
|
105 |
+
*/
|
106 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
107 |
+
{
|
108 |
+
$options = static::getShortcodeAttributes( $attributes );
|
109 |
+
// Moment ID required
|
110 |
+
if ( ! $options['id'] ) {
|
111 |
+
return '';
|
112 |
+
}
|
113 |
+
|
114 |
+
$timeline = \Twitter\Widgets\Embeds\Moment::fromArray( $options );
|
115 |
+
if ( ! ( $timeline && $timeline->getID() ) ) {
|
116 |
+
return '';
|
117 |
+
}
|
118 |
+
|
119 |
+
return static::getHTMLForTimeline( $timeline );
|
120 |
+
}
|
121 |
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Timeline.php
ADDED
@@ -0,0 +1,347 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Common references for a Twitter timeline
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
trait Timeline
|
34 |
+
{
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Accepted timeline shortcode attributes and their default values
|
38 |
+
*
|
39 |
+
* @since 2.0.0
|
40 |
+
*
|
41 |
+
* @type array
|
42 |
+
*/
|
43 |
+
public static $TIMELINE_SHORTCODE_DEFAULTS = array(
|
44 |
+
'width' => null,
|
45 |
+
'height' => null,
|
46 |
+
'limit' => null,
|
47 |
+
'chrome' => array(),
|
48 |
+
'aria_polite' => 'polite',
|
49 |
+
'lang' => null,
|
50 |
+
'theme' => 'light',
|
51 |
+
'link_color' => null,
|
52 |
+
'border_color' => null,
|
53 |
+
);
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Shortcode attributes to be converted from underscores to dashes before object initialization
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type array
|
61 |
+
*/
|
62 |
+
public static $OPTIONS_KEYS_UNDERSCORE_TO_DASHES = array(
|
63 |
+
'aria_polite' => 'aria-polite',
|
64 |
+
'link_color' => 'link-color',
|
65 |
+
'border_color' => 'border-color',
|
66 |
+
);
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Shortcode attributes expected to be a positive integer value
|
70 |
+
*
|
71 |
+
* @since 2.0.0
|
72 |
+
*
|
73 |
+
* @type array
|
74 |
+
*/
|
75 |
+
public static $OPTIONS_KEYS_INT_VALUES = array(
|
76 |
+
'width',
|
77 |
+
'height',
|
78 |
+
'limit',
|
79 |
+
);
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Attach handlers for shortcode, oEmbed URL, shortcode UI
|
83 |
+
*
|
84 |
+
* @since 2.0.0
|
85 |
+
*
|
86 |
+
* @return void
|
87 |
+
*/
|
88 |
+
public static function init()
|
89 |
+
{
|
90 |
+
$classname = get_called_class();
|
91 |
+
|
92 |
+
// register our shortcode and its handler
|
93 |
+
add_shortcode( static::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
94 |
+
|
95 |
+
// Shortcode UI, if supported
|
96 |
+
add_action(
|
97 |
+
'register_shortcode_ui',
|
98 |
+
array( $classname, 'shortcodeUI' ),
|
99 |
+
5,
|
100 |
+
0
|
101 |
+
);
|
102 |
+
|
103 |
+
if ( ! is_admin() ) {
|
104 |
+
// unhook the WordPress Core oEmbed handler
|
105 |
+
wp_oembed_remove_provider( static::OEMBED_CORE_REGEX );
|
106 |
+
|
107 |
+
// convert a URL into the shortcode equivalent
|
108 |
+
wp_embed_register_handler(
|
109 |
+
static::SHORTCODE_TAG,
|
110 |
+
static::URL_REGEX,
|
111 |
+
array( $classname, 'linkHandler' ),
|
112 |
+
1
|
113 |
+
);
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Shortcode allowed attributes and default values for embedded timeline
|
119 |
+
*
|
120 |
+
* @since 2.0.0
|
121 |
+
*
|
122 |
+
* @return array shortcode allowed attributes and default values
|
123 |
+
*/
|
124 |
+
public static function getShortcodeDefaults()
|
125 |
+
{
|
126 |
+
return array_merge( static::$TIMELINE_SHORTCODE_DEFAULTS, static::$SHORTCODE_DEFAULTS );
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Process shortcode attributes received from the shortcode API
|
131 |
+
*
|
132 |
+
* @since 2.0.0
|
133 |
+
*
|
134 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
135 |
+
*
|
136 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
137 |
+
*
|
138 |
+
* @return array array processed by shortcode_atts, prepped for timeline objects
|
139 |
+
*/
|
140 |
+
public static function getShortcodeAttributes( $attributes )
|
141 |
+
{
|
142 |
+
$options = shortcode_atts(
|
143 |
+
static::getShortcodeDefaults(),
|
144 |
+
$attributes,
|
145 |
+
static::SHORTCODE_TAG
|
146 |
+
);
|
147 |
+
|
148 |
+
if ( ! is_array( $options ) || empty( $options ) ) {
|
149 |
+
return array();
|
150 |
+
}
|
151 |
+
|
152 |
+
return static::shortcodeAttributesToTimelineKeys( $options );
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Convert shortcode attributes provided as underscores to the dashed values expected by the object builder
|
157 |
+
*
|
158 |
+
* @since 2.0.0
|
159 |
+
*
|
160 |
+
* @param array $options shortcode options array {
|
161 |
+
* @type string shortcode attribute
|
162 |
+
* @type mixed shortcode attribute value
|
163 |
+
* }
|
164 |
+
*
|
165 |
+
* @return array shortcode attributes converted to keys and value types expected by timeline objects
|
166 |
+
*/
|
167 |
+
public static function shortcodeAttributesToTimelineKeys( $options )
|
168 |
+
{
|
169 |
+
if ( ! is_array( $options ) ) {
|
170 |
+
return array();
|
171 |
+
}
|
172 |
+
|
173 |
+
// expected int values
|
174 |
+
$options = \Twitter\WordPress\Shortcodes\Helpers\Attributes::positiveIntegerOption(
|
175 |
+
$options,
|
176 |
+
static::$OPTIONS_KEYS_INT_VALUES
|
177 |
+
);
|
178 |
+
|
179 |
+
foreach ( static::$OPTIONS_KEYS_UNDERSCORE_TO_DASHES as $underscore => $dashes ) {
|
180 |
+
if ( ! isset( $options[ $underscore ] ) ) {
|
181 |
+
continue;
|
182 |
+
}
|
183 |
+
$options[ $dashes ] = $options[ $underscore ];
|
184 |
+
unset( $options[ $underscore ] );
|
185 |
+
}
|
186 |
+
|
187 |
+
// set multiple chrome tokens through CSV
|
188 |
+
if ( isset( $options['chrome'] ) && ! is_array( $options['chrome'] ) ) {
|
189 |
+
$options['chrome'] = explode( ',', $options['chrome'] );
|
190 |
+
}
|
191 |
+
|
192 |
+
return $options;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Generate a unique string representing oEmbed result customizations
|
197 |
+
*
|
198 |
+
* @since 2.0.0
|
199 |
+
*
|
200 |
+
* @param array $query_parameters associative array of query parameters sent to the oEmbed endpoint {
|
201 |
+
* @type string query parameter name
|
202 |
+
* @type string|bool query parameter value
|
203 |
+
* }
|
204 |
+
*
|
205 |
+
* @return string cache key component
|
206 |
+
*/
|
207 |
+
public static function getOEmbedCacheKeyCustomParameters( array $query_parameters )
|
208 |
+
{
|
209 |
+
if ( empty( $query_parameters ) ) {
|
210 |
+
return '';
|
211 |
+
}
|
212 |
+
|
213 |
+
$key_pieces = array();
|
214 |
+
|
215 |
+
if ( isset( $query_parameters['maxwidth'] ) ) {
|
216 |
+
$key_pieces[] = 'w' . $query_parameters['maxwidth'];
|
217 |
+
}
|
218 |
+
if ( isset( $query_parameters['limit'] ) ) {
|
219 |
+
$key_pieces[] = 'l' . $query_parameters['limit'];
|
220 |
+
} else if ( isset( $query_parameters['maxheight'] ) ) {
|
221 |
+
$key_pieces[] = 'h' . $query_parameters['maxheight'];
|
222 |
+
}
|
223 |
+
|
224 |
+
if ( isset( $query_parameters['chrome'] ) && $query_parameters['chrome'] ) {
|
225 |
+
$chrome = explode( ' ', $query_parameters['chrome'] );
|
226 |
+
$chrome_piece = array();
|
227 |
+
$abbreviated_chrome_tokens = array(
|
228 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOHEADER => 'h',
|
229 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOFOOTER => 'f',
|
230 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOBORDERS => 'b',
|
231 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOSCROLLBAR => 's',
|
232 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_TRANSPARENT => 't',
|
233 |
+
);
|
234 |
+
foreach ( $chrome as $token ) {
|
235 |
+
if ( isset( $abbreviated_chrome_tokens[ $token ] ) ) {
|
236 |
+
$chrome_piece[ $abbreviated_chrome_tokens[ $token ] ] = true;
|
237 |
+
}
|
238 |
+
}
|
239 |
+
if ( ! empty( $chrome_piece ) ) {
|
240 |
+
$key_pieces[] = implode( '', array_keys( $chrome_piece ) );
|
241 |
+
}
|
242 |
+
unset( $chrome_piece );
|
243 |
+
unset( $chrome );
|
244 |
+
}
|
245 |
+
|
246 |
+
// ARIA live region override: assertive
|
247 |
+
if ( isset( $query_parameters['aria_polite'] ) ) {
|
248 |
+
$key_pieces[] = 'a';
|
249 |
+
}
|
250 |
+
|
251 |
+
// should only be set for dark theme
|
252 |
+
if ( isset( $query_parameters['theme'] ) ) {
|
253 |
+
$key_pieces[] = 'd';
|
254 |
+
}
|
255 |
+
|
256 |
+
$color_parameters = array(
|
257 |
+
'link_color' => 'l',
|
258 |
+
'border_color' => 'b',
|
259 |
+
);
|
260 |
+
foreach ( $color_parameters as $query_parameter => $cache_abbreviation ) {
|
261 |
+
if ( isset( $query_parameters[ $query_parameter ] ) ) {
|
262 |
+
$key_pieces[] = $cache_abbreviation . ltrim( $query_parameters[ $query_parameter ], '#' );
|
263 |
+
}
|
264 |
+
}
|
265 |
+
|
266 |
+
return implode( '_', $key_pieces );
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Construct a cache key for the oEmbed response. Account for query parameters needing to bust cache. 172 characters or fewer
|
271 |
+
*
|
272 |
+
* @since 2.0.0
|
273 |
+
*
|
274 |
+
* @link https://dev.twitter.com/web/embedded-timelines/oembed embedded timelines oEmbed
|
275 |
+
*
|
276 |
+
* @param string $id datasource ID
|
277 |
+
* @param array $query_parameters oEmbed API query parameters
|
278 |
+
*
|
279 |
+
* @return string cache key
|
280 |
+
*/
|
281 |
+
public static function getOEmbedCacheKey( $id, array $query_parameters )
|
282 |
+
{
|
283 |
+
if ( ! ( is_string( $id ) && $id ) ) {
|
284 |
+
return '';
|
285 |
+
}
|
286 |
+
|
287 |
+
$key_pieces = array( static::SHORTCODE_TAG, $id );
|
288 |
+
|
289 |
+
if ( isset( $query_parameters['lang'] ) ) {
|
290 |
+
$key_pieces[] = $query_parameters['lang'];
|
291 |
+
}
|
292 |
+
|
293 |
+
if ( isset( $query_parameters['dnt'] ) ) {
|
294 |
+
$key_pieces[] = 'p';
|
295 |
+
}
|
296 |
+
|
297 |
+
$customizations = static::getOEmbedCacheKeyCustomParameters( $query_parameters );
|
298 |
+
if ( $customizations ) {
|
299 |
+
$key_pieces[] = $customizations;
|
300 |
+
}
|
301 |
+
|
302 |
+
return implode( '_', $key_pieces );
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Get HTML markup for a timeline
|
307 |
+
*
|
308 |
+
* @since 2.0.0
|
309 |
+
*
|
310 |
+
* @param \Twitter\Widgets\Embeds\Timeline $timeline timeline object
|
311 |
+
*
|
312 |
+
* @return string HTML markup or empty string if minimum requirements not met
|
313 |
+
*/
|
314 |
+
public static function getHTMLForTimeline( $timeline )
|
315 |
+
{
|
316 |
+
// verify passed parameter
|
317 |
+
if ( ! is_a( $timeline, '\Twitter\Widgets\Embeds\Timeline' ) ) {
|
318 |
+
return '';
|
319 |
+
}
|
320 |
+
|
321 |
+
$oembed_params = $timeline->toOEmbedParameterArray();
|
322 |
+
if ( ! isset( $oembed_params['url'] ) ) {
|
323 |
+
return '';
|
324 |
+
}
|
325 |
+
$oembed_params = array_merge( static::getBaseOEmbedParams(), $oembed_params );
|
326 |
+
|
327 |
+
$cache_key = static::getOEmbedCacheKey( static::getDataSourceIdentifier( $timeline ), $oembed_params );
|
328 |
+
if ( ! $cache_key ) {
|
329 |
+
return '';
|
330 |
+
}
|
331 |
+
|
332 |
+
// fetch HTML markup from Twitter oEmbed endpoint for the given parameters
|
333 |
+
$html = trim( static::getOEmbedMarkup( $oembed_params, $cache_key ) );
|
334 |
+
if ( ! $html ) {
|
335 |
+
return '';
|
336 |
+
}
|
337 |
+
|
338 |
+
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
339 |
+
|
340 |
+
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
341 |
+
if ( $inline_js ) {
|
342 |
+
return $html . $inline_js;
|
343 |
+
}
|
344 |
+
|
345 |
+
return $html;
|
346 |
+
}
|
347 |
+
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Timeline/Collection.php
ADDED
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a collection of Tweets
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Collection implements \Twitter\WordPress\Shortcodes\ShortcodeInterface, \Twitter\WordPress\Shortcodes\PublishOEmbedEndpoint
|
34 |
+
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\OEmbedTrait, \Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'twitter_collection';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The oEmbed regex registered by WordPress Core
|
48 |
+
*
|
49 |
+
* @since 1.5.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const OEMBED_CORE_REGEX = '#https?://(www\.)?twitter\.com/\w{1,15}/timelines/.*#i';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* HTML class to be used in div wrapper
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type string
|
61 |
+
*/
|
62 |
+
const HTML_CLASS = 'twitter-collection';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Regex used to match a Collection in text
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @type string
|
70 |
+
*/
|
71 |
+
const URL_REGEX = '#^https://twitter\.com/[a-z0-9_]{1,20}/timelines/([0-9]+)#i';
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Base URL used to reconstruct a Collection URL
|
75 |
+
*
|
76 |
+
* @since 2.0.0
|
77 |
+
*
|
78 |
+
* @type string
|
79 |
+
*/
|
80 |
+
const BASE_URL = 'https://twitter.com/_/timelines/';
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Accepted shortcode attributes and their default values
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @type array
|
88 |
+
*/
|
89 |
+
public static $SHORTCODE_DEFAULTS = array( 'id' => '', 'template' => '' );
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Reference the feature by name
|
93 |
+
*
|
94 |
+
* @since 2.0.0
|
95 |
+
*
|
96 |
+
* @return string translated feature name
|
97 |
+
*/
|
98 |
+
public static function featureName()
|
99 |
+
{
|
100 |
+
return _x( 'Twitter Collection', 'Tweets organized into a collection', 'twitter' );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Describe shortcode for Shortcake UI
|
105 |
+
*
|
106 |
+
* @since 2.0.0
|
107 |
+
*
|
108 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcake UI
|
109 |
+
*
|
110 |
+
* @return void
|
111 |
+
*/
|
112 |
+
public static function shortcodeUI()
|
113 |
+
{
|
114 |
+
// Shortcake required
|
115 |
+
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
116 |
+
return;
|
117 |
+
}
|
118 |
+
|
119 |
+
shortcode_ui_register_for_shortcode(
|
120 |
+
static::SHORTCODE_TAG,
|
121 |
+
array(
|
122 |
+
'label' => esc_html( static::featureName() ),
|
123 |
+
'listItemImage' => 'dashicons-twitter',
|
124 |
+
'attrs' => array(
|
125 |
+
array(
|
126 |
+
'attr' => 'id',
|
127 |
+
'label' => 'ID',
|
128 |
+
'type' => 'text',
|
129 |
+
'meta' => array(
|
130 |
+
'required' => true,
|
131 |
+
'pattern' => '[0-9]+',
|
132 |
+
),
|
133 |
+
),
|
134 |
+
array(
|
135 |
+
'attr' => 'limit',
|
136 |
+
'label' => _x( 'Limit', 'Maximum number of items to include', 'twitter' ),
|
137 |
+
'type' => 'number',
|
138 |
+
'meta' => array(
|
139 |
+
'min' => 1,
|
140 |
+
'max' => 20,
|
141 |
+
'step' => 1,
|
142 |
+
),
|
143 |
+
),
|
144 |
+
),
|
145 |
+
)
|
146 |
+
);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Handle a URL matched by a embed handler
|
151 |
+
*
|
152 |
+
* @since 2.0.0
|
153 |
+
*
|
154 |
+
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
155 |
+
*
|
156 |
+
* @return string HTML markup for the Twitter Collection or an empty string if requirements not met
|
157 |
+
*/
|
158 |
+
public static function linkHandler( $matches )
|
159 |
+
{
|
160 |
+
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] ) ) {
|
161 |
+
return '';
|
162 |
+
}
|
163 |
+
|
164 |
+
return static::shortcodeHandler( array( 'id' => $matches[1] ) );
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Handle shortcode macro
|
169 |
+
*
|
170 |
+
* @since 2.0.0
|
171 |
+
*
|
172 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
173 |
+
* @type string|int attribute name or positional int
|
174 |
+
* @type mixed shortcode value
|
175 |
+
* }
|
176 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
177 |
+
*
|
178 |
+
* @return string HTML markup. empty string if parameter requirement not met or no collection info found
|
179 |
+
*/
|
180 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
181 |
+
{
|
182 |
+
// allow grid displays to be triggered from the main collection shortcode, handled by the compatibility layer of the grid shortcode
|
183 |
+
if ( isset( $attributes['template'] ) && \Twitter\Widgets\Embeds\Timeline\Collection::WIDGET_TYPE_GRID === $attributes['template'] ) {
|
184 |
+
return \Twitter\WordPress\Shortcodes\Embeds\Timeline\CollectionGrid::shortcodeHandler( $attributes, $content );
|
185 |
+
}
|
186 |
+
$options = static::getShortcodeAttributes( $attributes );
|
187 |
+
// collection ID required
|
188 |
+
if ( ! $options['id'] ) {
|
189 |
+
return '';
|
190 |
+
}
|
191 |
+
|
192 |
+
$timeline = \Twitter\Widgets\Embeds\Timeline\Collection::fromArray( $options );
|
193 |
+
if ( ! ( $timeline && $timeline->getID() ) ) {
|
194 |
+
return '';
|
195 |
+
}
|
196 |
+
|
197 |
+
return static::getHTMLForTimeline( $timeline );
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Get a unique identifier for the datasource to uniquely identify
|
202 |
+
*
|
203 |
+
* Used in oEmbed cache key to save a short, unique representation of the datasource
|
204 |
+
*
|
205 |
+
* @since 2.0.0
|
206 |
+
*
|
207 |
+
* @param \Twitter\Widgets\Embeds\Timeline $timeline timeline object
|
208 |
+
*
|
209 |
+
* @return string unique identifier or empty string if minimum requirements not met
|
210 |
+
*/
|
211 |
+
public static function getDataSourceIdentifier( $timeline )
|
212 |
+
{
|
213 |
+
// verify passed parameter
|
214 |
+
if ( ! ( is_a( $timeline, '\Twitter\Widgets\Embeds\Timeline' ) && method_exists( $timeline, 'getID' ) ) ) {
|
215 |
+
return '';
|
216 |
+
}
|
217 |
+
|
218 |
+
return $timeline->getID();
|
219 |
+
}
|
220 |
+
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Timeline/CollectionGrid.php
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a collection of Tweets in a grid template
|
30 |
+
*
|
31 |
+
* Maintains compatibility with the twitter_grid shortcode added in 1.3.0
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
class CollectionGrid extends \Twitter\WordPress\Shortcodes\Embeds\Timeline\Collection
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'twitter_grid';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* HTML class to be used in div wrapper
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const HTML_CLASS = 'twitter-collection-grid';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Accepted shortcode attributes and their default values
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type array
|
61 |
+
*/
|
62 |
+
public static $SHORTCODE_DEFAULTS = array( 'id' => '' );
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Collection shortcode defaults not supported in a grid template
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @type string[] shortcode defaults to remove if seen
|
70 |
+
*/
|
71 |
+
public static $UNSUPPORTED_SHORTCODE_DEFAULTS = array(
|
72 |
+
'height',
|
73 |
+
'aria_polite',
|
74 |
+
'theme',
|
75 |
+
'link_color',
|
76 |
+
'border_color',
|
77 |
+
);
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Reference the feature by name
|
81 |
+
*
|
82 |
+
* @since 2.0.0
|
83 |
+
*
|
84 |
+
* @return string translated feature name
|
85 |
+
*/
|
86 |
+
public static function featureName()
|
87 |
+
{
|
88 |
+
return _x( 'Twitter Collection Grid', 'Tweets organized into a collection displayed in a grid template', 'twitter' );
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Override the shortcode initialization and URL handler init with only shortcode logic
|
93 |
+
*
|
94 |
+
* @since 2.0.0
|
95 |
+
*
|
96 |
+
* @return void
|
97 |
+
*/
|
98 |
+
public static function init()
|
99 |
+
{
|
100 |
+
$classname = get_called_class();
|
101 |
+
|
102 |
+
// register our shortcode and its handler
|
103 |
+
add_shortcode( static::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
104 |
+
|
105 |
+
// Shortcode UI, if supported
|
106 |
+
add_action(
|
107 |
+
'register_shortcode_ui',
|
108 |
+
array( $classname, 'shortcodeUI' ),
|
109 |
+
5,
|
110 |
+
0
|
111 |
+
);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Shortcode allowed attributes and default values for grid template
|
116 |
+
*
|
117 |
+
* Remove attributes only applicable to standard timelines, allowing developers acting on the shortcode_atts_twitter_grid filter to have only valid parameters
|
118 |
+
*
|
119 |
+
* @since 2.0.0
|
120 |
+
*
|
121 |
+
* @return array shortcode allowed attributes and default values
|
122 |
+
*/
|
123 |
+
public static function getShortcodeDefaults()
|
124 |
+
{
|
125 |
+
$attributes = array_merge( static::$TIMELINE_SHORTCODE_DEFAULTS, static::$SHORTCODE_DEFAULTS );
|
126 |
+
|
127 |
+
foreach ( static::$UNSUPPORTED_SHORTCODE_DEFAULTS as $key ) {
|
128 |
+
unset( $attributes[ $key ] );
|
129 |
+
}
|
130 |
+
|
131 |
+
return $attributes;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Handle shortcode macro
|
136 |
+
*
|
137 |
+
* @since 2.0.0
|
138 |
+
*
|
139 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
140 |
+
* @type string|int attribute name or positional int
|
141 |
+
* @type mixed shortcode value
|
142 |
+
* }
|
143 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
144 |
+
*
|
145 |
+
* @return string HTML markup. empty string if parameter requirement not met or no collection info found
|
146 |
+
*/
|
147 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
148 |
+
{
|
149 |
+
$options = static::getShortcodeAttributes( $attributes );
|
150 |
+
// collection ID required
|
151 |
+
if ( ! $options['id'] ) {
|
152 |
+
return '';
|
153 |
+
}
|
154 |
+
$options['widget_type'] = \Twitter\Widgets\Embeds\Timeline\Collection::WIDGET_TYPE_GRID;
|
155 |
+
|
156 |
+
$timeline = \Twitter\Widgets\Embeds\Timeline\Collection::fromArray( $options );
|
157 |
+
if ( ! ( $timeline && $timeline->getID() ) ) {
|
158 |
+
return '';
|
159 |
+
}
|
160 |
+
|
161 |
+
return static::getHTMLForTimeline( $timeline );
|
162 |
+
}
|
163 |
+
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Timeline/Profile.php
ADDED
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display the latest Tweets from a Twitter account
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Profile implements \Twitter\WordPress\Shortcodes\ShortcodeInterface, \Twitter\WordPress\Shortcodes\PublishOEmbedEndpoint
|
34 |
+
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\OEmbedTrait, \Twitter\WordPress\Shortcodes\AuthorContext, \Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'twitter_profile';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The oEmbed regex registered by WordPress Core
|
48 |
+
*
|
49 |
+
* @since 1.5.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const OEMBED_CORE_REGEX = '#https?://(www\.)?twitter\.com/\w{1,15}$#i';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Regex used to match a Profile in text
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type string
|
61 |
+
*/
|
62 |
+
const URL_REGEX = '#^https://twitter\.com/([a-z0-9_]{1,20})$#i';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* HTML class to be used in div wrapper
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @type string
|
70 |
+
*/
|
71 |
+
const HTML_CLASS = 'twitter-timeline-profile';
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Base URL used to reconstruct a Profile URL
|
75 |
+
*
|
76 |
+
* @since 2.0.0
|
77 |
+
*
|
78 |
+
* @type string
|
79 |
+
*/
|
80 |
+
const BASE_URL = 'https://twitter.com/';
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Accepted shortcode attributes and their default values
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @type array
|
88 |
+
*/
|
89 |
+
public static $SHORTCODE_DEFAULTS = array( 'screen_name' => '' );
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Reference the feature by name
|
93 |
+
*
|
94 |
+
* @since 2.0.0
|
95 |
+
*
|
96 |
+
* @return string translated feature name
|
97 |
+
*/
|
98 |
+
public static function featureName()
|
99 |
+
{
|
100 |
+
return _x( 'Twitter Profile', 'The latest Tweets authored by a Twitter account', 'twitter' );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Describe shortcode for Shortcake UI
|
105 |
+
*
|
106 |
+
* @since 2.0.0
|
107 |
+
*
|
108 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcode UI
|
109 |
+
*
|
110 |
+
* @return void
|
111 |
+
*/
|
112 |
+
public static function shortcodeUI()
|
113 |
+
{
|
114 |
+
// Shortcake required
|
115 |
+
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
116 |
+
return;
|
117 |
+
}
|
118 |
+
|
119 |
+
shortcode_ui_register_for_shortcode(
|
120 |
+
static::SHORTCODE_TAG,
|
121 |
+
array(
|
122 |
+
'label' => esc_html( static::featureName() ),
|
123 |
+
'listItemImage' => 'dashicons-twitter',
|
124 |
+
'attrs' => array(
|
125 |
+
array(
|
126 |
+
'attr' => 'screen_name',
|
127 |
+
'label' => esc_html( __( 'Twitter @username', 'twitter' ) ),
|
128 |
+
'type' => 'text',
|
129 |
+
'meta' => array(
|
130 |
+
'placeholder' => 'WordPress',
|
131 |
+
'pattern' => '[A-Za-z0-9_]{1,20}',
|
132 |
+
),
|
133 |
+
),
|
134 |
+
),
|
135 |
+
)
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Handle a URL matched by a embed handler
|
141 |
+
*
|
142 |
+
* @since 2.0.0
|
143 |
+
*
|
144 |
+
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
145 |
+
* @param array $attr Embed attributes. Not used.
|
146 |
+
* @param string $url The original URL that was matched by the regex. Not used.
|
147 |
+
* @param array $rawattr The original unmodified attributes. Not used.
|
148 |
+
*
|
149 |
+
* @return string HTML markup for the profile timeline or an empty string if requirements not met
|
150 |
+
*/
|
151 |
+
public static function linkHandler( $matches, $attr, $url, $rawattr )
|
152 |
+
{
|
153 |
+
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] ) ) {
|
154 |
+
return '';
|
155 |
+
}
|
156 |
+
|
157 |
+
return static::shortcodeHandler( array( 'screen_name' => $matches[1] ) );
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Handle shortcode macro
|
162 |
+
*
|
163 |
+
* @since 2.0.0
|
164 |
+
*
|
165 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
166 |
+
* @type string|int attribute name or positional int
|
167 |
+
* @type mixed shortcode value
|
168 |
+
* }
|
169 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
170 |
+
*
|
171 |
+
* @return string HTML markup. empty string if parameter requirement not met or no profile info found
|
172 |
+
*/
|
173 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
174 |
+
{
|
175 |
+
$options = static::getShortcodeAttributes( $attributes );
|
176 |
+
|
177 |
+
$screen_name = '';
|
178 |
+
if ( isset( $options['screen_name'] ) ) {
|
179 |
+
$screen_name = $options['screen_name'];
|
180 |
+
unset( $options['screen_name'] );
|
181 |
+
}
|
182 |
+
if ( ! $screen_name ) {
|
183 |
+
// set screen name from rendering context
|
184 |
+
$screen_name = static::getScreenName();
|
185 |
+
// profile data source required
|
186 |
+
if ( ! $screen_name ) {
|
187 |
+
return '';
|
188 |
+
}
|
189 |
+
}
|
190 |
+
$options['screen_name'] = $screen_name;
|
191 |
+
|
192 |
+
$timeline = \Twitter\Widgets\Embeds\Timeline\Profile::fromArray( $options );
|
193 |
+
if ( ! ( $timeline && $timeline->getScreenName() ) ) {
|
194 |
+
return '';
|
195 |
+
}
|
196 |
+
|
197 |
+
return static::getHTMLForTimeline( $timeline );
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Get a unique identifier for the datasource to uniquely identify
|
202 |
+
*
|
203 |
+
* Used in oEmbed cache key to save a short, unique representation of the datasource
|
204 |
+
*
|
205 |
+
* @since 2.0.0
|
206 |
+
*
|
207 |
+
* @param \Twitter\Widgets\Embeds\Timeline $timeline timeline object
|
208 |
+
*
|
209 |
+
* @return string unique identifier or empty string if minimum requirements not met
|
210 |
+
*/
|
211 |
+
public static function getDataSourceIdentifier( $timeline )
|
212 |
+
{
|
213 |
+
// verify passed parameter
|
214 |
+
if ( ! is_a( $timeline, '\Twitter\Widgets\Embeds\Timeline' ) ) {
|
215 |
+
return '';
|
216 |
+
}
|
217 |
+
|
218 |
+
return $timeline->getScreenName();
|
219 |
+
}
|
220 |
+
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Timeline/Search.php
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2017 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display recent search results in a timeline
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Search implements \Twitter\WordPress\Shortcodes\ShortcodeInterface
|
34 |
+
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'twitter_search';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* HTML class to be used in div wrapper
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const HTML_CLASS = 'twitter-timeline-search';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Accepted shortcode attributes and their default values
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type array
|
61 |
+
*/
|
62 |
+
public static $SHORTCODE_DEFAULTS = array( 'widget_id' => '', 'terms' => '' );
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Reference the feature by name
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @return string translated feature name
|
70 |
+
*/
|
71 |
+
public static function featureName()
|
72 |
+
{
|
73 |
+
return _x( 'Twitter Search', 'Tweets matching a search result query', 'twitter' );
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Attach handlers for shortcode, shortcode UI
|
78 |
+
*
|
79 |
+
* @since 2.0.0
|
80 |
+
*
|
81 |
+
* @return void
|
82 |
+
*/
|
83 |
+
public static function init()
|
84 |
+
{
|
85 |
+
$classname = get_called_class();
|
86 |
+
|
87 |
+
// register our shortcode and its handler
|
88 |
+
add_shortcode( static::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
89 |
+
|
90 |
+
// Shortcode UI, if supported
|
91 |
+
add_action(
|
92 |
+
'register_shortcode_ui',
|
93 |
+
array( $classname, 'shortcodeUI' ),
|
94 |
+
5,
|
95 |
+
0
|
96 |
+
);
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Describe shortcode for Shortcake UI
|
101 |
+
*
|
102 |
+
* @since 2.0.0
|
103 |
+
*
|
104 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcode UI
|
105 |
+
*
|
106 |
+
* @return void
|
107 |
+
*/
|
108 |
+
public static function shortcodeUI()
|
109 |
+
{
|
110 |
+
// Shortcake required
|
111 |
+
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
112 |
+
return;
|
113 |
+
}
|
114 |
+
|
115 |
+
shortcode_ui_register_for_shortcode(
|
116 |
+
static::SHORTCODE_TAG,
|
117 |
+
array(
|
118 |
+
'label' => esc_html( static::featureName() ),
|
119 |
+
'listItemImage' => 'dashicons-twitter',
|
120 |
+
'attrs' => array(
|
121 |
+
array(
|
122 |
+
'attr' => 'widget_id',
|
123 |
+
'label' => esc_html( __( 'Widget ID', 'twitter' ) ),
|
124 |
+
'type' => 'text',
|
125 |
+
'meta' => array(
|
126 |
+
'pattern' => '[0-9]+',
|
127 |
+
),
|
128 |
+
),
|
129 |
+
),
|
130 |
+
)
|
131 |
+
);
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Handle shortcode macro
|
136 |
+
*
|
137 |
+
* @since 2.0.0
|
138 |
+
*
|
139 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
140 |
+
* @type string|int attribute name or positional int
|
141 |
+
* @type mixed shortcode value
|
142 |
+
* }
|
143 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
144 |
+
*
|
145 |
+
* @return string HTML markup. empty string if parameter requirement not met or no profile info found
|
146 |
+
*/
|
147 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
148 |
+
{
|
149 |
+
$options = static::getShortcodeAttributes( $attributes );
|
150 |
+
if ( isset( $options['widget_id'] ) ) {
|
151 |
+
$options['widget_id'] = trim( $options['widget_id'] );
|
152 |
+
} else {
|
153 |
+
return '';
|
154 |
+
}
|
155 |
+
|
156 |
+
$timeline = \Twitter\Widgets\Embeds\Timeline\Search::fromArray( $options );
|
157 |
+
if ( ! ( $timeline && $timeline->getWidgetID() ) ) {
|
158 |
+
return '';
|
159 |
+
}
|
160 |
+
|
161 |
+
return static::getHTMLForTimeline( $timeline );
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Get HTML markup for a timeline
|
166 |
+
*
|
167 |
+
* @since 2.0.0
|
168 |
+
*
|
169 |
+
* @param \Twitter\Widgets\Embeds\Timeline\Search $timeline timeline object
|
170 |
+
*
|
171 |
+
* @return string HTML markup or empty string if minimum requirements not met
|
172 |
+
*/
|
173 |
+
public static function getHTMLForTimeline( $timeline )
|
174 |
+
{
|
175 |
+
// verify passed parameter
|
176 |
+
if ( ! is_a( $timeline, '\Twitter\Widgets\Embeds\Timeline\Search' ) ) {
|
177 |
+
return '';
|
178 |
+
}
|
179 |
+
|
180 |
+
if ( $timeline->getSearchTerms() ) {
|
181 |
+
$link_text = _x( 'Tweets about %s', 'Tweets about a term or topic', 'twitter' );
|
182 |
+
} else {
|
183 |
+
$link_text = static::featureName();
|
184 |
+
}
|
185 |
+
|
186 |
+
$html = $timeline->toHTML( $link_text, '\Twitter\WordPress\Helpers\HTMLBuilder' );
|
187 |
+
if ( ! $html ) {
|
188 |
+
return '';
|
189 |
+
}
|
190 |
+
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
191 |
+
|
192 |
+
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
193 |
+
if ( $inline_js ) {
|
194 |
+
return $html . $inline_js;
|
195 |
+
}
|
196 |
+
|
197 |
+
return $html;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* oEmbed not supported for search timeline
|
202 |
+
*
|
203 |
+
* @since 2.0.0
|
204 |
+
*
|
205 |
+
* @param array $query_parameters not used
|
206 |
+
*
|
207 |
+
* @return string empty string
|
208 |
+
*/
|
209 |
+
public static function getOEmbedCacheKeyCustomParameters( array $query_parameters )
|
210 |
+
{
|
211 |
+
return '';
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* oEmbed not supported for search timeline
|
216 |
+
*
|
217 |
+
* @since 2.0.0
|
218 |
+
*
|
219 |
+
* @param string $id not used
|
220 |
+
* @param array $query_parameters not used
|
221 |
+
*
|
222 |
+
* @return string empty string
|
223 |
+
*/
|
224 |
+
public static function getOEmbedCacheKey( $id, array $query_parameters )
|
225 |
+
{
|
226 |
+
return '';
|
227 |
+
}
|
228 |
+
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Timeline/TwitterList.php
ADDED
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display the latest Tweets from a list of Twitter accounts
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class TwitterList implements \Twitter\WordPress\Shortcodes\ShortcodeInterface, \Twitter\WordPress\Shortcodes\PublishOEmbedEndpoint
|
34 |
+
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\OEmbedTrait, \Twitter\WordPress\Shortcodes\Embeds\Timeline;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'twitter_list';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The oEmbed regex registered by WordPress Core
|
48 |
+
*
|
49 |
+
* @since 1.5.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const OEMBED_CORE_REGEX = '#https?://(www\.)?twitter\.com/\w{1,15}/lists/.*#i';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Regex used to match a List in text
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @type string
|
61 |
+
*/
|
62 |
+
const URL_REGEX = '#^https://twitter\.com/([a-z0-9_]{1,20})/lists/([a-z][a-z0-9_\\-]{0,24})$#i';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* HTML class to be used in div wrapper
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @type string
|
70 |
+
*/
|
71 |
+
const HTML_CLASS = 'twitter-timeline-list';
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Accepted shortcode attributes and their default values
|
75 |
+
*
|
76 |
+
* @since 2.0.0
|
77 |
+
*
|
78 |
+
* @type array
|
79 |
+
*/
|
80 |
+
public static $SHORTCODE_DEFAULTS = array( 'screen_name' => '', 'slug' => '' );
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Reference the feature by name
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @return string translated feature name
|
88 |
+
*/
|
89 |
+
public static function featureName()
|
90 |
+
{
|
91 |
+
return _x( 'Twitter List', 'The latest Tweets authored by members of a Twitter list', 'twitter' );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Describe shortcode for Shortcake UI
|
96 |
+
*
|
97 |
+
* @since 2.0.0
|
98 |
+
*
|
99 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcode UI
|
100 |
+
*
|
101 |
+
* @return void
|
102 |
+
*/
|
103 |
+
public static function shortcodeUI()
|
104 |
+
{
|
105 |
+
// Shortcode required
|
106 |
+
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
107 |
+
return;
|
108 |
+
}
|
109 |
+
|
110 |
+
shortcode_ui_register_for_shortcode(
|
111 |
+
static::SHORTCODE_TAG,
|
112 |
+
array(
|
113 |
+
'label' => esc_html( static::featureName() ),
|
114 |
+
'listItemImage' => 'dashicons-twitter',
|
115 |
+
'attrs' => array(
|
116 |
+
array(
|
117 |
+
'attr' => 'screen_name',
|
118 |
+
'label' => esc_html( __( 'Twitter @username', 'twitter' ) ),
|
119 |
+
'type' => 'text',
|
120 |
+
'meta' => array(
|
121 |
+
'placeholder' => 'UN',
|
122 |
+
'pattern' => '[A-Za-z0-9_]{1,20}',
|
123 |
+
),
|
124 |
+
),
|
125 |
+
array(
|
126 |
+
'attr' => 'slug',
|
127 |
+
'label' => esc_html( _x( 'List slug', 'Unique identifier for a Twitter List', 'twitter' ) ),
|
128 |
+
'type' => 'text',
|
129 |
+
'meta' => array(
|
130 |
+
'placeholder' => 'security-council',
|
131 |
+
'pattern' => '[a-z][a-z0-9_\\-]{0,24}',
|
132 |
+
),
|
133 |
+
),
|
134 |
+
),
|
135 |
+
)
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Handle a URL matched by a embed handler
|
141 |
+
*
|
142 |
+
* @since 2.0.0
|
143 |
+
*
|
144 |
+
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
145 |
+
* @param array $attr Embed attributes. Not used.
|
146 |
+
* @param string $url The original URL that was matched by the regex. Not used.
|
147 |
+
* @param array $rawattr The original unmodified attributes. Not used.
|
148 |
+
*
|
149 |
+
* @return string HTML markup for the profile timeline or an empty string if requirements not met
|
150 |
+
*/
|
151 |
+
public static function linkHandler( $matches, $attr, $url, $rawattr )
|
152 |
+
{
|
153 |
+
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] && isset( $matches[2] ) && $matches[2] ) ) {
|
154 |
+
return '';
|
155 |
+
}
|
156 |
+
|
157 |
+
return static::shortcodeHandler( array( 'screen_name' => $matches[1], 'slug' => $matches[2] ) );
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Handle shortcode macro
|
162 |
+
*
|
163 |
+
* @since 2.0.0
|
164 |
+
*
|
165 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
166 |
+
* @type string|int attribute name or positional int
|
167 |
+
* @type mixed shortcode value
|
168 |
+
* }
|
169 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
170 |
+
*
|
171 |
+
* @return string HTML markup. empty string if parameter requirement not met or no profile info found
|
172 |
+
*/
|
173 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
174 |
+
{
|
175 |
+
$options = static::getShortcodeAttributes( $attributes );
|
176 |
+
|
177 |
+
if ( ! ($options['screen_name'] && $options['slug']) ) {
|
178 |
+
return '';
|
179 |
+
}
|
180 |
+
|
181 |
+
$timeline = \Twitter\Widgets\Embeds\Timeline\TwitterList::fromArray( $options );
|
182 |
+
if ( ! ( $timeline && $timeline->getScreenName() && $timeline->getSlug() ) ) {
|
183 |
+
return '';
|
184 |
+
}
|
185 |
+
|
186 |
+
return static::getHTMLForTimeline( $timeline );
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Get a unique identifier for the datasource to uniquely identify
|
191 |
+
*
|
192 |
+
* Used in oEmbed cache key to save a short, unique representation of the datasource
|
193 |
+
*
|
194 |
+
* @since 2.0.0
|
195 |
+
*
|
196 |
+
* @param \Twitter\Widgets\Embeds\Timeline $timeline timeline object
|
197 |
+
*
|
198 |
+
* @return string unique identifier or empty string if minimum requirements not met
|
199 |
+
*/
|
200 |
+
public static function getDataSourceIdentifier( $timeline )
|
201 |
+
{
|
202 |
+
// verify passed parameter
|
203 |
+
if ( ! is_a( $timeline, '\Twitter\Widgets\Embeds\Timeline' ) ) {
|
204 |
+
return '';
|
205 |
+
}
|
206 |
+
|
207 |
+
$screen_name = $timeline->getScreenName();
|
208 |
+
if ( ! $screen_name ) {
|
209 |
+
return '';
|
210 |
+
}
|
211 |
+
$slug = $timeline->getSlug();
|
212 |
+
if ( ! $slug ) {
|
213 |
+
return '';
|
214 |
+
}
|
215 |
+
|
216 |
+
return $screen_name . '/' . $slug;
|
217 |
+
}
|
218 |
+
}
|
src/Twitter/WordPress/Shortcodes/Embeds/Tweet.php
ADDED
@@ -0,0 +1,559 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2015 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Display a Tweet
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Tweet implements \Twitter\WordPress\Shortcodes\ShortcodeInterface, \Twitter\WordPress\Shortcodes\PublishOEmbedEndpoint
|
34 |
+
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\OEmbedTrait;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shortcode tag to be matched
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_TAG = 'tweet';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The oEmbed regex registered by WordPress Core
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const OEMBED_CORE_REGEX = '#https?://(www\.)?twitter\.com/.+?/status(es)?/.*#i';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Regex used to match a Tweet in text
|
57 |
+
*
|
58 |
+
* More specific than WordPress Core regex
|
59 |
+
*
|
60 |
+
* @since 2.0.0
|
61 |
+
*
|
62 |
+
* @type string
|
63 |
+
*/
|
64 |
+
const URL_REGEX = '#^https?://(www\.)?twitter\.com/[a-z0-9_]{1,20}/status(es)?/([0-9]+)#i';
|
65 |
+
|
66 |
+
/**
|
67 |
+
* HTML class to be used in div wrapper
|
68 |
+
*
|
69 |
+
* @since 2.0.0
|
70 |
+
*
|
71 |
+
* @type string
|
72 |
+
*/
|
73 |
+
const HTML_CLASS = 'twitter-tweet';
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Tweet object class
|
77 |
+
*
|
78 |
+
* @since 2.0.0
|
79 |
+
*
|
80 |
+
* @type string
|
81 |
+
*/
|
82 |
+
const TWEET_CLASS = '\Twitter\Widgets\Embeds\Tweet';
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Base URL used to reconstruct a Tweet URL
|
86 |
+
*
|
87 |
+
* @since 1.3.0
|
88 |
+
*
|
89 |
+
* @type string
|
90 |
+
*/
|
91 |
+
const BASE_URL = 'https://twitter.com/_/status/';
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Accepted shortcode attributes and their default values
|
95 |
+
*
|
96 |
+
* @since 2.0.0
|
97 |
+
*
|
98 |
+
* @type array
|
99 |
+
*/
|
100 |
+
public static $SHORTCODE_DEFAULTS = array(
|
101 |
+
'id' => null,
|
102 |
+
'conversation' => true,
|
103 |
+
'cards' => true,
|
104 |
+
'width' => null,
|
105 |
+
'align' => null,
|
106 |
+
'theme' => null,
|
107 |
+
'link_color' => null,
|
108 |
+
'border_color' => null,
|
109 |
+
);
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Extra parameters accepted by Jetpack included for compatibility
|
113 |
+
*
|
114 |
+
* @since 2.0.0
|
115 |
+
*
|
116 |
+
* @link https://github.com/Automattic/jetpack/blob/master/modules/shortcodes/tweet.php Jetpack tweet shortcode
|
117 |
+
*
|
118 |
+
* @type array
|
119 |
+
*/
|
120 |
+
public static $JETPACK_SHORTCODE_EXTRAS = array(
|
121 |
+
'tweet' => null,
|
122 |
+
'hide_thread' => false,
|
123 |
+
'hide_media' => false,
|
124 |
+
);
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Data attribute keys used in a Tweet object mapped to oEmbed keys used by Jetpack
|
128 |
+
*
|
129 |
+
* @since 2.0.0
|
130 |
+
*
|
131 |
+
* @type array
|
132 |
+
*/
|
133 |
+
public static $DATA_ATTRIBUTES_TO_OEMBED_KEYS = array(
|
134 |
+
'cards' => 'hide_media',
|
135 |
+
'conversation' => 'hide_thread',
|
136 |
+
);
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Shortcode attributes to be converted from underscores to dashes before object initialization
|
140 |
+
*
|
141 |
+
* @since 2.0.0
|
142 |
+
*
|
143 |
+
* @type array
|
144 |
+
*/
|
145 |
+
public static $OPTIONS_KEYS_UNDERSCORE_TO_DASHES = array(
|
146 |
+
'link_color' => 'link-color',
|
147 |
+
'border_color' => 'border-color',
|
148 |
+
);
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Attach handlers for embedded Tweets
|
152 |
+
*
|
153 |
+
* @since 2.0.0
|
154 |
+
*
|
155 |
+
* @return void
|
156 |
+
*/
|
157 |
+
public static function init()
|
158 |
+
{
|
159 |
+
$classname = get_called_class();
|
160 |
+
|
161 |
+
// register our shortcode and its handler
|
162 |
+
add_shortcode( self::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
163 |
+
|
164 |
+
// Shortcode UI, if supported
|
165 |
+
add_action(
|
166 |
+
'register_shortcode_ui',
|
167 |
+
array( $classname, 'shortcodeUI' ),
|
168 |
+
5,
|
169 |
+
0
|
170 |
+
);
|
171 |
+
|
172 |
+
if ( ! is_admin() ) {
|
173 |
+
// unhook the WordPress Core oEmbed handler
|
174 |
+
wp_oembed_remove_provider( static::OEMBED_CORE_REGEX );
|
175 |
+
// pass a Tweet detail URL through the Tweet shortcode handler
|
176 |
+
wp_embed_register_handler(
|
177 |
+
self::SHORTCODE_TAG,
|
178 |
+
static::URL_REGEX,
|
179 |
+
array( $classname, 'linkHandler' ),
|
180 |
+
1
|
181 |
+
);
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Reference the feature by name
|
187 |
+
*
|
188 |
+
* @since 2.0.0
|
189 |
+
*
|
190 |
+
* @return string translated feature name
|
191 |
+
*/
|
192 |
+
public static function featureName()
|
193 |
+
{
|
194 |
+
return __( 'Embedded Tweet', 'twitter' );
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Describe shortcode for Shortcake UI
|
199 |
+
*
|
200 |
+
* @since 2.0.0
|
201 |
+
*
|
202 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcake UI
|
203 |
+
*
|
204 |
+
* @return void
|
205 |
+
*/
|
206 |
+
public static function shortcodeUI()
|
207 |
+
{
|
208 |
+
// Shortcake required
|
209 |
+
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
210 |
+
return;
|
211 |
+
}
|
212 |
+
|
213 |
+
// id only
|
214 |
+
// avoids an unchecked Shortcake input checkbox requiring a shortcode output
|
215 |
+
shortcode_ui_register_for_shortcode(
|
216 |
+
self::SHORTCODE_TAG,
|
217 |
+
array(
|
218 |
+
'label' => esc_html( static::featureName() ),
|
219 |
+
'listItemImage' => 'dashicons-twitter',
|
220 |
+
'attrs' => array(
|
221 |
+
array(
|
222 |
+
'attr' => 'id',
|
223 |
+
'label' => 'ID',
|
224 |
+
'type' => 'text',
|
225 |
+
'meta' => array(
|
226 |
+
'required' => true,
|
227 |
+
'pattern' => '[0-9]+',
|
228 |
+
'placeholder' => '560070183650213889',
|
229 |
+
),
|
230 |
+
),
|
231 |
+
),
|
232 |
+
)
|
233 |
+
);
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Handle a URL matched by an embed handler
|
238 |
+
*
|
239 |
+
* @since 2.0.0
|
240 |
+
*
|
241 |
+
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
242 |
+
*
|
243 |
+
* @return string HTML markup for the Tweet or an empty string if requirements not met
|
244 |
+
*/
|
245 |
+
public static function linkHandler( $matches )
|
246 |
+
{
|
247 |
+
if ( ! ( is_array( $matches ) && isset( $matches[3] ) && $matches[3] ) ) {
|
248 |
+
return '';
|
249 |
+
}
|
250 |
+
|
251 |
+
return static::shortcodeHandler( array( 'id' => $matches[3] ) );
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Convert a Tweet ID in ID or URL form into a trimmed ID
|
256 |
+
*
|
257 |
+
* @since 2.0.0
|
258 |
+
*
|
259 |
+
* @param string $tweet_id Tweet identifier
|
260 |
+
*
|
261 |
+
* @return string $tweet_id Tweet identifier or empty string if minimum requirements not met
|
262 |
+
*/
|
263 |
+
public static function sanitizeTweetID( $tweet_id )
|
264 |
+
{
|
265 |
+
if ( ! is_string( $tweet_id ) ) {
|
266 |
+
return '';
|
267 |
+
}
|
268 |
+
|
269 |
+
$tweet_id = trim( $tweet_id );
|
270 |
+
if ( ! $tweet_id ) {
|
271 |
+
return '';
|
272 |
+
}
|
273 |
+
$tweet_id = trim( rtrim( trim( $tweet_id ), '/' ) );
|
274 |
+
if ( ! $tweet_id ) {
|
275 |
+
return '';
|
276 |
+
}
|
277 |
+
|
278 |
+
$last_slash = strrpos( $tweet_id, '/' );
|
279 |
+
if ( false !== $last_slash ) {
|
280 |
+
$tweet_id = substr( $tweet_id, $last_slash + 1 );
|
281 |
+
}
|
282 |
+
|
283 |
+
return $tweet_id;
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Shortcode allowed attributes and default values Tweet
|
288 |
+
*
|
289 |
+
* Jetpack compatibility mixed in
|
290 |
+
*
|
291 |
+
* @since 2.0.0
|
292 |
+
*
|
293 |
+
* @return array shortcode allowed attributes and default values
|
294 |
+
*/
|
295 |
+
public static function getShortcodeDefaults()
|
296 |
+
{
|
297 |
+
return array_merge( static::$JETPACK_SHORTCODE_EXTRAS, static::$SHORTCODE_DEFAULTS );
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Process shortcode attributes received from the shortcode API
|
302 |
+
*
|
303 |
+
* @since 2.0.0
|
304 |
+
*
|
305 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
306 |
+
*
|
307 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
308 |
+
*
|
309 |
+
* @return array array processed by shortcode_atts, prepped for Tweet object
|
310 |
+
*/
|
311 |
+
public static function getShortcodeAttributes( $attributes )
|
312 |
+
{
|
313 |
+
$options = shortcode_atts(
|
314 |
+
static::getShortcodeDefaults(),
|
315 |
+
$attributes,
|
316 |
+
static::SHORTCODE_TAG
|
317 |
+
);
|
318 |
+
|
319 |
+
if ( ! is_array( $options ) || empty( $options ) ) {
|
320 |
+
return array();
|
321 |
+
}
|
322 |
+
|
323 |
+
// support a Tweet ID or URL in the first position for compatibility with WordPress.com / Jetpack
|
324 |
+
if ( empty( $options['id'] ) ) {
|
325 |
+
// support tweet attribute for WordPress.com / Jetpack compatibility
|
326 |
+
if ( ! empty( $options['tweet'] ) ) {
|
327 |
+
$options['id'] = $options['tweet'];
|
328 |
+
} else {
|
329 |
+
// support Tweet ID or URL in the first position for compatibility with WordPress.com / Jetpack
|
330 |
+
if ( ! empty( $attributes[0] ) ) {
|
331 |
+
$options['id'] = $attributes[0];
|
332 |
+
unset( $options['tweet'] );
|
333 |
+
}
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
return static::shortcodeAttributesToTweetKeys( $options );
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Convert shortcode parameters, attributes, and defaults into a clean set of Tweet parameters
|
342 |
+
*
|
343 |
+
* @since 2.0.0
|
344 |
+
*
|
345 |
+
* @param array $attributes set of shortcode attribute-value pairs content matching the WordPress shortcode regex {
|
346 |
+
* @type string|int attribute name or positional int
|
347 |
+
* @type mixed shortcode value
|
348 |
+
* }
|
349 |
+
*
|
350 |
+
* @return array cleaned up options ready to be passed into a Tweet object {
|
351 |
+
* @type string option name
|
352 |
+
* @type string|bool option value
|
353 |
+
* }
|
354 |
+
*/
|
355 |
+
public static function shortcodeAttributesToTweetKeys( $attributes )
|
356 |
+
{
|
357 |
+
if ( ! is_array( $attributes ) || empty( $attributes ) ) {
|
358 |
+
return array();
|
359 |
+
}
|
360 |
+
|
361 |
+
if ( isset( $attributes['id'] ) ) {
|
362 |
+
$attributes['id'] = static::sanitizeTweetID( (string) $attributes['id'] );
|
363 |
+
} else {
|
364 |
+
return array();
|
365 |
+
}
|
366 |
+
if ( ! $attributes['id'] ) {
|
367 |
+
return array();
|
368 |
+
}
|
369 |
+
|
370 |
+
$attributes = \Twitter\WordPress\Shortcodes\Helpers\Attributes::booleanOption(
|
371 |
+
$attributes,
|
372 |
+
array( 'cards', 'hide_media', 'conversation', 'hide_thread' )
|
373 |
+
);
|
374 |
+
$attributes = \Twitter\WordPress\Shortcodes\Helpers\Attributes::positiveIntegerOption(
|
375 |
+
$attributes,
|
376 |
+
array( 'width' )
|
377 |
+
);
|
378 |
+
$attributes = \Twitter\WordPress\Shortcodes\Helpers\Attributes::lowercaseStringOption(
|
379 |
+
$attributes,
|
380 |
+
array( 'align', 'theme', 'link_color', 'border_color' )
|
381 |
+
);
|
382 |
+
|
383 |
+
// test for oEmbed-style parameter used by WordPress.com / Jetpack
|
384 |
+
// if both attributes are used and have values prefer cards and conversation
|
385 |
+
foreach ( static::$DATA_ATTRIBUTES_TO_OEMBED_KEYS as $option => $alternate_naming ) {
|
386 |
+
if ( isset( $attributes[ $alternate_naming ] ) ) {
|
387 |
+
if ( ! isset( $attributes[ $option ] ) && $attributes[ $alternate_naming ] !== static::$SHORTCODE_DEFAULTS[ $option ] ) {
|
388 |
+
$attributes[ $option ] = $attributes[ $alternate_naming ];
|
389 |
+
}
|
390 |
+
unset( $attributes[ $alternate_naming ] );
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
foreach ( static::$OPTIONS_KEYS_UNDERSCORE_TO_DASHES as $underscore => $dashes ) {
|
395 |
+
if ( ! isset( $attributes[ $underscore ] ) ) {
|
396 |
+
continue;
|
397 |
+
}
|
398 |
+
$attributes[ $dashes ] = $attributes[ $underscore ];
|
399 |
+
unset( $attributes[ $underscore ] );
|
400 |
+
}
|
401 |
+
|
402 |
+
return $attributes;
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Handle shortcode macro
|
407 |
+
*
|
408 |
+
* @since 2.0.0
|
409 |
+
*
|
410 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
411 |
+
* @type string|int attribute name or positional int
|
412 |
+
* @type mixed shortcode value
|
413 |
+
* }
|
414 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
415 |
+
*
|
416 |
+
* @return string HTML markup. empty string if parameter requirement not met or no Tweet info found
|
417 |
+
*/
|
418 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
419 |
+
{
|
420 |
+
$options = static::getShortcodeAttributes( $attributes );
|
421 |
+
|
422 |
+
$tweet_id = '';
|
423 |
+
if ( isset( $options['id'] ) ) {
|
424 |
+
$tweet_id = $options['id'];
|
425 |
+
} else {
|
426 |
+
// allow shortcode use in enclosed form
|
427 |
+
$content = trim( $content );
|
428 |
+
if ( $content ) {
|
429 |
+
$tweet_id = static::sanitizeTweetID( $content );
|
430 |
+
}
|
431 |
+
}
|
432 |
+
if ( ! $tweet_id ) {
|
433 |
+
return '';
|
434 |
+
}
|
435 |
+
$options['id'] = $tweet_id;
|
436 |
+
|
437 |
+
$object_class = static::TWEET_CLASS;
|
438 |
+
if ( ! method_exists( $object_class, 'fromArray' ) ) {
|
439 |
+
return '';
|
440 |
+
}
|
441 |
+
$tweet = $object_class::fromArray( $options );
|
442 |
+
unset( $object_class );
|
443 |
+
if ( ! ($tweet && method_exists( $tweet, 'getID' ) && $tweet->getID() && method_exists( $tweet, 'toOEmbedParameterArray' ) ) ) {
|
444 |
+
return '';
|
445 |
+
}
|
446 |
+
|
447 |
+
$oembed_params = $tweet->toOEmbedParameterArray();
|
448 |
+
if ( empty( $oembed_params ) || ! isset( $oembed_params['url'] ) ) {
|
449 |
+
return '';
|
450 |
+
}
|
451 |
+
$oembed_params = array_merge( static::getBaseOEmbedParams(), $oembed_params );
|
452 |
+
|
453 |
+
$cache_key = static::getOEmbedCacheKey( $tweet_id, $oembed_params );
|
454 |
+
if ( ! $cache_key ) {
|
455 |
+
return '';
|
456 |
+
}
|
457 |
+
|
458 |
+
// fetch HTML markup from Twitter oEmbed endpoint for the given parameters
|
459 |
+
$html = trim( static::getOEmbedMarkup( $oembed_params, $cache_key ) );
|
460 |
+
if ( ! $html ) {
|
461 |
+
return '';
|
462 |
+
}
|
463 |
+
|
464 |
+
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
465 |
+
|
466 |
+
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
467 |
+
if ( $inline_js ) {
|
468 |
+
return $html . $inline_js;
|
469 |
+
}
|
470 |
+
|
471 |
+
return $html;
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Generate a unique string representing oEmbed result customizations set by shortcode parameters
|
476 |
+
*
|
477 |
+
* @since 2.0.0
|
478 |
+
*
|
479 |
+
* @param array $query_parameters associative array of query parameters sent to the oEmbed endpoint {
|
480 |
+
* @type string query parameter name
|
481 |
+
* @type string|bool query parameter value
|
482 |
+
* }
|
483 |
+
*
|
484 |
+
* @return string cache key component
|
485 |
+
*/
|
486 |
+
public static function getOEmbedCacheKeyCustomParameters( array $query_parameters )
|
487 |
+
{
|
488 |
+
$key_pieces = array();
|
489 |
+
|
490 |
+
if ( isset( $query_parameters['maxwidth'] ) ) {
|
491 |
+
$key_pieces[] = 'w' . $query_parameters['maxwidth'];
|
492 |
+
}
|
493 |
+
|
494 |
+
// one letter customizations
|
495 |
+
$customizations = '';
|
496 |
+
if ( isset( $query_parameters['hide_media'] ) && $query_parameters['hide_media'] ) {
|
497 |
+
$customizations .= 'm';
|
498 |
+
}
|
499 |
+
if ( isset( $query_parameters['hide_thread'] ) && $query_parameters['hide_thread'] ) {
|
500 |
+
$customizations .= 't';
|
501 |
+
}
|
502 |
+
// should only be set for dark theme
|
503 |
+
if ( isset( $query_parameters['theme'] ) ) {
|
504 |
+
$customizations .= 'd';
|
505 |
+
}
|
506 |
+
// left, right, center
|
507 |
+
if ( isset( $query_parameters['align'] ) && $query_parameters['align'] ) {
|
508 |
+
$customizations .= substr( $query_parameters['align'], 0, 1 );
|
509 |
+
}
|
510 |
+
if ( $customizations ) {
|
511 |
+
$key_pieces[] = $customizations;
|
512 |
+
}
|
513 |
+
unset( $customizations );
|
514 |
+
|
515 |
+
$color_parameters = array(
|
516 |
+
'link_color' => 'l',
|
517 |
+
'border_color' => 'b',
|
518 |
+
);
|
519 |
+
foreach ( $color_parameters as $query_parameter => $cache_abbreviation ) {
|
520 |
+
if ( isset( $query_parameters[ $query_parameter ] ) ) {
|
521 |
+
$key_pieces[] = $cache_abbreviation . ltrim( $query_parameters[ $query_parameter ], '#' );
|
522 |
+
}
|
523 |
+
}
|
524 |
+
|
525 |
+
return implode( '_', $key_pieces );
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* Construct a cache key for the oEmbed response. Account for query parameters needing to bust cache
|
530 |
+
*
|
531 |
+
* @since 2.0.0
|
532 |
+
*
|
533 |
+
* @link https://dev.twitter.com/rest/reference/get/statuses/oembed oEmbed doc
|
534 |
+
*
|
535 |
+
* @param string $id Tweet ID
|
536 |
+
* @param array $query_parameters oEmbed API query parameters
|
537 |
+
*
|
538 |
+
* @return string cache key
|
539 |
+
*/
|
540 |
+
public static function getOEmbedCacheKey( $id, array $query_parameters )
|
541 |
+
{
|
542 |
+
if ( ! ( is_string( $id ) && $id ) ) {
|
543 |
+
return '';
|
544 |
+
}
|
545 |
+
$key_pieces = array( static::SHORTCODE_TAG, $id );
|
546 |
+
|
547 |
+
// separate cache for each explicitly-defined display language
|
548 |
+
if ( isset( $query_parameters['lang'] ) && $query_parameters['lang'] ) {
|
549 |
+
$key_pieces[] = $query_parameters['lang'];
|
550 |
+
}
|
551 |
+
|
552 |
+
$customizations = static::getOEmbedCacheKeyCustomParameters( $query_parameters );
|
553 |
+
if ( $customizations ) {
|
554 |
+
$key_pieces[] = $customizations;
|
555 |
+
}
|
556 |
+
|
557 |
+
return implode( '_', $key_pieces );
|
558 |
+
}
|
559 |
+
}
|
src/Twitter/WordPress/Shortcodes/{EmbeddedTweetVideo.php → Embeds/Tweet/Video.php}
RENAMED
@@ -23,20 +23,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
|
28 |
/**
|
29 |
* Display a video attached to a Tweet
|
30 |
*
|
31 |
-
* @since
|
32 |
*/
|
33 |
-
class
|
34 |
{
|
35 |
|
36 |
/**
|
37 |
* Shortcode tag to be matched
|
38 |
*
|
39 |
-
* @since
|
40 |
*
|
41 |
* @type string
|
42 |
*/
|
@@ -45,16 +45,34 @@ class EmbeddedTweetVideo extends EmbeddedTweet
|
|
45 |
/**
|
46 |
* Accepted shortcode attributes and their default values
|
47 |
*
|
48 |
-
* @since
|
49 |
*
|
50 |
* @type array
|
51 |
*/
|
52 |
-
public static $SHORTCODE_DEFAULTS = array( 'id' => ''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
/**
|
55 |
* Attach handlers for Twitter embedded video
|
56 |
*
|
57 |
-
* @since
|
58 |
*
|
59 |
* @return void
|
60 |
*/
|
@@ -74,12 +92,24 @@ class EmbeddedTweetVideo extends EmbeddedTweet
|
|
74 |
);
|
75 |
}
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
/**
|
78 |
* Describe shortcode for Shortcake UI
|
79 |
*
|
80 |
* @since 1.1.0
|
81 |
*
|
82 |
-
* @link https://github.com/
|
83 |
*
|
84 |
* @return void
|
85 |
*/
|
@@ -95,7 +125,7 @@ class EmbeddedTweetVideo extends EmbeddedTweet
|
|
95 |
shortcode_ui_register_for_shortcode(
|
96 |
self::SHORTCODE_TAG,
|
97 |
array(
|
98 |
-
'label' =>
|
99 |
'listItemImage' => 'dashicons-twitter',
|
100 |
'attrs' => array(
|
101 |
array(
|
@@ -116,7 +146,7 @@ class EmbeddedTweetVideo extends EmbeddedTweet
|
|
116 |
/**
|
117 |
* Convert shortcode parameters into a clean set of Twitter embedded video options parameters
|
118 |
*
|
119 |
-
* @since
|
120 |
*
|
121 |
* @param array $attributes set of shortcode attribute-value pairs matching the WordPress shortcode regex {
|
122 |
* @type string attribute name
|
@@ -145,101 +175,46 @@ class EmbeddedTweetVideo extends EmbeddedTweet
|
|
145 |
unset( $tweet_id );
|
146 |
}
|
147 |
|
148 |
-
// allow option style or oEmbed style parameter
|
149 |
-
if ( isset( $attributes['status'] ) ) {
|
150 |
-
if ( false === $attributes['status'] || '0' == $attributes['status'] || ( is_string( $attributes['status'] ) && in_array( strtolower( $attributes['status'] ), array( 'false', 'no', 'off' ) ) ) ) {
|
151 |
-
$options['status'] = false;
|
152 |
-
}
|
153 |
-
} else if ( isset( $attributes['hide_tweet'] ) ) {
|
154 |
-
if ( true === $attributes['hide_tweet'] || '1' == $attributes['hide_tweet'] || ( is_string( $attributes['hide_tweet'] ) && in_array( strtolower( $attributes['hide_tweet'] ), array( 'true', 'yes', 'on' ) ) ) ) {
|
155 |
-
$options['status'] = false;
|
156 |
-
}
|
157 |
-
}
|
158 |
-
|
159 |
return $options;
|
160 |
}
|
161 |
|
162 |
/**
|
163 |
-
*
|
164 |
*
|
165 |
-
* @since
|
166 |
*
|
167 |
-
* @param array
|
168 |
-
*
|
|
|
|
|
169 |
*
|
170 |
-
* @return
|
|
|
|
|
|
|
171 |
*/
|
172 |
-
public static function
|
173 |
{
|
174 |
-
|
175 |
-
|
176 |
-
/** This filter is documented in wp-includes/shortcodes.php */
|
177 |
-
$options = apply_filters(
|
178 |
-
'shortcode_atts_' . self::SHORTCODE_TAG,
|
179 |
-
array_merge(
|
180 |
-
static::$SHORTCODE_DEFAULTS,
|
181 |
-
static::sanitizeShortcodeParameters( (array) $attributes )
|
182 |
-
),
|
183 |
-
static::$SHORTCODE_DEFAULTS,
|
184 |
-
$attributes
|
185 |
-
);
|
186 |
-
|
187 |
-
if ( ! $options['id'] ) {
|
188 |
-
return '';
|
189 |
-
}
|
190 |
-
$tweet_id = $options['id'];
|
191 |
-
unset( $options['id'] );
|
192 |
-
|
193 |
-
$oembed_params = static::shortcodeParamsToOEmbedParams( $tweet_id, $options );
|
194 |
-
if ( empty( $oembed_params ) ) {
|
195 |
-
return '';
|
196 |
-
}
|
197 |
-
|
198 |
-
// fetch HTML markup from Twitter oEmbed endpoint for the given parameters
|
199 |
-
$html = trim( static::getOEmbedMarkup( $oembed_params ) );
|
200 |
-
if ( ! $html ) {
|
201 |
-
return '';
|
202 |
-
}
|
203 |
-
|
204 |
-
$html = '<div class="twitter-video">' . $html . '</div>';
|
205 |
-
|
206 |
-
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
207 |
-
if ( $inline_js ) {
|
208 |
-
return $html . $inline_js;
|
209 |
}
|
210 |
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
/**
|
215 |
-
* Convert shortcode parameters into query parameters supported by the Twitter oEmbed endpoint
|
216 |
-
*
|
217 |
-
* @since 1.0.0
|
218 |
-
*
|
219 |
-
* @param string $tweet_id Tweet identifier
|
220 |
-
* @param array $shortcode_options customizations specified in the shortcode
|
221 |
-
*
|
222 |
-
* @return array associative array of query parameters ready for http_build_query
|
223 |
-
*/
|
224 |
-
public static function shortcodeParamsToOEmbedParams( $tweet_id, $shortcode_options = array() )
|
225 |
-
{
|
226 |
-
$query_parameters = static::getBaseOEmbedParams( $tweet_id );
|
227 |
-
if ( empty( $query_parameters ) ) {
|
228 |
return array();
|
229 |
}
|
230 |
-
$
|
231 |
-
|
232 |
-
if ( isset( $shortcode_options['status'] ) && false === $shortcode_options['status'] ) {
|
233 |
-
$query_parameters['hide_tweet'] = true;
|
234 |
}
|
235 |
|
236 |
-
return $
|
237 |
}
|
238 |
|
239 |
/**
|
240 |
* Generate a unique string representing oEmbed result customizations set by shortcode parameters
|
241 |
*
|
242 |
-
* @since
|
243 |
*
|
244 |
* @param array $query_parameters associative array of query parameters sent to the oEmbed endpoint {
|
245 |
* @type string query parameter name
|
@@ -250,12 +225,6 @@ class EmbeddedTweetVideo extends EmbeddedTweet
|
|
250 |
*/
|
251 |
public static function getOEmbedCacheKeyCustomParameters( array $query_parameters )
|
252 |
{
|
253 |
-
|
254 |
-
|
255 |
-
if ( isset( $query_parameters['hide_tweet'] ) && $query_parameters['hide_tweet'] ) {
|
256 |
-
$customizations .= 'h';
|
257 |
-
}
|
258 |
-
|
259 |
-
return $customizations;
|
260 |
}
|
261 |
}
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds\Tweet;
|
27 |
|
28 |
/**
|
29 |
* Display a video attached to a Tweet
|
30 |
*
|
31 |
+
* @since 2.0.0
|
32 |
*/
|
33 |
+
class Video extends \Twitter\WordPress\Shortcodes\Embeds\Tweet
|
34 |
{
|
35 |
|
36 |
/**
|
37 |
* Shortcode tag to be matched
|
38 |
*
|
39 |
+
* @since 2.0.0
|
40 |
*
|
41 |
* @type string
|
42 |
*/
|
45 |
/**
|
46 |
* Accepted shortcode attributes and their default values
|
47 |
*
|
48 |
+
* @since 2.0.0
|
49 |
*
|
50 |
* @type array
|
51 |
*/
|
52 |
+
public static $SHORTCODE_DEFAULTS = array( 'id' => '' );
|
53 |
+
|
54 |
+
/**
|
55 |
+
* HTML class to be used in div wrapper
|
56 |
+
*
|
57 |
+
* @since 2.0.0
|
58 |
+
*
|
59 |
+
* @type string
|
60 |
+
*/
|
61 |
+
const HTML_CLASS = 'twitter-video';
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Tweet object class
|
65 |
+
*
|
66 |
+
* @since 2.0.0
|
67 |
+
*
|
68 |
+
* @type string
|
69 |
+
*/
|
70 |
+
const TWEET_CLASS = '\Twitter\Widgets\Embeds\Tweet\Video';
|
71 |
|
72 |
/**
|
73 |
* Attach handlers for Twitter embedded video
|
74 |
*
|
75 |
+
* @since 2.0.0
|
76 |
*
|
77 |
* @return void
|
78 |
*/
|
92 |
);
|
93 |
}
|
94 |
|
95 |
+
/**
|
96 |
+
* Reference the feature by name
|
97 |
+
*
|
98 |
+
* @since 2.0.0
|
99 |
+
*
|
100 |
+
* @return string translated feature name
|
101 |
+
*/
|
102 |
+
public static function featureName()
|
103 |
+
{
|
104 |
+
return _x( 'Twitter Video', 'A single embedded Tweet shown with a video-specific template', 'twitter' );
|
105 |
+
}
|
106 |
+
|
107 |
/**
|
108 |
* Describe shortcode for Shortcake UI
|
109 |
*
|
110 |
* @since 1.1.0
|
111 |
*
|
112 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcake UI
|
113 |
*
|
114 |
* @return void
|
115 |
*/
|
125 |
shortcode_ui_register_for_shortcode(
|
126 |
self::SHORTCODE_TAG,
|
127 |
array(
|
128 |
+
'label' => esc_html( static::featureName() ),
|
129 |
'listItemImage' => 'dashicons-twitter',
|
130 |
'attrs' => array(
|
131 |
array(
|
146 |
/**
|
147 |
* Convert shortcode parameters into a clean set of Twitter embedded video options parameters
|
148 |
*
|
149 |
+
* @since 2.0.0
|
150 |
*
|
151 |
* @param array $attributes set of shortcode attribute-value pairs matching the WordPress shortcode regex {
|
152 |
* @type string attribute name
|
175 |
unset( $tweet_id );
|
176 |
}
|
177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
return $options;
|
179 |
}
|
180 |
|
181 |
/**
|
182 |
+
* Convert shortcode parameters, attributes, and defaults into a clean set of Tweet parameters
|
183 |
*
|
184 |
+
* @since 2.0.0
|
185 |
*
|
186 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
187 |
+
* @type string|int attribute name or positional int
|
188 |
+
* @type mixed shortcode value
|
189 |
+
* }
|
190 |
*
|
191 |
+
* @return array cleaned up options ready to be passed into a Tweet Video object {
|
192 |
+
* @type string option name
|
193 |
+
* @type string|bool option value
|
194 |
+
* }
|
195 |
*/
|
196 |
+
public static function shortcodeAttributesToTweetKeys( $attributes )
|
197 |
{
|
198 |
+
if ( ! is_array( $attributes ) || empty( $attributes ) ) {
|
199 |
+
return array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
|
202 |
+
if ( isset( $attributes['id'] ) ) {
|
203 |
+
$attributes['id'] = static::sanitizeTweetID( (string) $attributes['id'] );
|
204 |
+
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
return array();
|
206 |
}
|
207 |
+
if ( ! $attributes['id'] ) {
|
208 |
+
return array();
|
|
|
|
|
209 |
}
|
210 |
|
211 |
+
return $attributes;
|
212 |
}
|
213 |
|
214 |
/**
|
215 |
* Generate a unique string representing oEmbed result customizations set by shortcode parameters
|
216 |
*
|
217 |
+
* @since 2.0.0
|
218 |
*
|
219 |
* @param array $query_parameters associative array of query parameters sent to the oEmbed endpoint {
|
220 |
* @type string query parameter name
|
225 |
*/
|
226 |
public static function getOEmbedCacheKeyCustomParameters( array $query_parameters )
|
227 |
{
|
228 |
+
return '';
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
}
|
230 |
}
|
src/Twitter/WordPress/Shortcodes/{Vine.php → Embeds/Vine.php}
RENAMED
@@ -23,21 +23,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
|
28 |
/**
|
29 |
* Display a Vine
|
30 |
*
|
31 |
-
* @since
|
32 |
*/
|
33 |
-
class Vine implements ShortcodeInterface
|
34 |
{
|
35 |
-
use OEmbedTrait;
|
36 |
|
37 |
/**
|
38 |
* Shortcode tag to be matched
|
39 |
*
|
40 |
-
* @since
|
41 |
*
|
42 |
* @type string
|
43 |
*/
|
@@ -46,7 +46,7 @@ class Vine implements ShortcodeInterface
|
|
46 |
/**
|
47 |
* HTML class to be used in div wrapper
|
48 |
*
|
49 |
-
* @since
|
50 |
*
|
51 |
* @type string
|
52 |
*/
|
@@ -55,16 +55,16 @@ class Vine implements ShortcodeInterface
|
|
55 |
/**
|
56 |
* Regex used to match a Vine in text
|
57 |
*
|
58 |
-
* @since
|
59 |
*
|
60 |
* @type string
|
61 |
*/
|
62 |
const URL_REGEX = '#https?://vine\.co/v/([a-z0-9]+)\/?#i';
|
63 |
|
64 |
/**
|
65 |
-
* oEmbed regex registered by WordPress Core since 4.1
|
66 |
*
|
67 |
-
* @since
|
68 |
*
|
69 |
* @type string
|
70 |
*/
|
@@ -73,7 +73,7 @@ class Vine implements ShortcodeInterface
|
|
73 |
/**
|
74 |
* Base URL used to reconstruct a Vine URL
|
75 |
*
|
76 |
-
* @since
|
77 |
*
|
78 |
* @type string
|
79 |
*/
|
@@ -82,7 +82,7 @@ class Vine implements ShortcodeInterface
|
|
82 |
/**
|
83 |
* PHP class to use for fetching oEmbed data
|
84 |
*
|
85 |
-
* @since
|
86 |
*
|
87 |
* @type string
|
88 |
*/
|
@@ -91,7 +91,7 @@ class Vine implements ShortcodeInterface
|
|
91 |
/**
|
92 |
* Relative path for the oEmbed API relative to Vine base path
|
93 |
*
|
94 |
-
* @since
|
95 |
*
|
96 |
* @type string
|
97 |
*/
|
@@ -100,7 +100,7 @@ class Vine implements ShortcodeInterface
|
|
100 |
/**
|
101 |
* Accepted shortcode attributes and their default values
|
102 |
*
|
103 |
-
* @since
|
104 |
*
|
105 |
* @type array
|
106 |
*/
|
@@ -109,7 +109,7 @@ class Vine implements ShortcodeInterface
|
|
109 |
/**
|
110 |
* Attach handlers for Vine
|
111 |
*
|
112 |
-
* @since
|
113 |
*
|
114 |
* @return void
|
115 |
*/
|
@@ -143,7 +143,7 @@ class Vine implements ShortcodeInterface
|
|
143 |
/**
|
144 |
* Reference the feature by name
|
145 |
*
|
146 |
-
* @since
|
147 |
*
|
148 |
* @return string translated feature name
|
149 |
*/
|
@@ -155,9 +155,9 @@ class Vine implements ShortcodeInterface
|
|
155 |
/**
|
156 |
* Describe shortcode for Shortcake UI
|
157 |
*
|
158 |
-
* @since
|
159 |
*
|
160 |
-
* @link https://github.com/
|
161 |
*
|
162 |
* @return void
|
163 |
*/
|
@@ -191,16 +191,13 @@ class Vine implements ShortcodeInterface
|
|
191 |
/**
|
192 |
* Handle a URL matched by a embed handler
|
193 |
*
|
194 |
-
* @since
|
195 |
*
|
196 |
-
* @param array
|
197 |
-
* @param array $attr Embed attributes. Not used.
|
198 |
-
* @param string $url The original URL that was matched by the regex. Not used.
|
199 |
-
* @param array $rawattr The original unmodified attributes. Not used.
|
200 |
*
|
201 |
* @return string HTML markup for the Vine or an empty string if requirements not met
|
202 |
*/
|
203 |
-
public static function linkHandler( $matches
|
204 |
{
|
205 |
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] ) ) {
|
206 |
return '';
|
@@ -210,39 +207,55 @@ class Vine implements ShortcodeInterface
|
|
210 |
}
|
211 |
|
212 |
/**
|
213 |
-
*
|
214 |
-
*
|
215 |
-
* @since 1.3.0
|
216 |
*
|
217 |
-
* @
|
218 |
-
* @type string|int attribute name or positional int
|
219 |
-
* @type mixed shortcode value
|
220 |
-
* }
|
221 |
-
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
222 |
*
|
223 |
-
* @return
|
224 |
*/
|
225 |
-
public static function
|
226 |
{
|
227 |
-
|
|
|
228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
$options = shortcode_atts(
|
230 |
-
static
|
231 |
$attributes,
|
232 |
static::SHORTCODE_TAG
|
233 |
);
|
234 |
|
235 |
-
$
|
236 |
-
|
237 |
-
return '';
|
238 |
}
|
239 |
|
240 |
-
|
241 |
-
|
|
|
242 |
|
243 |
-
$
|
244 |
-
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
}
|
247 |
if ( $width > 100 ) {
|
248 |
// reset max_width to max value supported by Vine
|
@@ -250,11 +263,51 @@ class Vine implements ShortcodeInterface
|
|
250 |
if ( $width > 600 ) {
|
251 |
$width = 600;
|
252 |
}
|
253 |
-
$
|
254 |
}
|
255 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
// fetch HTML markup from Vine oEmbed endpoint for the given parameters
|
257 |
-
$html = trim( static::getOEmbedMarkup( $query_parameters ) );
|
258 |
if ( ! $html ) {
|
259 |
return '';
|
260 |
}
|
@@ -272,19 +325,19 @@ class Vine implements ShortcodeInterface
|
|
272 |
/**
|
273 |
* Construct a cache key for the oEmbed response. Account for query parameters needing to bust cache
|
274 |
*
|
275 |
-
* @since
|
276 |
*
|
277 |
-
* @param
|
|
|
278 |
*
|
279 |
* @return string cache key
|
280 |
*/
|
281 |
-
public static function
|
282 |
{
|
283 |
-
if ( ! (
|
284 |
return '';
|
285 |
}
|
286 |
-
|
287 |
-
$key_pieces = array( static::SHORTCODE_TAG, $query_parameters['id'] );
|
288 |
|
289 |
if ( isset( $query_parameters['maxwidth'] ) && $query_parameters['maxwidth'] ) {
|
290 |
$key_pieces[] = 'w' . $query_parameters['maxwidth'];
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Embeds;
|
27 |
|
28 |
/**
|
29 |
* Display a Vine
|
30 |
*
|
31 |
+
* @since 2.0.0
|
32 |
*/
|
33 |
+
class Vine implements \Twitter\WordPress\Shortcodes\ShortcodeInterface
|
34 |
{
|
35 |
+
use \Twitter\WordPress\Shortcodes\OEmbedTrait;
|
36 |
|
37 |
/**
|
38 |
* Shortcode tag to be matched
|
39 |
*
|
40 |
+
* @since 2.0.0
|
41 |
*
|
42 |
* @type string
|
43 |
*/
|
46 |
/**
|
47 |
* HTML class to be used in div wrapper
|
48 |
*
|
49 |
+
* @since 2.0.0
|
50 |
*
|
51 |
* @type string
|
52 |
*/
|
55 |
/**
|
56 |
* Regex used to match a Vine in text
|
57 |
*
|
58 |
+
* @since 2.0.0
|
59 |
*
|
60 |
* @type string
|
61 |
*/
|
62 |
const URL_REGEX = '#https?://vine\.co/v/([a-z0-9]+)\/?#i';
|
63 |
|
64 |
/**
|
65 |
+
* The oEmbed regex registered by WordPress Core since 4.1
|
66 |
*
|
67 |
+
* @since 2.0.0
|
68 |
*
|
69 |
* @type string
|
70 |
*/
|
73 |
/**
|
74 |
* Base URL used to reconstruct a Vine URL
|
75 |
*
|
76 |
+
* @since 2.0.0
|
77 |
*
|
78 |
* @type string
|
79 |
*/
|
82 |
/**
|
83 |
* PHP class to use for fetching oEmbed data
|
84 |
*
|
85 |
+
* @since 2.0.0
|
86 |
*
|
87 |
* @type string
|
88 |
*/
|
91 |
/**
|
92 |
* Relative path for the oEmbed API relative to Vine base path
|
93 |
*
|
94 |
+
* @since 2.0.0
|
95 |
*
|
96 |
* @type string
|
97 |
*/
|
100 |
/**
|
101 |
* Accepted shortcode attributes and their default values
|
102 |
*
|
103 |
+
* @since 2.0.0
|
104 |
*
|
105 |
* @type array
|
106 |
*/
|
109 |
/**
|
110 |
* Attach handlers for Vine
|
111 |
*
|
112 |
+
* @since 2.0.0
|
113 |
*
|
114 |
* @return void
|
115 |
*/
|
143 |
/**
|
144 |
* Reference the feature by name
|
145 |
*
|
146 |
+
* @since 2.0.0
|
147 |
*
|
148 |
* @return string translated feature name
|
149 |
*/
|
155 |
/**
|
156 |
* Describe shortcode for Shortcake UI
|
157 |
*
|
158 |
+
* @since 2.0.0
|
159 |
*
|
160 |
+
* @link https://github.com/wp-shortcake/shortcake Shortcake UI
|
161 |
*
|
162 |
* @return void
|
163 |
*/
|
191 |
/**
|
192 |
* Handle a URL matched by a embed handler
|
193 |
*
|
194 |
+
* @since 2.0.0
|
195 |
*
|
196 |
+
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
|
|
|
|
|
|
197 |
*
|
198 |
* @return string HTML markup for the Vine or an empty string if requirements not met
|
199 |
*/
|
200 |
+
public static function linkHandler( $matches )
|
201 |
{
|
202 |
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] ) ) {
|
203 |
return '';
|
207 |
}
|
208 |
|
209 |
/**
|
210 |
+
* Shortcode allowed attributes and default values
|
|
|
|
|
211 |
*
|
212 |
+
* @since 2.0.0
|
|
|
|
|
|
|
|
|
213 |
*
|
214 |
+
* @return array shortcode allowed attributes and default values
|
215 |
*/
|
216 |
+
public static function getShortcodeDefaults()
|
217 |
{
|
218 |
+
return static::$SHORTCODE_DEFAULTS;
|
219 |
+
}
|
220 |
|
221 |
+
/**
|
222 |
+
* Process shortcode attributes received from the shortcode API
|
223 |
+
*
|
224 |
+
* @since 2.0.0
|
225 |
+
*
|
226 |
+
* @link https://codex.wordpress.org/Shortcode_API Shortcode API
|
227 |
+
*
|
228 |
+
* @param array $attributes associative array of shortcode attributes, usually from the Shortcode API
|
229 |
+
*
|
230 |
+
* @return array array processed by shortcode_atts, prepped for Tweet object
|
231 |
+
*/
|
232 |
+
public static function getShortcodeAttributes( $attributes )
|
233 |
+
{
|
234 |
$options = shortcode_atts(
|
235 |
+
static::getShortcodeDefaults(),
|
236 |
$attributes,
|
237 |
static::SHORTCODE_TAG
|
238 |
);
|
239 |
|
240 |
+
if ( ! is_array( $options ) || empty( $options ) ) {
|
241 |
+
return array();
|
|
|
242 |
}
|
243 |
|
244 |
+
if ( isset( $options['id'] ) ) {
|
245 |
+
$options['id'] = trim( $options['id'] );
|
246 |
+
}
|
247 |
|
248 |
+
$options = \Twitter\WordPress\Shortcodes\Helpers\Attributes::positiveIntegerOption(
|
249 |
+
$options,
|
250 |
+
array( 'width' )
|
251 |
+
);
|
252 |
+
|
253 |
+
$width = 0;
|
254 |
+
if ( isset( $options['width'] ) ) {
|
255 |
+
$width = absint( $options['width'] );
|
256 |
+
if ( $width < 100 && isset( $content_width ) ) {
|
257 |
+
$width = absint( $content_width );
|
258 |
+
}
|
259 |
}
|
260 |
if ( $width > 100 ) {
|
261 |
// reset max_width to max value supported by Vine
|
263 |
if ( $width > 600 ) {
|
264 |
$width = 600;
|
265 |
}
|
266 |
+
$options['width'] = $width;
|
267 |
}
|
268 |
|
269 |
+
return $options;
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Handle shortcode macro
|
274 |
+
*
|
275 |
+
* @since 2.0.0
|
276 |
+
*
|
277 |
+
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
278 |
+
* @type string|int attribute name or positional int
|
279 |
+
* @type mixed shortcode value
|
280 |
+
* }
|
281 |
+
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
282 |
+
*
|
283 |
+
* @return string HTML markup. empty string if parameter requirement not met or no collection info found
|
284 |
+
*/
|
285 |
+
public static function shortcodeHandler( $attributes, $content = '' )
|
286 |
+
{
|
287 |
+
$options = static::getShortcodeAttributes( $attributes );
|
288 |
+
|
289 |
+
if ( ! ( isset( $options['id'] ) && $options['id'] ) ) {
|
290 |
+
return '';
|
291 |
+
}
|
292 |
+
|
293 |
+
$vine = \Twitter\Widgets\Embeds\Vine::fromArray( $options );
|
294 |
+
|
295 |
+
if ( ! $vine->getWidth() ) {
|
296 |
+
// set to content width of the current theme
|
297 |
+
// @see https://codex.wordpress.org/Content_Width
|
298 |
+
if ( isset( $GLOBALS['content_width'] ) && $GLOBALS['content_width'] ) {
|
299 |
+
$vine->setWidth( absint( $GLOBALS['content_width'] ) );
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
$query_parameters = $vine->toOEmbedParameterArray();
|
304 |
+
$query_parameters = array_merge( static::getBaseOEmbedParams(), $query_parameters );
|
305 |
+
|
306 |
+
// not used by Vine
|
307 |
+
unset( $query_parameters['lang'] );
|
308 |
+
|
309 |
// fetch HTML markup from Vine oEmbed endpoint for the given parameters
|
310 |
+
$html = trim( static::getOEmbedMarkup( $query_parameters, static::getOEmbedCacheKey( $options['id'], $query_parameters ) ) );
|
311 |
if ( ! $html ) {
|
312 |
return '';
|
313 |
}
|
325 |
/**
|
326 |
* Construct a cache key for the oEmbed response. Account for query parameters needing to bust cache
|
327 |
*
|
328 |
+
* @since 2.0.0
|
329 |
*
|
330 |
+
* @param string $id Vine ID
|
331 |
+
* @param array $query_parameters oEmbed API query parameters
|
332 |
*
|
333 |
* @return string cache key
|
334 |
*/
|
335 |
+
public static function getOEmbedCacheKey( $id, array $query_parameters )
|
336 |
{
|
337 |
+
if ( ! ( is_string( $id ) && $id ) ) {
|
338 |
return '';
|
339 |
}
|
340 |
+
$key_pieces = array( static::SHORTCODE_TAG, $id );
|
|
|
341 |
|
342 |
if ( isset( $query_parameters['maxwidth'] ) && $query_parameters['maxwidth'] ) {
|
343 |
$key_pieces[] = 'w' . $query_parameters['maxwidth'];
|
src/Twitter/WordPress/Shortcodes/Follow.php
DELETED
@@ -1,293 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
The MIT License (MIT)
|
4 |
-
|
5 |
-
Copyright (c) 2015 Twitter Inc.
|
6 |
-
|
7 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
-
of this software and associated documentation files (the "Software"), to deal
|
9 |
-
in the Software without restriction, including without limitation the rights
|
10 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
-
copies of the Software, and to permit persons to whom the Software is
|
12 |
-
furnished to do so, subject to the following conditions:
|
13 |
-
|
14 |
-
The above copyright notice and this permission notice shall be included in
|
15 |
-
all copies or substantial portions of the Software.
|
16 |
-
|
17 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
-
THE SOFTWARE.
|
24 |
-
*/
|
25 |
-
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Display a Follow button
|
30 |
-
*
|
31 |
-
* @since 1.0.0
|
32 |
-
*/
|
33 |
-
class Follow implements ShortcodeInterface
|
34 |
-
{
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Shortcode tag to be matched
|
38 |
-
*
|
39 |
-
* @since 1.0.0
|
40 |
-
*
|
41 |
-
* @type string
|
42 |
-
*/
|
43 |
-
const SHORTCODE_TAG = 'twitter_follow';
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Regex used to match a Twitter profile URL in text
|
47 |
-
*
|
48 |
-
* @since 1.3.0
|
49 |
-
*
|
50 |
-
* @type string
|
51 |
-
*/
|
52 |
-
const URL_REGEX = '#^https://twitter\.com/([a-z0-9_]{1,20})$#i';
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Accepted shortcode attributes and their default values
|
56 |
-
*
|
57 |
-
* @since 1.0.0
|
58 |
-
*
|
59 |
-
* @type array
|
60 |
-
*/
|
61 |
-
public static $SHORTCODE_DEFAULTS = array( 'screen_name' => '', 'show_count' => true, 'show_screen_name' => true, 'size' => 'medium' );
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Register shortcode macro and handler
|
65 |
-
*
|
66 |
-
* @since 1.0.0
|
67 |
-
*
|
68 |
-
* @return void
|
69 |
-
*/
|
70 |
-
public static function init()
|
71 |
-
{
|
72 |
-
$classname = get_called_class();
|
73 |
-
|
74 |
-
add_shortcode( static::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
75 |
-
|
76 |
-
// convert a URL into the shortcode equivalent
|
77 |
-
wp_embed_register_handler(
|
78 |
-
static::SHORTCODE_TAG,
|
79 |
-
static::URL_REGEX,
|
80 |
-
array( $classname, 'linkHandler' ),
|
81 |
-
1
|
82 |
-
);
|
83 |
-
|
84 |
-
// Shortcode UI, if supported
|
85 |
-
add_action(
|
86 |
-
'register_shortcode_ui',
|
87 |
-
array( $classname, 'shortcodeUI' ),
|
88 |
-
5,
|
89 |
-
0
|
90 |
-
);
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Describe shortcode for Shortcake UI
|
95 |
-
*
|
96 |
-
* @since 1.1.0
|
97 |
-
*
|
98 |
-
* @link https://github.com/fusioneng/Shortcake Shortcake UI
|
99 |
-
*
|
100 |
-
* @return void
|
101 |
-
*/
|
102 |
-
public static function shortcodeUI()
|
103 |
-
{
|
104 |
-
// Shortcake required
|
105 |
-
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
106 |
-
return;
|
107 |
-
}
|
108 |
-
|
109 |
-
shortcode_ui_register_for_shortcode(
|
110 |
-
static::SHORTCODE_TAG,
|
111 |
-
array(
|
112 |
-
'label' => esc_html( __( 'Follow Button', 'twitter' ) ),
|
113 |
-
'listItemImage' => 'dashicons-twitter',
|
114 |
-
'attrs' => array(
|
115 |
-
array(
|
116 |
-
'attr' => 'screen_name',
|
117 |
-
'label' => esc_html( __( 'Twitter @username', 'twitter' ) ),
|
118 |
-
'type' => 'text',
|
119 |
-
'meta' => array(
|
120 |
-
'placeholder' => 'WordPress',
|
121 |
-
'pattern' => '[A-Za-z0-9_]{1,20}',
|
122 |
-
),
|
123 |
-
),
|
124 |
-
array(
|
125 |
-
'attr' => 'size',
|
126 |
-
'label' => esc_html( __( 'Button size:', 'twitter' ) ),
|
127 |
-
'type' => 'radio',
|
128 |
-
'value' => '',
|
129 |
-
'options' => array(
|
130 |
-
'' => esc_html( _x( 'medium', 'medium size button', 'twitter' ) ),
|
131 |
-
'large' => esc_html( _x( 'large', 'large size button', 'twitter' ) ),
|
132 |
-
),
|
133 |
-
),
|
134 |
-
),
|
135 |
-
)
|
136 |
-
);
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Handle a URL matched by a embed handler
|
141 |
-
*
|
142 |
-
* @since 1.3.1
|
143 |
-
*
|
144 |
-
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
145 |
-
* @param array $attr Embed attributes. Not used.
|
146 |
-
* @param string $url The original URL that was matched by the regex. Not used.
|
147 |
-
* @param array $rawattr The original unmodified attributes. Not used.
|
148 |
-
*
|
149 |
-
* @return string HTML markup for the follow button or an empty string if requirements not met
|
150 |
-
*/
|
151 |
-
public static function linkHandler( $matches, $attr, $url, $rawattr )
|
152 |
-
{
|
153 |
-
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] ) ) {
|
154 |
-
return '';
|
155 |
-
}
|
156 |
-
|
157 |
-
return static::shortcodeHandler( array( 'screen_name' => $matches[1] ) );
|
158 |
-
}
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Clean up provided shortcode values
|
162 |
-
*
|
163 |
-
* Be liberal in what we accept in shortcode syntax before constructing a Follow button
|
164 |
-
*
|
165 |
-
* @since 1.0.0
|
166 |
-
*
|
167 |
-
* @param array $attributes provided shortcode attributes {
|
168 |
-
* @type string shortcode attribute name
|
169 |
-
* @type mixed shortcode attribute value
|
170 |
-
* }
|
171 |
-
*
|
172 |
-
* @return array simplified shortcode values with defaults removed {
|
173 |
-
* @type string shortcode attribute name
|
174 |
-
* @type bool|string shortcode attribute value
|
175 |
-
* }
|
176 |
-
*/
|
177 |
-
public static function sanitizeShortcodeParameters( $attributes = array() )
|
178 |
-
{
|
179 |
-
if ( ! is_array( $attributes ) ) {
|
180 |
-
return array();
|
181 |
-
}
|
182 |
-
|
183 |
-
$options = array();
|
184 |
-
|
185 |
-
if ( isset( $attributes['screen_name'] ) ) {
|
186 |
-
$screen_name = \Twitter\Helpers\Validators\ScreenName::trim( $attributes['screen_name'] );
|
187 |
-
if ( $screen_name ) {
|
188 |
-
$options['screen_name'] = $screen_name;
|
189 |
-
}
|
190 |
-
unset( $screen_name );
|
191 |
-
}
|
192 |
-
|
193 |
-
foreach ( array( 'show_count', 'show_screen_name' ) as $falsey_option ) {
|
194 |
-
// check for falsey values passed to shortcode
|
195 |
-
if ( isset( $attributes[ $falsey_option ] ) ) {
|
196 |
-
if ( false === $attributes[ $falsey_option ] || '0' == $attributes[ $falsey_option ] || ( is_string( $attributes[ $falsey_option ] ) && in_array( strtolower( $attributes[ $falsey_option ] ), array( 'false', 'no', 'off' ) ) ) ) {
|
197 |
-
$options[ $falsey_option ] = false;
|
198 |
-
}
|
199 |
-
}
|
200 |
-
}
|
201 |
-
|
202 |
-
// large is the only option
|
203 |
-
if ( isset( $attributes['size'] ) ) {
|
204 |
-
if ( is_string( $attributes['size'] ) && in_array( strtolower( $attributes['size'] ), array( 'large', 'l' ) ) ) {
|
205 |
-
$options['size'] = 'large';
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
return $options;
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* Get the Twitter screen name of the author of the current post
|
214 |
-
*
|
215 |
-
* @since 1.0.0
|
216 |
-
*
|
217 |
-
* @return string Twitter screen name or empty if no screen name stored
|
218 |
-
*/
|
219 |
-
public static function getScreenName()
|
220 |
-
{
|
221 |
-
if ( ! in_the_loop() ) {
|
222 |
-
return '';
|
223 |
-
}
|
224 |
-
|
225 |
-
$screen_name = \Twitter\WordPress\User\Meta::getTwitterUsername( get_the_author_meta( 'ID' ) );
|
226 |
-
if ( ! $screen_name ) {
|
227 |
-
return '';
|
228 |
-
}
|
229 |
-
|
230 |
-
return $screen_name;
|
231 |
-
}
|
232 |
-
|
233 |
-
/**
|
234 |
-
* Handle shortcode macro
|
235 |
-
*
|
236 |
-
* @since 1.0.0
|
237 |
-
*
|
238 |
-
* @param array $attributes shortcode attributes
|
239 |
-
* @param string $content shortcode content. no effect
|
240 |
-
*
|
241 |
-
* @return string Follow button HTML or empty string
|
242 |
-
*/
|
243 |
-
public static function shortcodeHandler( $attributes, $content = '' )
|
244 |
-
{
|
245 |
-
// clean up attribute to shortcode option mappings before passing to filter
|
246 |
-
// apply the same filter as shortcode_atts
|
247 |
-
/** This filter is documented in wp-includes/shortcodes.php */
|
248 |
-
$options = apply_filters(
|
249 |
-
'shortcode_atts_' . self::SHORTCODE_TAG,
|
250 |
-
array_merge(
|
251 |
-
static::$SHORTCODE_DEFAULTS,
|
252 |
-
static::sanitizeShortcodeParameters( (array) $attributes )
|
253 |
-
),
|
254 |
-
static::$SHORTCODE_DEFAULTS,
|
255 |
-
$attributes
|
256 |
-
);
|
257 |
-
|
258 |
-
$screen_name = '';
|
259 |
-
if ( isset( $options['screen_name'] ) ) {
|
260 |
-
$screen_name = $options['screen_name'];
|
261 |
-
unset( $options['screen_name'] );
|
262 |
-
}
|
263 |
-
if ( ! $screen_name ) {
|
264 |
-
$screen_name = static::getScreenName();
|
265 |
-
// follow target required
|
266 |
-
if ( ! $screen_name ) {
|
267 |
-
return '';
|
268 |
-
}
|
269 |
-
}
|
270 |
-
|
271 |
-
// update the options array with the Follow screen name
|
272 |
-
$options['screen_name'] = $screen_name;
|
273 |
-
|
274 |
-
$follow = \Twitter\Widgets\FollowButton::fromArray( $options );
|
275 |
-
if ( ! $follow ) {
|
276 |
-
return '';
|
277 |
-
}
|
278 |
-
|
279 |
-
$html = $follow->toHTML( _x( 'Follow %s', 'Follow a Twitter user', 'twitter' ), '\Twitter\WordPress\Helpers\HTMLBuilder' );
|
280 |
-
if ( ! $html ) {
|
281 |
-
return '';
|
282 |
-
}
|
283 |
-
|
284 |
-
$html = '<div class="twitter-follow">' . $html . '</div>';
|
285 |
-
|
286 |
-
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
287 |
-
if ( $inline_js ) {
|
288 |
-
return $html . $inline_js;
|
289 |
-
}
|
290 |
-
|
291 |
-
return $html;
|
292 |
-
}
|
293 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/Twitter/WordPress/Shortcodes/Helpers/Attributes.php
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Shortcodes\Helpers;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Process and convert shortcode attributes into their expected PHP types
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
class Attributes
|
34 |
+
{
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Accepted string attribute values for a true boolean
|
38 |
+
*
|
39 |
+
* @since 2.0.0
|
40 |
+
*
|
41 |
+
* type array
|
42 |
+
*/
|
43 |
+
public static $TRUTHY_STRING_VALUES = array(
|
44 |
+
'true' => true,
|
45 |
+
'yes' => true,
|
46 |
+
'on' => true,
|
47 |
+
);
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Accepted string attribute values for a false boolean
|
51 |
+
*
|
52 |
+
* @since 2.0.0
|
53 |
+
*
|
54 |
+
* type array
|
55 |
+
*/
|
56 |
+
public static $FALSEY_STRING_VALUES = array(
|
57 |
+
'false' => false,
|
58 |
+
'no' => false,
|
59 |
+
'off' => false,
|
60 |
+
);
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Convert shortcode attribute value to boolean
|
64 |
+
*
|
65 |
+
* @since 2.0.0
|
66 |
+
*
|
67 |
+
* @param array $attributes parsed shortcode attributes
|
68 |
+
* @param array $bool_keys array keys of expected truthy or falsey values
|
69 |
+
*
|
70 |
+
* @return array $attributes shortcode attributes with possible type conversions or removed keys
|
71 |
+
*/
|
72 |
+
public static function booleanOption( array $attributes, $bool_keys )
|
73 |
+
{
|
74 |
+
if ( ! is_array( $bool_keys ) || empty( $bool_keys ) ) {
|
75 |
+
return $attributes;
|
76 |
+
}
|
77 |
+
|
78 |
+
foreach ( $bool_keys as $bool_key ) {
|
79 |
+
if ( ! isset( $attributes[ $bool_key ] ) || is_bool( $attributes[ $bool_key ] ) ) {
|
80 |
+
continue;
|
81 |
+
}
|
82 |
+
|
83 |
+
// purposely allow int, string, or truthy/falsey loose match
|
84 |
+
// @codingStandardsIgnoreStart WordPress.PHP.StrictComparisons.LooseComparison
|
85 |
+
if ( '1' == $attributes[ $bool_key ] || (is_string( $attributes[ $bool_key ] ) && isset( static::$TRUTHY_STRING_VALUES[ strtolower( $attributes[ $bool_key ] ) ] ) ) ) {
|
86 |
+
$attributes[ $bool_key ] = true;
|
87 |
+
} else if ( '0' == $attributes[ $bool_key ] || (is_string( $attributes[ $bool_key ] ) && isset( static::$FALSEY_STRING_VALUES[ strtolower( $attributes[ $bool_key ] ) ] )) ) {
|
88 |
+
$attributes[ $bool_key ] = false;
|
89 |
+
} else {
|
90 |
+
unset( $attributes[ $bool_key ] );
|
91 |
+
}
|
92 |
+
// @codingStandardsIgnoreEnd WordPress.PHP.StrictComparisons.LooseComparison
|
93 |
+
}
|
94 |
+
|
95 |
+
return $attributes;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Convert shortcode attribute value to positive integer
|
100 |
+
*
|
101 |
+
* @since 2.0.0
|
102 |
+
*
|
103 |
+
* @param array $attributes parsed shortcode attributes
|
104 |
+
* @param array $int_keys array keys of expected positive integer values
|
105 |
+
*
|
106 |
+
* @return array $attributes shortcode attributes with possible type conversions or removed keys
|
107 |
+
*/
|
108 |
+
public static function positiveIntegerOption( array $attributes, $int_keys )
|
109 |
+
{
|
110 |
+
if ( ! is_array( $int_keys ) || empty( $int_keys ) ) {
|
111 |
+
return $attributes;
|
112 |
+
}
|
113 |
+
|
114 |
+
foreach ( $int_keys as $int_key ) {
|
115 |
+
if ( ! isset( $attributes[ $int_key ] ) ) {
|
116 |
+
continue;
|
117 |
+
}
|
118 |
+
|
119 |
+
$attributes[ $int_key ] = absint( $attributes[ $int_key ] );
|
120 |
+
if ( 0 === $attributes[ $int_key ] ) {
|
121 |
+
unset( $attributes[ $int_key ] );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
return $attributes;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Remove whitespace and convert string attribute to lowercase ASCII characters
|
130 |
+
*
|
131 |
+
* @since 2.0.0
|
132 |
+
*
|
133 |
+
* @param array $attributes parsed shortcode attributes
|
134 |
+
* @param array $string_keys array keys of expected positive integer values
|
135 |
+
*
|
136 |
+
* @return array $attributes shortcode attributes with possible type conversions, values to lowercase, or removed keys
|
137 |
+
*/
|
138 |
+
public static function lowercaseStringOption( array $attributes, $string_keys )
|
139 |
+
{
|
140 |
+
if ( ! is_array( $string_keys ) || empty( $string_keys ) ) {
|
141 |
+
return $attributes;
|
142 |
+
}
|
143 |
+
|
144 |
+
foreach ( $string_keys as $string_key ) {
|
145 |
+
if ( ! isset( $attributes[ $string_key ] ) ) {
|
146 |
+
continue;
|
147 |
+
}
|
148 |
+
|
149 |
+
$attributes[ $string_key ] = strtolower( trim( $attributes[ $string_key ] ) );
|
150 |
+
if ( ! $attributes[ $string_key ] ) {
|
151 |
+
unset( $attributes[ $string_key ] );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
return $attributes;
|
156 |
+
}
|
157 |
+
}
|
src/Twitter/WordPress/Shortcodes/OEmbedTrait.php
CHANGED
@@ -37,23 +37,15 @@ trait OEmbedTrait
|
|
37 |
*
|
38 |
* @since 1.3.0
|
39 |
*
|
40 |
-
* @param string $snowflake_id object identifier
|
41 |
-
*
|
42 |
* @return array associative array of query parameters ready for http_build_query {
|
43 |
* @type string query parameter name
|
44 |
* @type string|bool query parameter value
|
45 |
* }
|
46 |
*/
|
47 |
-
public static function getBaseOEmbedParams(
|
48 |
{
|
49 |
-
$snowflake_id = trim( $snowflake_id );
|
50 |
-
if ( ! $snowflake_id ) {
|
51 |
-
return array();
|
52 |
-
}
|
53 |
-
|
54 |
// omit JavaScript. enqueue separately
|
55 |
$query_parameters = array(
|
56 |
-
'id' => $snowflake_id,
|
57 |
'omit_script' => true,
|
58 |
);
|
59 |
|
@@ -71,15 +63,14 @@ trait OEmbedTrait
|
|
71 |
*
|
72 |
* @since 1.3.0
|
73 |
*
|
74 |
-
* @param array
|
|
|
75 |
*
|
76 |
-
* @todo make this not mocked
|
77 |
* @return string HTML markup returned by the oEmbed endpoint
|
78 |
*/
|
79 |
-
public static function getOEmbedMarkup( $query_parameters )
|
80 |
{
|
81 |
-
$cache_key
|
82 |
-
if ( ! $cache_key ) {
|
83 |
return '';
|
84 |
}
|
85 |
|
@@ -98,23 +89,26 @@ trait OEmbedTrait
|
|
98 |
return '';
|
99 |
}
|
100 |
|
101 |
-
if (
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
105 |
}
|
106 |
|
107 |
$allowed_resource_types = array( 'rich' => true, 'video' => true );
|
108 |
$ttl = DAY_IN_SECONDS;
|
109 |
|
110 |
$oembed_response = $oembed_api_class::getJSON( static::OEMBED_API_ENDPOINT, $query_parameters );
|
111 |
-
if ( ! (
|
112 |
-
$oembed_response
|
113 |
-
isset( $oembed_response->type )
|
114 |
-
isset( $
|
115 |
-
|
116 |
-
|
117 |
-
) ) {
|
118 |
// do not rerequest errors with every page request
|
119 |
set_transient( $cache_key, ' ', $ttl );
|
120 |
return '';
|
37 |
*
|
38 |
* @since 1.3.0
|
39 |
*
|
|
|
|
|
40 |
* @return array associative array of query parameters ready for http_build_query {
|
41 |
* @type string query parameter name
|
42 |
* @type string|bool query parameter value
|
43 |
* }
|
44 |
*/
|
45 |
+
public static function getBaseOEmbedParams()
|
46 |
{
|
|
|
|
|
|
|
|
|
|
|
47 |
// omit JavaScript. enqueue separately
|
48 |
$query_parameters = array(
|
|
|
49 |
'omit_script' => true,
|
50 |
);
|
51 |
|
63 |
*
|
64 |
* @since 1.3.0
|
65 |
*
|
66 |
+
* @param array $query_parameters query parameters to be passed to the oEmbed endpoint
|
67 |
+
* @param string $cache_key key to retrieve and store HTML values for the given configuration
|
68 |
*
|
|
|
69 |
* @return string HTML markup returned by the oEmbed endpoint
|
70 |
*/
|
71 |
+
public static function getOEmbedMarkup( $query_parameters, $cache_key )
|
72 |
{
|
73 |
+
if ( ! (is_string( $cache_key ) && $cache_key ) ) {
|
|
|
74 |
return '';
|
75 |
}
|
76 |
|
89 |
return '';
|
90 |
}
|
91 |
|
92 |
+
if ( ! isset( $query_parameters['url'] ) ) {
|
93 |
+
if ( defined( $classname . '::BASE_URL' ) && isset( $query_parameters['id'] ) ) {
|
94 |
+
// convert ID to full URL to allow more flexibility for oEmbed endpoint
|
95 |
+
$query_parameters['url'] = static::BASE_URL . $query_parameters['id'];
|
96 |
+
unset( $query_parameters['id'] );
|
97 |
+
} else {
|
98 |
+
return '';
|
99 |
+
}
|
100 |
}
|
101 |
|
102 |
$allowed_resource_types = array( 'rich' => true, 'video' => true );
|
103 |
$ttl = DAY_IN_SECONDS;
|
104 |
|
105 |
$oembed_response = $oembed_api_class::getJSON( static::OEMBED_API_ENDPOINT, $query_parameters );
|
106 |
+
if ( ! ($oembed_response
|
107 |
+
&& isset( $oembed_response->type )
|
108 |
+
&& isset( $allowed_resource_types[ $oembed_response->type ] )
|
109 |
+
&& isset( $oembed_response->html )
|
110 |
+
&& $oembed_response->html )
|
111 |
+
) {
|
|
|
112 |
// do not rerequest errors with every page request
|
113 |
set_transient( $cache_key, ' ', $ttl );
|
114 |
return '';
|
src/Twitter/WordPress/Shortcodes/PublishOEmbedEndpoint.php
CHANGED
@@ -30,7 +30,8 @@ namespace Twitter\WordPress\Shortcodes;
|
|
30 |
*
|
31 |
* @since 1.5.0
|
32 |
*/
|
33 |
-
interface PublishOEmbedEndpoint
|
|
|
34 |
/**
|
35 |
* PHP class to use for fetching oEmbed data
|
36 |
*
|
@@ -48,4 +49,16 @@ interface PublishOEmbedEndpoint {
|
|
48 |
* @type string
|
49 |
*/
|
50 |
const OEMBED_API_ENDPOINT = 'oembed';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
30 |
*
|
31 |
* @since 1.5.0
|
32 |
*/
|
33 |
+
interface PublishOEmbedEndpoint
|
34 |
+
{
|
35 |
/**
|
36 |
* PHP class to use for fetching oEmbed data
|
37 |
*
|
49 |
* @type string
|
50 |
*/
|
51 |
const OEMBED_API_ENDPOINT = 'oembed';
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Create a unique cache key to represent the requested object
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*
|
58 |
+
* @param string $id datasource identifier
|
59 |
+
* @param array $query_parameters oEmbed-compatible API parameters possibly affecting display
|
60 |
+
*
|
61 |
+
* @return string cache key
|
62 |
+
*/
|
63 |
+
public static function getOEmbedCacheKey( $id, array $query_parameters );
|
64 |
}
|
src/Twitter/WordPress/Shortcodes/ShortcodeInterface.php
CHANGED
@@ -46,7 +46,7 @@ interface ShortcodeInterface
|
|
46 |
*
|
47 |
* @since 1.3.0
|
48 |
*
|
49 |
-
* @
|
50 |
*
|
51 |
* @return void
|
52 |
*/
|
@@ -63,4 +63,25 @@ interface ShortcodeInterface
|
|
63 |
* @return string HTML result or empty string. JavaScript dependencies should be enqueued or loaded in the returned HTML
|
64 |
*/
|
65 |
public static function shortcodeHandler( $attributes, $content );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
46 |
*
|
47 |
* @since 1.3.0
|
48 |
*
|
49 |
+
* @see https://github.com/wp-shortcake/shortcake Shortcake UI
|
50 |
*
|
51 |
* @return void
|
52 |
*/
|
63 |
* @return string HTML result or empty string. JavaScript dependencies should be enqueued or loaded in the returned HTML
|
64 |
*/
|
65 |
public static function shortcodeHandler( $attributes, $content );
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Process and clean supplied attributes
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*
|
72 |
+
* @param array $attributes array of attributes passed by WordPress shortcode API
|
73 |
+
*
|
74 |
+
* @return array processed attriutes prepped
|
75 |
+
*/
|
76 |
+
public static function getShortcodeAttributes( $attributes );
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Describe the shortcode
|
80 |
+
*
|
81 |
+
* Used by shortcake UI to list available shortcodes.
|
82 |
+
* May be used by a widget or other visuals to describe a feature
|
83 |
+
*
|
84 |
+
* @return string Translated feature name
|
85 |
+
*/
|
86 |
+
public static function featureName();
|
87 |
}
|
src/Twitter/WordPress/Shortcodes/TweetGrid.php
DELETED
@@ -1,288 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
The MIT License (MIT)
|
4 |
-
|
5 |
-
Copyright (c) 2015 Twitter Inc.
|
6 |
-
|
7 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
-
of this software and associated documentation files (the "Software"), to deal
|
9 |
-
in the Software without restriction, including without limitation the rights
|
10 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
-
copies of the Software, and to permit persons to whom the Software is
|
12 |
-
furnished to do so, subject to the following conditions:
|
13 |
-
|
14 |
-
The above copyright notice and this permission notice shall be included in
|
15 |
-
all copies or substantial portions of the Software.
|
16 |
-
|
17 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
-
THE SOFTWARE.
|
24 |
-
*/
|
25 |
-
|
26 |
-
namespace Twitter\WordPress\Shortcodes;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Display a grid of Tweets
|
30 |
-
*
|
31 |
-
* @since 1.3.0
|
32 |
-
*/
|
33 |
-
class TweetGrid implements ShortcodeInterface, PublishOEmbedEndpoint
|
34 |
-
{
|
35 |
-
use OEmbedTrait;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Shortcode tag to be matched
|
39 |
-
*
|
40 |
-
* @since 1.3.0
|
41 |
-
*
|
42 |
-
* @type string
|
43 |
-
*/
|
44 |
-
const SHORTCODE_TAG = 'twitter_grid';
|
45 |
-
|
46 |
-
/**
|
47 |
-
* oEmbed regex registered by WordPress Core
|
48 |
-
*
|
49 |
-
* @since 1.5.0
|
50 |
-
*
|
51 |
-
* @type string
|
52 |
-
*/
|
53 |
-
const OEMBED_CORE_REGEX = '#https?://(www\.)?twitter\.com/.+?/timelines/.*#i';
|
54 |
-
|
55 |
-
/**
|
56 |
-
* HTML class to be used in div wrapper
|
57 |
-
*
|
58 |
-
* @since 1.3.0
|
59 |
-
*
|
60 |
-
* @type string
|
61 |
-
*/
|
62 |
-
const HTML_CLASS = 'twitter-grid';
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Regex used to match a Collection in text
|
66 |
-
*
|
67 |
-
* @since 1.3.0
|
68 |
-
*
|
69 |
-
* @type string
|
70 |
-
*/
|
71 |
-
const URL_REGEX = '#^https://twitter\.com/[a-z0-9_]{1,20}/timelines/([0-9]+)#i';
|
72 |
-
|
73 |
-
/**
|
74 |
-
* Base URL used to reconstruct a Collection URL
|
75 |
-
*
|
76 |
-
* @since 1.3.0
|
77 |
-
*
|
78 |
-
* @type string
|
79 |
-
*/
|
80 |
-
const BASE_URL = 'https://twitter.com/_/timelines/';
|
81 |
-
|
82 |
-
/**
|
83 |
-
* Accepted shortcode attributes and their default values
|
84 |
-
*
|
85 |
-
* @since 1.3.0
|
86 |
-
*
|
87 |
-
* @type array
|
88 |
-
*/
|
89 |
-
public static $SHORTCODE_DEFAULTS = array( 'id' => '', 'limit' => 20 );
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Attach handlers for Twitter Grid
|
93 |
-
*
|
94 |
-
* @since 1.3.0
|
95 |
-
*
|
96 |
-
* @return void
|
97 |
-
*/
|
98 |
-
public static function init()
|
99 |
-
{
|
100 |
-
$classname = get_called_class();
|
101 |
-
|
102 |
-
// register our shortcode and its handler
|
103 |
-
add_shortcode( static::SHORTCODE_TAG, array( $classname, 'shortcodeHandler' ) );
|
104 |
-
|
105 |
-
// Shortcode UI, if supported
|
106 |
-
add_action(
|
107 |
-
'register_shortcode_ui',
|
108 |
-
array( $classname, 'shortcodeUI' ),
|
109 |
-
5,
|
110 |
-
0
|
111 |
-
);
|
112 |
-
|
113 |
-
if ( ! is_admin() ) {
|
114 |
-
// unhook the WordPress Core oEmbed handler
|
115 |
-
wp_oembed_remove_provider( static::OEMBED_CORE_REGEX );
|
116 |
-
|
117 |
-
// convert a URL into the shortcode equivalent
|
118 |
-
wp_embed_register_handler(
|
119 |
-
static::SHORTCODE_TAG,
|
120 |
-
static::URL_REGEX,
|
121 |
-
array( $classname, 'linkHandler' ),
|
122 |
-
1
|
123 |
-
);
|
124 |
-
}
|
125 |
-
}
|
126 |
-
|
127 |
-
/**
|
128 |
-
* Reference the feature by name
|
129 |
-
*
|
130 |
-
* @since 1.3.0
|
131 |
-
*
|
132 |
-
* @return string translated feature name
|
133 |
-
*/
|
134 |
-
public static function featureName()
|
135 |
-
{
|
136 |
-
return _x( 'Tweet Grid', 'Tweets displayed in a grid layout', 'twitter' );
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Describe shortcode for Shortcake UI
|
141 |
-
*
|
142 |
-
* @since 1.3.0
|
143 |
-
*
|
144 |
-
* @link https://github.com/fusioneng/Shortcake Shortcake UI
|
145 |
-
*
|
146 |
-
* @return void
|
147 |
-
*/
|
148 |
-
public static function shortcodeUI()
|
149 |
-
{
|
150 |
-
// Shortcake required
|
151 |
-
if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
|
152 |
-
return;
|
153 |
-
}
|
154 |
-
|
155 |
-
shortcode_ui_register_for_shortcode(
|
156 |
-
static::SHORTCODE_TAG,
|
157 |
-
array(
|
158 |
-
'label' => esc_html( static::featureName() ),
|
159 |
-
'listItemImage' => 'dashicons-twitter',
|
160 |
-
'attrs' => array(
|
161 |
-
array(
|
162 |
-
'attr' => 'id',
|
163 |
-
'label' => 'ID',
|
164 |
-
'type' => 'text',
|
165 |
-
'meta' => array(
|
166 |
-
'required' => true,
|
167 |
-
'pattern' => '[0-9]+',
|
168 |
-
),
|
169 |
-
),
|
170 |
-
array(
|
171 |
-
'attr' => 'limit',
|
172 |
-
'label' => _x( 'Limit', 'Maximum number of items to include', 'twitter' ),
|
173 |
-
'type' => 'number',
|
174 |
-
'value' => static::$SHORTCODE_DEFAULTS['limit'],
|
175 |
-
'meta' => array(
|
176 |
-
'min' => 1,
|
177 |
-
'max' => 20,
|
178 |
-
'step' => 1,
|
179 |
-
),
|
180 |
-
),
|
181 |
-
),
|
182 |
-
)
|
183 |
-
);
|
184 |
-
}
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Handle a URL matched by a embed handler
|
188 |
-
*
|
189 |
-
* @since 1.3.0
|
190 |
-
*
|
191 |
-
* @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
|
192 |
-
* @param array $attr Embed attributes. Not used.
|
193 |
-
* @param string $url The original URL that was matched by the regex. Not used.
|
194 |
-
* @param array $rawattr The original unmodified attributes. Not used.
|
195 |
-
*
|
196 |
-
* @return string HTML markup for the Tweet grid or an empty string if requirements not met
|
197 |
-
*/
|
198 |
-
public static function linkHandler( $matches, $attr, $url, $rawattr )
|
199 |
-
{
|
200 |
-
if ( ! ( is_array( $matches ) && isset( $matches[1] ) && $matches[1] ) ) {
|
201 |
-
return '';
|
202 |
-
}
|
203 |
-
|
204 |
-
return static::shortcodeHandler( array( 'id' => $matches[1] ) );
|
205 |
-
}
|
206 |
-
|
207 |
-
/**
|
208 |
-
* Handle shortcode macro
|
209 |
-
*
|
210 |
-
* @since 1.3.0
|
211 |
-
*
|
212 |
-
* @param array $attributes set of shortcode attribute-value pairs or positional content matching the WordPress shortcode regex {
|
213 |
-
* @type string|int attribute name or positional int
|
214 |
-
* @type mixed shortcode value
|
215 |
-
* }
|
216 |
-
* @param string $content content inside a shortcode macro. no effect on this shortcode
|
217 |
-
*
|
218 |
-
* @return string HTML markup. empty string if parameter requirement not met or no collection info found
|
219 |
-
*/
|
220 |
-
public static function shortcodeHandler( $attributes, $content = '' )
|
221 |
-
{
|
222 |
-
$options = shortcode_atts(
|
223 |
-
static::$SHORTCODE_DEFAULTS,
|
224 |
-
$attributes,
|
225 |
-
static::SHORTCODE_TAG
|
226 |
-
);
|
227 |
-
|
228 |
-
$snowflake_id = trim( $options['id'] );
|
229 |
-
if ( ! $snowflake_id ) {
|
230 |
-
return '';
|
231 |
-
}
|
232 |
-
|
233 |
-
$query_parameters = static::getBaseOEmbedParams( $snowflake_id );
|
234 |
-
if ( isset( $options['limit'] ) ) {
|
235 |
-
$limit = 0;
|
236 |
-
try {
|
237 |
-
$limit = intval( trim( $options['limit'] ), 10 );
|
238 |
-
} catch( Exception $e ) {}
|
239 |
-
if ( $limit > 0 && $limit < 20 ) {
|
240 |
-
$query_parameters['limit'] = $limit;
|
241 |
-
}
|
242 |
-
}
|
243 |
-
|
244 |
-
// fetch HTML markup from Twitter oEmbed endpoint for the given parameters
|
245 |
-
$html = trim( static::getOEmbedMarkup( $query_parameters ) );
|
246 |
-
if ( ! $html ) {
|
247 |
-
return '';
|
248 |
-
}
|
249 |
-
|
250 |
-
$html = '<div class="' . sanitize_html_class( static::HTML_CLASS ) . '">' . $html . '</div>';
|
251 |
-
|
252 |
-
$inline_js = \Twitter\WordPress\JavaScriptLoaders\Widgets::enqueue();
|
253 |
-
if ( $inline_js ) {
|
254 |
-
return $html . $inline_js;
|
255 |
-
}
|
256 |
-
|
257 |
-
return $html;
|
258 |
-
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
* Construct a cache key for the oEmbed response. Account for query parameters needing to bust cache
|
262 |
-
*
|
263 |
-
* @since 1.3.0
|
264 |
-
*
|
265 |
-
* @param array $query_parameters oEmbed API query parameters
|
266 |
-
*
|
267 |
-
* @return string cache key
|
268 |
-
*/
|
269 |
-
public static function oEmbedCacheKey( array $query_parameters )
|
270 |
-
{
|
271 |
-
if ( ! ( isset( $query_parameters['id'] ) && $query_parameters['id'] ) ) {
|
272 |
-
return '';
|
273 |
-
}
|
274 |
-
|
275 |
-
$key_pieces = array( static::SHORTCODE_TAG, $query_parameters['id'] );
|
276 |
-
|
277 |
-
// separate cache for each explicitly-defined display language
|
278 |
-
if ( isset( $query_parameters['lang'] ) && $query_parameters['lang'] ) {
|
279 |
-
$key_pieces[] = $query_parameters['lang'];
|
280 |
-
}
|
281 |
-
|
282 |
-
if ( isset( $query_parameters['limit'] ) && $query_parameters['limit'] ) {
|
283 |
-
$key_pieces[] = $query_parameters['limit'];
|
284 |
-
}
|
285 |
-
|
286 |
-
return implode( '_', $key_pieces );
|
287 |
-
}
|
288 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/Twitter/WordPress/Site/Username.php
CHANGED
@@ -55,7 +55,7 @@ class Username
|
|
55 |
$post_id = null;
|
56 |
}
|
57 |
|
58 |
-
$username = get_option( \Twitter\WordPress\Admin\Settings\SiteAttribution::OPTION_NAME, '' );
|
59 |
|
60 |
if ( ! is_string( $username ) ) {
|
61 |
$username = '';
|
55 |
$post_id = null;
|
56 |
}
|
57 |
|
58 |
+
$username = get_option( \Twitter\WordPress\Admin\Settings\Cards\SiteAttribution::OPTION_NAME, '' );
|
59 |
|
60 |
if ( ! is_string( $username ) ) {
|
61 |
$username = '';
|
src/Twitter/WordPress/User/Meta.php
CHANGED
@@ -39,11 +39,12 @@ class Meta
|
|
39 |
* @since 1.3.0
|
40 |
*
|
41 |
* @param int|string $user_id WordPress user identifier. may be WP_User->ID or a separate identifier used by an extending system
|
42 |
-
* @param string $key
|
43 |
*
|
44 |
* @return string stored username. empty string if no user_id provided or no username found
|
45 |
*/
|
46 |
-
public static function getSocialUsername( $user_id, $key )
|
|
|
47 |
// basic test for invalid passed parameter
|
48 |
if ( ! $user_id ) {
|
49 |
return '';
|
@@ -87,7 +88,8 @@ class Meta
|
|
87 |
*
|
88 |
* @return string Twitter username value stored for the given WordPress user identifier
|
89 |
*/
|
90 |
-
public static function getTwitterUsername( $user_id )
|
|
|
91 |
return static::getSocialUsername( $user_id, 'twitter' );
|
92 |
}
|
93 |
|
@@ -100,7 +102,8 @@ class Meta
|
|
100 |
*
|
101 |
* @return string Periscope username value stored for the given WordPress user identifier
|
102 |
*/
|
103 |
-
public static function getPeriscopeUsername( $user_id )
|
|
|
104 |
return static::getSocialUsername( $user_id, 'periscope' );
|
105 |
}
|
106 |
}
|
39 |
* @since 1.3.0
|
40 |
*
|
41 |
* @param int|string $user_id WordPress user identifier. may be WP_User->ID or a separate identifier used by an extending system
|
42 |
+
* @param string $key user attribute or meta key storing the username of interest
|
43 |
*
|
44 |
* @return string stored username. empty string if no user_id provided or no username found
|
45 |
*/
|
46 |
+
public static function getSocialUsername( $user_id, $key )
|
47 |
+
{
|
48 |
// basic test for invalid passed parameter
|
49 |
if ( ! $user_id ) {
|
50 |
return '';
|
88 |
*
|
89 |
* @return string Twitter username value stored for the given WordPress user identifier
|
90 |
*/
|
91 |
+
public static function getTwitterUsername( $user_id )
|
92 |
+
{
|
93 |
return static::getSocialUsername( $user_id, 'twitter' );
|
94 |
}
|
95 |
|
102 |
*
|
103 |
* @return string Periscope username value stored for the given WordPress user identifier
|
104 |
*/
|
105 |
+
public static function getPeriscopeUsername( $user_id )
|
106 |
+
{
|
107 |
return static::getSocialUsername( $user_id, 'periscope' );
|
108 |
}
|
109 |
}
|
src/Twitter/WordPress/Widgets/Advertising/Tracking.php
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2017 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets\Advertising;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add embedded profile timeline as a WordPress widget
|
30 |
+
*
|
31 |
+
* @see http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
class Tracking extends \Twitter\WordPress\Widgets\Widget
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class of the related shortcode handler
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const SHORTCODE_CLASS = '\Twitter\WordPress\Shortcodes\Advertising\Tracking';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Register widget with WordPress
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @return void
|
52 |
+
*/
|
53 |
+
public function __construct()
|
54 |
+
{
|
55 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
56 |
+
parent::__construct(
|
57 |
+
'twitter-tracking', // Base ID
|
58 |
+
$shortcode_class::featureName(), // name
|
59 |
+
array(
|
60 |
+
'description' => static::getDescription(),
|
61 |
+
)
|
62 |
+
);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Describe the functionality offered by the widget
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @return string description of the widget functionality
|
71 |
+
*/
|
72 |
+
public static function getDescription()
|
73 |
+
{
|
74 |
+
return __( 'Track Twitter advertising conversion or build a custom audience for ad targeting', 'twitter' );
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Front-end display of widget
|
79 |
+
*
|
80 |
+
* @since 2.0.0
|
81 |
+
*
|
82 |
+
* @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
|
83 |
+
* @param array $instance The settings for the particular instance of the widget
|
84 |
+
*
|
85 |
+
* @return void
|
86 |
+
*/
|
87 |
+
public function widget( $args, $instance )
|
88 |
+
{
|
89 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
90 |
+
if ( ! method_exists( $shortcode_class, 'shortcodeHandler' ) ) {
|
91 |
+
return;
|
92 |
+
}
|
93 |
+
$html = $shortcode_class::shortcodeHandler( $instance );
|
94 |
+
if ( ! $html ) {
|
95 |
+
return;
|
96 |
+
}
|
97 |
+
|
98 |
+
// Allow HTML markup set by author, site
|
99 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
100 |
+
echo $args['before_widget'];
|
101 |
+
|
102 |
+
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
|
103 |
+
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
|
104 |
+
if ( $title ) {
|
105 |
+
// Allow HTML markup set by author, site
|
106 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
107 |
+
echo $args['before_title'];
|
108 |
+
|
109 |
+
// Allow HTML in title. Link to Twitter datasource might be common use
|
110 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
111 |
+
echo $title;
|
112 |
+
|
113 |
+
// Allow HTML markup set by author, site
|
114 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
115 |
+
echo $args['after_title'];
|
116 |
+
}
|
117 |
+
|
118 |
+
// escaped in markup builder
|
119 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput
|
120 |
+
echo $html;
|
121 |
+
|
122 |
+
// Allow HTML markup set by author, site
|
123 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
124 |
+
echo $args['after_widget'];
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Settings update form
|
129 |
+
*
|
130 |
+
* @since 2.0.0
|
131 |
+
*
|
132 |
+
* @param array $instance Current settings
|
133 |
+
*
|
134 |
+
* @return void
|
135 |
+
*/
|
136 |
+
public function form( $instance )
|
137 |
+
{
|
138 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
139 |
+
if ( ! method_exists( $shortcode_class, 'getShortcodeDefaults' ) ) {
|
140 |
+
return;
|
141 |
+
}
|
142 |
+
$instance = wp_parse_args(
|
143 |
+
(array) $instance,
|
144 |
+
$shortcode_class::getShortcodeDefaults()
|
145 |
+
);
|
146 |
+
|
147 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'id' ) ); ?>"><?php echo esc_html( _x( 'Website tag ID', 'Identifier used to track an advertising campaign including conversion and custom audiences', 'twitter' ) . ':' ); ?></label>
|
148 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'id' ) ); ?>" type="text" inputmode="verbatim" spellcheck="false" pattern="<?php echo esc_attr( \Twitter\Helpers\Validators\WebsiteTag::getPattern() ); ?>" maxlength="<?php echo esc_attr( \Twitter\Helpers\Validators\WebsiteTag::MAX_LENGTH ); ?>" value="<?php echo esc_attr( trim( $instance['id'] ) ); ?>" required<?php
|
149 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
150 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
151 |
+
?>></p><?php
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Update a widget instance
|
156 |
+
*
|
157 |
+
* @since 2.0.0
|
158 |
+
*
|
159 |
+
* @param array $new_instance New settings for this instance as input by the user via form()
|
160 |
+
* @param array $old_instance Old settings for this instance
|
161 |
+
*
|
162 |
+
* @return bool|array settings to save or false to cancel saving
|
163 |
+
*/
|
164 |
+
public function update( $new_instance, $old_instance )
|
165 |
+
{
|
166 |
+
$new_instance = (array) $new_instance;
|
167 |
+
|
168 |
+
$id = '';
|
169 |
+
if ( isset( $new_instance['id'] ) ) {
|
170 |
+
$id = \Twitter\Helpers\Validators\WebsiteTag::sanitize( $new_instance['id'] );
|
171 |
+
}
|
172 |
+
// ID required, otherwise nothing to track
|
173 |
+
if ( ! $id ) {
|
174 |
+
return false;
|
175 |
+
}
|
176 |
+
|
177 |
+
return array(
|
178 |
+
'id' => $id,
|
179 |
+
);
|
180 |
+
}
|
181 |
+
}
|
src/Twitter/WordPress/Widgets/{Follow.php → Buttons/Follow.php}
RENAMED
@@ -23,16 +23,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Widgets;
|
27 |
|
28 |
/**
|
29 |
-
* Add Twitter Follow
|
30 |
*
|
31 |
* @link http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
*
|
33 |
* @since 1.0.0
|
34 |
*/
|
35 |
-
class Follow extends \
|
36 |
{
|
37 |
|
38 |
/**
|
@@ -50,8 +50,6 @@ class Follow extends \WP_Widget
|
|
50 |
* Register widget with WordPress
|
51 |
*
|
52 |
* @since 1.0.0
|
53 |
-
*
|
54 |
-
* @return void
|
55 |
*/
|
56 |
public function __construct()
|
57 |
{
|
@@ -59,11 +57,23 @@ class Follow extends \WP_Widget
|
|
59 |
static::BASE_ID, // Base ID
|
60 |
__( 'Twitter Follow Button', 'twitter' ), // name
|
61 |
array(
|
62 |
-
'description' =>
|
63 |
)
|
64 |
);
|
65 |
}
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
/**
|
68 |
* Front-end display of widget
|
69 |
*
|
@@ -76,29 +86,37 @@ class Follow extends \WP_Widget
|
|
76 |
*/
|
77 |
public function widget( $args, $instance )
|
78 |
{
|
79 |
-
|
80 |
-
if ( empty( $instance['screen_name'] ) ) {
|
81 |
-
return;
|
82 |
-
}
|
83 |
-
|
84 |
-
$follow_button_html = \Twitter\WordPress\Shortcodes\Follow::shortcodeHandler( $instance );
|
85 |
if ( ! $follow_button_html ) {
|
86 |
return;
|
87 |
}
|
88 |
|
|
|
|
|
89 |
echo $args['before_widget'];
|
90 |
|
91 |
/** This filter is documented in wp-includes/default-widgets.php */
|
92 |
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
|
93 |
if ( $title ) {
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
96 |
|
97 |
// escaped in markup builder
|
98 |
-
// @
|
99 |
echo $follow_button_html;
|
100 |
-
// @codingStandardsIgnoreEnd WordPress.XSS.EscapeOutput
|
101 |
|
|
|
|
|
102 |
echo $args['after_widget'];
|
103 |
}
|
104 |
|
@@ -117,28 +135,50 @@ class Follow extends \WP_Widget
|
|
117 |
(array) $instance,
|
118 |
array_merge(
|
119 |
array( 'title' => '' ),
|
120 |
-
\Twitter\WordPress\Shortcodes\Follow::$SHORTCODE_DEFAULTS
|
121 |
)
|
122 |
);
|
123 |
|
|
|
124 |
$close_void_element = \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
125 |
-
?>
|
126 |
-
<p><label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php echo esc_html( __( 'Title:' ) ); ?></label>
|
127 |
-
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( trim( strip_tags( $instance['title'] ) ) ); ?>"<?php echo $close_void_element; ?>></p>
|
128 |
|
|
|
129 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'screen_name' ) ); ?>"><?php echo esc_html( __( '@username:', 'twitter' ) ); ?></label>
|
130 |
-
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'screen_name' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'screen_name' ) ); ?>" type="text" pattern="
|
131 |
-
|
132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
<label for="<?php echo esc_attr( $this->get_field_id( 'show_screen_name' ) ); ?>"><?php echo esc_html( __( 'Show username?', 'twitter' ) ); ?></label></p>
|
134 |
|
135 |
-
<p><input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_count' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_count' ) ); ?>" value="1"<?php
|
|
|
|
|
|
|
|
|
136 |
<label for="<?php echo esc_attr( $this->get_field_id( 'show_count' ) ); ?>"><?php echo esc_html( __( 'Show number of followers?', 'twitter' ) ); ?></label></p>
|
137 |
|
138 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>"><?php echo esc_html( __( 'Button size:', 'twitter' ) ); ?></label>
|
139 |
<fieldset id="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>">
|
140 |
-
<label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" value="medium"
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
</fieldset></p>
|
143 |
<?php
|
144 |
}
|
@@ -171,12 +211,12 @@ class Follow extends \WP_Widget
|
|
171 |
}
|
172 |
}
|
173 |
|
174 |
-
$follow_button = \Twitter\Widgets\
|
175 |
if ( ! $follow_button ) {
|
176 |
return false;
|
177 |
}
|
178 |
|
179 |
-
$filtered_options = $follow_button->toArray(
|
180 |
$screen_name = $follow_button->getScreenName();
|
181 |
if ( $screen_name ) {
|
182 |
$filtered_options['screen_name'] = $screen_name;
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Widgets\Buttons;
|
27 |
|
28 |
/**
|
29 |
+
* Add Twitter Follow button as a WordPress widget
|
30 |
*
|
31 |
* @link http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
*
|
33 |
* @since 1.0.0
|
34 |
*/
|
35 |
+
class Follow extends \Twitter\WordPress\Widgets\Widget implements \Twitter\WordPress\Widgets\WidgetInterface
|
36 |
{
|
37 |
|
38 |
/**
|
50 |
* Register widget with WordPress
|
51 |
*
|
52 |
* @since 1.0.0
|
|
|
|
|
53 |
*/
|
54 |
public function __construct()
|
55 |
{
|
57 |
static::BASE_ID, // Base ID
|
58 |
__( 'Twitter Follow Button', 'twitter' ), // name
|
59 |
array(
|
60 |
+
'description' => static::getDescription(), // args
|
61 |
)
|
62 |
);
|
63 |
}
|
64 |
|
65 |
+
/**
|
66 |
+
* Describe the functionality offered by the widget
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @return string description of the widget functionality
|
71 |
+
*/
|
72 |
+
public static function getDescription()
|
73 |
+
{
|
74 |
+
return __( 'Lets a viewer follow your Twitter account', 'twitter' );
|
75 |
+
}
|
76 |
+
|
77 |
/**
|
78 |
* Front-end display of widget
|
79 |
*
|
86 |
*/
|
87 |
public function widget( $args, $instance )
|
88 |
{
|
89 |
+
$follow_button_html = \Twitter\WordPress\Shortcodes\Buttons\Follow::shortcodeHandler( $instance );
|
|
|
|
|
|
|
|
|
|
|
90 |
if ( ! $follow_button_html ) {
|
91 |
return;
|
92 |
}
|
93 |
|
94 |
+
// Allow HTML markup set by author, site
|
95 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
96 |
echo $args['before_widget'];
|
97 |
|
98 |
/** This filter is documented in wp-includes/default-widgets.php */
|
99 |
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
|
100 |
if ( $title ) {
|
101 |
+
// Allow HTML markup set by author, site
|
102 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
103 |
+
echo $args['before_title'];
|
104 |
+
|
105 |
+
// Allow HTML in title. Link to Twitter profile might be common use
|
106 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
107 |
+
echo $title;
|
108 |
+
|
109 |
+
// Allow HTML markup set by author, site
|
110 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
111 |
+
echo $args['after_title'];
|
112 |
}
|
113 |
|
114 |
// escaped in markup builder
|
115 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
116 |
echo $follow_button_html;
|
|
|
117 |
|
118 |
+
// Allow HTML markup set by author, site
|
119 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
120 |
echo $args['after_widget'];
|
121 |
}
|
122 |
|
135 |
(array) $instance,
|
136 |
array_merge(
|
137 |
array( 'title' => '' ),
|
138 |
+
\Twitter\WordPress\Shortcodes\Buttons\Follow::$SHORTCODE_DEFAULTS
|
139 |
)
|
140 |
);
|
141 |
|
142 |
+
$this->titleFormElements( $instance );
|
143 |
$close_void_element = \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
|
|
|
|
|
|
144 |
|
145 |
+
?>
|
146 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'screen_name' ) ); ?>"><?php echo esc_html( __( '@username:', 'twitter' ) ); ?></label>
|
147 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'screen_name' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'screen_name' ) ); ?>" type="text" pattern="<?php echo esc_attr( \Twitter\Helpers\Validators\ScreenName::getPattern() ); ?>" inputmode="verbatim" spellcheck="false" maxlength="<?php echo esc_attr( \Twitter\Helpers\Validators\ScreenName::MAX_LENGTH ); ?>" value="<?php echo esc_attr( $instance['screen_name'] ); ?>"<?php
|
148 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
149 |
+
echo $close_void_element;
|
150 |
+
?>></p>
|
151 |
+
|
152 |
+
<p><input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_screen_name' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_screen_name' ) ); ?>" value="1"<?php
|
153 |
+
checked( $instance['show_screen_name'] );
|
154 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
155 |
+
echo $close_void_element;
|
156 |
+
?>>
|
157 |
<label for="<?php echo esc_attr( $this->get_field_id( 'show_screen_name' ) ); ?>"><?php echo esc_html( __( 'Show username?', 'twitter' ) ); ?></label></p>
|
158 |
|
159 |
+
<p><input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_count' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_count' ) ); ?>" value="1"<?php
|
160 |
+
checked( $instance['show_count'] );
|
161 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
162 |
+
echo $close_void_element;
|
163 |
+
?>>
|
164 |
<label for="<?php echo esc_attr( $this->get_field_id( 'show_count' ) ); ?>"><?php echo esc_html( __( 'Show number of followers?', 'twitter' ) ); ?></label></p>
|
165 |
|
166 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>"><?php echo esc_html( __( 'Button size:', 'twitter' ) ); ?></label>
|
167 |
<fieldset id="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>">
|
168 |
+
<label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" value="medium"
|
169 |
+
<?php
|
170 |
+
checked( 'large' !== $instance['size'] );
|
171 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
172 |
+
echo $close_void_element;
|
173 |
+
?>>
|
174 |
+
<?php echo esc_html( _x( 'medium', 'medium size button', 'twitter' ) ); ?> </label>
|
175 |
+
<label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" value="large"
|
176 |
+
<?php
|
177 |
+
checked( 'large' === $instance['size'] );
|
178 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
179 |
+
echo $close_void_element;
|
180 |
+
?>>
|
181 |
+
<?php echo esc_html( _x( 'large', 'large size button', 'twitter' ) ); ?> </label>
|
182 |
</fieldset></p>
|
183 |
<?php
|
184 |
}
|
211 |
}
|
212 |
}
|
213 |
|
214 |
+
$follow_button = \Twitter\Widgets\Buttons\Follow::fromArray( $new_instance );
|
215 |
if ( ! $follow_button ) {
|
216 |
return false;
|
217 |
}
|
218 |
|
219 |
+
$filtered_options = $follow_button->toArray();
|
220 |
$screen_name = $follow_button->getScreenName();
|
221 |
if ( $screen_name ) {
|
222 |
$filtered_options['screen_name'] = $screen_name;
|
src/Twitter/WordPress/Widgets/{PeriscopeOnAir.php → Buttons/Periscope/OnAir.php}
RENAMED
@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
-
namespace Twitter\WordPress\Widgets;
|
27 |
|
28 |
/**
|
29 |
* Add Periscope On Air button as a WordPress widget
|
@@ -32,7 +32,7 @@ namespace Twitter\WordPress\Widgets;
|
|
32 |
*
|
33 |
* @since 1.3.0
|
34 |
*/
|
35 |
-
class
|
36 |
{
|
37 |
|
38 |
/**
|
@@ -50,8 +50,6 @@ class PeriscopeOnAir extends \WP_Widget
|
|
50 |
* Register widget with WordPress
|
51 |
*
|
52 |
* @since 1.3.0
|
53 |
-
*
|
54 |
-
* @return void
|
55 |
*/
|
56 |
public function __construct()
|
57 |
{
|
@@ -59,11 +57,23 @@ class PeriscopeOnAir extends \WP_Widget
|
|
59 |
static::BASE_ID, // Base ID
|
60 |
__( 'Periscope On Air Button', 'twitter' ), // name
|
61 |
array(
|
62 |
-
'description' =>
|
63 |
)
|
64 |
);
|
65 |
}
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
/**
|
68 |
* Front-end display of widget
|
69 |
*
|
@@ -76,8 +86,8 @@ class PeriscopeOnAir extends \WP_Widget
|
|
76 |
*/
|
77 |
public function widget( $args, $instance )
|
78 |
{
|
79 |
-
|
80 |
-
if (
|
81 |
return;
|
82 |
}
|
83 |
|
@@ -85,22 +95,30 @@ class PeriscopeOnAir extends \WP_Widget
|
|
85 |
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
|
86 |
unset( $instance['title'] );
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
return;
|
91 |
-
}
|
92 |
-
|
93 |
echo $args['before_widget'];
|
94 |
|
95 |
if ( $title ) {
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
}
|
98 |
|
99 |
// escaped in markup builder
|
100 |
-
// @
|
101 |
echo $button_html;
|
102 |
-
// @codingStandardsIgnoreEnd WordPress.XSS.EscapeOutput
|
103 |
|
|
|
|
|
104 |
echo $args['after_widget'];
|
105 |
}
|
106 |
|
@@ -119,22 +137,31 @@ class PeriscopeOnAir extends \WP_Widget
|
|
119 |
(array) $instance,
|
120 |
array_merge(
|
121 |
array( 'title' => '' ),
|
122 |
-
\Twitter\WordPress\Shortcodes\
|
123 |
)
|
124 |
);
|
125 |
|
126 |
$close_void_element = \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
|
|
127 |
?>
|
128 |
-
<p><label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php echo esc_html( __( 'Title:', 'twitter' ) ); ?></label>
|
129 |
-
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( trim( strip_tags( $instance['title'] ) ) ); ?>"<?php echo $close_void_element; ?>></p>
|
130 |
-
|
131 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>"><?php echo esc_html( _x( 'Periscope username', 'Prompt requesting entry of a Periscope username', 'twitter' ) ); ?></label>
|
132 |
-
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'username' ) ); ?>" type="text" pattern="
|
|
|
|
|
|
|
133 |
|
134 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>"><?php echo esc_html( __( 'Button size:', 'twitter' ) ); ?></label>
|
135 |
<fieldset id="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>">
|
136 |
-
<label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" value="small"<?php
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
</fieldset></p>
|
139 |
<?php
|
140 |
}
|
@@ -159,7 +186,7 @@ class PeriscopeOnAir extends \WP_Widget
|
|
159 |
}
|
160 |
unset( $new_instance['title'] );
|
161 |
|
162 |
-
$on_air = \Twitter\Widgets\
|
163 |
if ( ! $on_air ) {
|
164 |
return false;
|
165 |
}
|
23 |
THE SOFTWARE.
|
24 |
*/
|
25 |
|
26 |
+
namespace Twitter\WordPress\Widgets\Buttons\Periscope;
|
27 |
|
28 |
/**
|
29 |
* Add Periscope On Air button as a WordPress widget
|
32 |
*
|
33 |
* @since 1.3.0
|
34 |
*/
|
35 |
+
class OnAir extends \Twitter\WordPress\Widgets\Widget implements \Twitter\WordPress\Widgets\WidgetInterface
|
36 |
{
|
37 |
|
38 |
/**
|
50 |
* Register widget with WordPress
|
51 |
*
|
52 |
* @since 1.3.0
|
|
|
|
|
53 |
*/
|
54 |
public function __construct()
|
55 |
{
|
57 |
static::BASE_ID, // Base ID
|
58 |
__( 'Periscope On Air Button', 'twitter' ), // name
|
59 |
array(
|
60 |
+
'description' => static::getDescription(),
|
61 |
)
|
62 |
);
|
63 |
}
|
64 |
|
65 |
+
/**
|
66 |
+
* Describe the functionality offered by the widget
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @return string description of the widget functionality
|
71 |
+
*/
|
72 |
+
public static function getDescription()
|
73 |
+
{
|
74 |
+
return __( 'Lets a viewer discover your Periscope account and on air status', 'twitter' );
|
75 |
+
}
|
76 |
+
|
77 |
/**
|
78 |
* Front-end display of widget
|
79 |
*
|
86 |
*/
|
87 |
public function widget( $args, $instance )
|
88 |
{
|
89 |
+
$button_html = \Twitter\WordPress\Shortcodes\Buttons\Periscope\OnAir::shortcodeHandler( $instance );
|
90 |
+
if ( ! $button_html ) {
|
91 |
return;
|
92 |
}
|
93 |
|
95 |
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
|
96 |
unset( $instance['title'] );
|
97 |
|
98 |
+
// Allow HTML markup set by author, site
|
99 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
|
|
|
|
|
|
100 |
echo $args['before_widget'];
|
101 |
|
102 |
if ( $title ) {
|
103 |
+
// Allow HTML markup set by author, site
|
104 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
105 |
+
echo $args['before_title'];
|
106 |
+
|
107 |
+
// Allow HTML in title. Link to Periscope profile might be common use
|
108 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
109 |
+
echo $title;
|
110 |
+
|
111 |
+
// Allow HTML markup set by author, site
|
112 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
113 |
+
echo $args['after_title'];
|
114 |
}
|
115 |
|
116 |
// escaped in markup builder
|
117 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
118 |
echo $button_html;
|
|
|
119 |
|
120 |
+
// Allow HTML markup set by author, site
|
121 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
122 |
echo $args['after_widget'];
|
123 |
}
|
124 |
|
137 |
(array) $instance,
|
138 |
array_merge(
|
139 |
array( 'title' => '' ),
|
140 |
+
\Twitter\WordPress\Shortcodes\Buttons\Periscope\OnAir::$SHORTCODE_DEFAULTS
|
141 |
)
|
142 |
);
|
143 |
|
144 |
$close_void_element = \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
145 |
+
$this->titleFormElements( $instance );
|
146 |
?>
|
|
|
|
|
|
|
147 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>"><?php echo esc_html( _x( 'Periscope username', 'Prompt requesting entry of a Periscope username', 'twitter' ) ); ?></label>
|
148 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'username' ) ); ?>" type="text" pattern="<?php echo esc_attr( \Twitter\Helpers\Validators\PeriscopeUsername::getPattern() ); ?>" inputmode="verbatim" spellcheck="false" maxlength="<?php echo esc_attr( \Twitter\Helpers\Validators\PeriscopeUsername::MAX_LENGTH ); ?>" value="<?php echo esc_attr( $instance['username'] ); ?>"<?php
|
149 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
150 |
+
echo $close_void_element;
|
151 |
+
?>></p>
|
152 |
|
153 |
<p><label for="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>"><?php echo esc_html( __( 'Button size:', 'twitter' ) ); ?></label>
|
154 |
<fieldset id="<?php echo esc_attr( $this->get_field_id( 'size' ) ); ?>">
|
155 |
+
<label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" value="small"<?php
|
156 |
+
checked( 'large' !== $instance['size'] );
|
157 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
158 |
+
echo $close_void_element;
|
159 |
+
?>> <?php echo esc_html( _x( 'small', 'small size button', 'twitter' ) ); ?> </label>
|
160 |
+
<label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'size' ) ); ?>" value="large"<?php
|
161 |
+
checked( 'large' === $instance['size'] );
|
162 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
163 |
+
echo $close_void_element;
|
164 |
+
?>> <?php echo esc_html( _x( 'large', 'large size button', 'twitter' ) ); ?> </label>
|
165 |
</fieldset></p>
|
166 |
<?php
|
167 |
}
|
186 |
}
|
187 |
unset( $new_instance['title'] );
|
188 |
|
189 |
+
$on_air = \Twitter\Widgets\Buttons\Periscope\OnAir::fromArray( $new_instance );
|
190 |
if ( ! $on_air ) {
|
191 |
return false;
|
192 |
}
|
src/Twitter/WordPress/Widgets/Embeds/Timeline.php
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets\Embeds;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add embedded profile timeline as a WordPress widget
|
30 |
+
*
|
31 |
+
* @link http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
abstract class Timeline extends \Twitter\WordPress\Widgets\Widget implements \Twitter\WordPress\Widgets\WidgetInterface
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Register widget with WordPress
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @return void
|
43 |
+
*/
|
44 |
+
public function __construct()
|
45 |
+
{
|
46 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
47 |
+
parent::__construct(
|
48 |
+
$shortcode_class::HTML_CLASS, // Base ID
|
49 |
+
$shortcode_class::featureName(), // name
|
50 |
+
array(
|
51 |
+
'description' => static::getDescription(),
|
52 |
+
)
|
53 |
+
);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Get displayed options for chrome configuration with label
|
58 |
+
*
|
59 |
+
* @since 2.0.0
|
60 |
+
*
|
61 |
+
* @return array chrome options
|
62 |
+
*/
|
63 |
+
public static function getChromeFormOptions()
|
64 |
+
{
|
65 |
+
return array(
|
66 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOHEADER => _x( 'Hide header', 'Hide introductory section before the timeline', 'twitter' ),
|
67 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOFOOTER => _x( 'Hide footer', 'Hide summary section after the timeline', 'twitter' ),
|
68 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOBORDERS => _x( 'Hide borders', 'Hide the visual line between two sections', 'twitter' ),
|
69 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_NOSCROLLBAR => _x( 'Hide scroll bar', 'Hide the visual indicator of additional content available above or below the current position', 'twitter' ),
|
70 |
+
\Twitter\Widgets\Embeds\Timeline::CHROME_TRANSPARENT => _x( 'Transparent background', 'Remove color shown behind the widget', 'twitter' ),
|
71 |
+
);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Front-end display of widget
|
76 |
+
*
|
77 |
+
* @since 2.0.0
|
78 |
+
*
|
79 |
+
* @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
|
80 |
+
* @param array $instance The settings for the particular instance of the widget
|
81 |
+
*
|
82 |
+
* @return void
|
83 |
+
*/
|
84 |
+
public function widget( $args, $instance )
|
85 |
+
{
|
86 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
87 |
+
if ( ! method_exists( $shortcode_class, 'shortcodeHandler' ) ) {
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
$timeline_html = $shortcode_class::shortcodeHandler( $instance );
|
91 |
+
if ( ! $timeline_html ) {
|
92 |
+
return;
|
93 |
+
}
|
94 |
+
|
95 |
+
// Allow HTML markup set by author, site
|
96 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
97 |
+
echo $args['before_widget'];
|
98 |
+
|
99 |
+
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
|
100 |
+
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
|
101 |
+
if ( $title ) {
|
102 |
+
// Allow HTML markup set by author, site
|
103 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
104 |
+
echo $args['before_title'];
|
105 |
+
|
106 |
+
// Allow HTML in title. Link to Twitter datasource might be common use
|
107 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
108 |
+
echo $title;
|
109 |
+
|
110 |
+
// Allow HTML markup set by author, site
|
111 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
112 |
+
echo $args['after_title'];
|
113 |
+
}
|
114 |
+
|
115 |
+
// escaped in markup builder
|
116 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput
|
117 |
+
echo $timeline_html;
|
118 |
+
|
119 |
+
// Allow HTML markup set by author, site
|
120 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
121 |
+
echo $args['after_widget'];
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Settings update form
|
126 |
+
*
|
127 |
+
* @since 2.0.0
|
128 |
+
*
|
129 |
+
* @param array $instance Current settings
|
130 |
+
*
|
131 |
+
* @return void
|
132 |
+
*/
|
133 |
+
public function form( $instance )
|
134 |
+
{
|
135 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
136 |
+
if ( ! method_exists( $shortcode_class, 'getShortcodeDefaults' ) ) {
|
137 |
+
return;
|
138 |
+
}
|
139 |
+
$instance = wp_parse_args(
|
140 |
+
(array) $instance,
|
141 |
+
array_merge(
|
142 |
+
array( 'title' => '' ),
|
143 |
+
$shortcode_class::getShortcodeDefaults()
|
144 |
+
)
|
145 |
+
);
|
146 |
+
|
147 |
+
$this->titleFormElements( $instance );
|
148 |
+
$this->dataSourceFormElements( $instance );
|
149 |
+
$this->timelineFormElements( $instance );
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Widget form applicable to all timelines
|
154 |
+
*
|
155 |
+
* @since 2.0.0
|
156 |
+
*
|
157 |
+
* @param array $instance widget instance
|
158 |
+
*
|
159 |
+
* @return void
|
160 |
+
*/
|
161 |
+
protected function timelineFormElements( $instance )
|
162 |
+
{
|
163 |
+
$close_void_element = \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
164 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>"><?php echo esc_html( \Twitter\WordPress\Admin\Settings\Embeds\Theme::featureName() . ':' ); ?></label></p><?php
|
165 |
+
$theme_choices = \Twitter\WordPress\Admin\Settings\Embeds\Theme::themeChoices();
|
166 |
+
?><fieldset id="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>"><?php
|
167 |
+
foreach ( $theme_choices as $value => $label ) {
|
168 |
+
?>
|
169 |
+
<p><label><input type="radio" name="<?php echo esc_attr( $this->get_field_name( 'theme' ) ); ?>" value="<?php echo esc_attr( $value ); ?>"<?php
|
170 |
+
checked( $value, $instance['theme'] );
|
171 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
172 |
+
echo $close_void_element;
|
173 |
+
?>><?php echo esc_html( $label ); ?></label></p>
|
174 |
+
<?php } ?>
|
175 |
+
</fieldset>
|
176 |
+
|
177 |
+
<?php
|
178 |
+
$chrome = static::getChromeFormOptions();
|
179 |
+
if ( ! ( isset( $instance['chrome'] ) && is_array( $instance['chrome'] ) ) ) {
|
180 |
+
$instance['chrome'] = array();
|
181 |
+
}
|
182 |
+
?><label for="<?php echo esc_attr( $this->get_field_id( 'chrome' ) ); ?>"><?php echo esc_html( _x( 'Layout options', 'Visual layout choices', 'twitter' ) . ':' ); ?></label>
|
183 |
+
<fieldset id="<?php echo esc_attr( $this->get_field_id( 'chrome' ) ); ?>"><?php
|
184 |
+
foreach ( $chrome as $value => $label ) {
|
185 |
+
?><p><label><input type="checkbox" class="checkbox" name="<?php echo esc_attr( $this->get_field_name( 'chrome' ) ); ?>[]" value="<?php echo esc_attr( $value ); ?>"<?php
|
186 |
+
checked( in_array( $value, $instance['chrome'], /* strict */ true ) );
|
187 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
188 |
+
echo $close_void_element;
|
189 |
+
?>><?php echo esc_html( $label ); ?></label></p><?php
|
190 |
+
}
|
191 |
+
?></fieldset>
|
192 |
+
|
193 |
+
<p>
|
194 |
+
<label for="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>"><?php echo esc_html( _x( 'Limit', 'Limit the number of Tweets displayed', 'twitter' ) . ':' ); ?></label>
|
195 |
+
<input type="number" class="tiny-text" id="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'limit' ) ); ?>" min="<?php echo esc_attr( \Twitter\Widgets\Embeds\Timeline::MIN_LIMIT ); ?>" max="<?php echo esc_attr( \Twitter\Widgets\Embeds\Timeline::MAX_LIMIT ); ?>" step="1" value="<?php echo esc_attr( $instance['limit'] ); ?>" size="3"<?php
|
196 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
197 |
+
echo $close_void_element;
|
198 |
+
?>>
|
199 |
+
</p>
|
200 |
+
|
201 |
+
<p><label for="<?php echo esc_attr( $this->get_field_id( 'width' ) ); ?>"><?php echo esc_html( _x( 'Width', 'Horizontal dimension measured in whole pixels', 'twitter' ) . ':' ); ?></label><input type="number" id="<?php echo esc_attr( $this->get_field_id( 'width' ) ); ?>" class="small-text" name="<?php echo esc_attr( $this->get_field_name( 'width' ) ); ?>" step="1" min="<?php echo esc_attr( \Twitter\Widgets\Embeds\Timeline::MIN_WIDTH ); ?>" max="<?php echo esc_attr( \Twitter\Widgets\Embeds\Timeline::MAX_WIDTH ); ?>" step="10" value="<?php echo esc_attr( $instance['width'] ); ?>" size="4"<?php
|
202 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
203 |
+
echo $close_void_element;
|
204 |
+
?>></p>
|
205 |
+
|
206 |
+
<p><label for="<?php echo esc_attr( $this->get_field_id( 'height' ) ); ?>"><?php echo esc_html( _x( 'Height', 'Vertical dimension measured in whole pixels', 'twitter' ) . ':' ); ?></label><input type="number" id="<?php echo esc_attr( $this->get_field_id( 'height' ) ); ?>" class="small-text" name="<?php echo esc_attr( $this->get_field_name( 'height' ) ); ?>" step="1" min="<?php echo esc_attr( \Twitter\Widgets\Embeds\Timeline::MIN_HEIGHT ); ?>" step="10" value="<?php echo esc_attr( $instance['height'] ); ?>" size="4"<?php
|
207 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
208 |
+
echo $close_void_element;
|
209 |
+
?>></p><?php
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Fields specific to the timeline datasource configured in the widget
|
214 |
+
*
|
215 |
+
* @since 2.0.0
|
216 |
+
*
|
217 |
+
* @param array $instance widget instance
|
218 |
+
*
|
219 |
+
* @return void
|
220 |
+
*/
|
221 |
+
abstract protected function dataSourceFormElements( $instance );
|
222 |
+
}
|
src/Twitter/WordPress/Widgets/Embeds/Timeline/Collection.php
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add embedded collection as a WordPress widget
|
30 |
+
*
|
31 |
+
* @link http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
class Collection extends \Twitter\WordPress\Widgets\Embeds\Timeline
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class of the related PHP object builder and validator
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const TIMELINE_CLASS = '\Twitter\Widgets\Embeds\Timeline\Collection';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Class of the related shortcode handler
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const SHORTCODE_CLASS = '\Twitter\WordPress\Shortcodes\Embeds\Timeline\Collection';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Describe the functionality offered by the widget
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @return string description of the widget functionality
|
61 |
+
*/
|
62 |
+
public static function getDescription()
|
63 |
+
{
|
64 |
+
return __( 'Tweets organized into a collection', 'twitter' );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Fields specific to the timeline datasource configured in the widget
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*
|
72 |
+
* @param array $instance widget instance
|
73 |
+
*
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
protected function dataSourceFormElements( $instance )
|
77 |
+
{
|
78 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'id' ) ); ?>"><?php echo esc_html( _x( 'Collection ID', 'Unique identifier for a Twitter collection', 'twitter' ) . ':' ); ?></label><input id="<?php echo esc_attr( $this->get_field_id( 'id' ) ); ?>" class="widefat" name="<?php echo esc_attr( $this->get_field_name( 'id' ) ); ?>" type="text" pattern="[0-9]{1,}" inputmode="verbatim" spellcheck="false" value="<?php echo esc_attr( $instance['id'] ); ?>"<?php
|
79 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
80 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
81 |
+
?>></p><?php
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Update a widget instance
|
86 |
+
*
|
87 |
+
* @since 2.0.0
|
88 |
+
*
|
89 |
+
* @param array $new_instance New settings for this instance as input by the user via form()
|
90 |
+
* @param array $old_instance Old settings for this instance
|
91 |
+
*
|
92 |
+
* @return bool|array settings to save or false to cancel saving
|
93 |
+
*/
|
94 |
+
public function update( $new_instance, $old_instance )
|
95 |
+
{
|
96 |
+
$new_instance = (array) $new_instance;
|
97 |
+
|
98 |
+
// collection ID required
|
99 |
+
if ( ! ( isset( $new_instance['id'] ) && $new_instance['id'] ) ) {
|
100 |
+
return false;
|
101 |
+
}
|
102 |
+
|
103 |
+
$instance = array();
|
104 |
+
$title = sanitize_text_field( $new_instance['title'] );
|
105 |
+
if ( $title ) {
|
106 |
+
$instance['title'] = $title;
|
107 |
+
}
|
108 |
+
unset( $new_instance['title'] );
|
109 |
+
|
110 |
+
// process widget parameters as if they were parsed shortcode attributes
|
111 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
112 |
+
$timeline_class = static::TIMELINE_CLASS;
|
113 |
+
if ( ! ( method_exists( $timeline_class, 'fromArray' ) && method_exists( $shortcode_class, 'shortcodeAttributesToTimelineKeys' ) ) ) {
|
114 |
+
return false;
|
115 |
+
}
|
116 |
+
$timeline = $timeline_class::fromArray( $shortcode_class::shortcodeAttributesToTimelineKeys( $new_instance ) );
|
117 |
+
if ( ! ( $timeline && method_exists( $timeline, 'getID' ) && $timeline->getID() && method_exists( $timeline, 'toArray' ) ) ) {
|
118 |
+
return false;
|
119 |
+
}
|
120 |
+
|
121 |
+
$data_attributes = $timeline->toArray();
|
122 |
+
if ( isset( $data_attributes['tweet-limit'] ) ) {
|
123 |
+
$data_attributes['limit'] = $data_attributes['tweet-limit'];
|
124 |
+
}
|
125 |
+
|
126 |
+
return array_merge( $instance, $data_attributes );
|
127 |
+
}
|
128 |
+
}
|
src/Twitter/WordPress/Widgets/Embeds/Timeline/Profile.php
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add embedded profile timeline as a WordPress widget
|
30 |
+
*
|
31 |
+
* @see http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
class Profile extends \Twitter\WordPress\Widgets\Embeds\Timeline
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class of the related PHP object builder and validator
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const TIMELINE_CLASS = '\Twitter\Widgets\Embeds\Timeline\Profile';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Class of the related shortcode handler
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const SHORTCODE_CLASS = '\Twitter\WordPress\Shortcodes\Embeds\Timeline\Profile';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Describe the functionality offered by the widget
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @return string description of the widget functionality
|
61 |
+
*/
|
62 |
+
public static function getDescription()
|
63 |
+
{
|
64 |
+
return __( 'The latest Tweets from a Twitter account', 'twitter' );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Fields specific to the timeline datasource configured in the widget
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*
|
72 |
+
* @param array $instance widget instance
|
73 |
+
*
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
protected function dataSourceFormElements( $instance )
|
77 |
+
{
|
78 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'screen_name' ) ); ?>"><?php echo esc_html( __( 'Twitter @username', 'twitter' ) . ':' ); ?></label>
|
79 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'screen_name' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'screen_name' ) ); ?>" type="text" pattern="<?php echo esc_attr( \Twitter\Helpers\Validators\ScreenName::getPattern() ); ?>" inputmode="verbatim" spellcheck="false" maxlength="<?php echo esc_attr( \Twitter\Helpers\Validators\ScreenName::MAX_LENGTH ); ?>" value="<?php echo esc_attr( $instance['screen_name'] ); ?>"<?php
|
80 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
81 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
82 |
+
?>></p><?php
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Update a widget instance
|
87 |
+
*
|
88 |
+
* @since 2.0.0
|
89 |
+
*
|
90 |
+
* @param array $new_instance New settings for this instance as input by the user via form()
|
91 |
+
* @param array $old_instance Old settings for this instance
|
92 |
+
*
|
93 |
+
* @return bool|array settings to save or false to cancel saving
|
94 |
+
*/
|
95 |
+
public function update( $new_instance, $old_instance )
|
96 |
+
{
|
97 |
+
$instance = array();
|
98 |
+
$new_instance = (array) $new_instance;
|
99 |
+
$title = sanitize_text_field( $new_instance['title'] );
|
100 |
+
if ( $title ) {
|
101 |
+
$instance['title'] = $title;
|
102 |
+
}
|
103 |
+
unset( $new_instance['title'] );
|
104 |
+
|
105 |
+
// process widget parameters as if they were parsed shortcode attributes
|
106 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
107 |
+
$timeline_class = static::TIMELINE_CLASS;
|
108 |
+
if ( ! ( method_exists( $timeline_class, 'fromArray' ) && method_exists( $shortcode_class, 'shortcodeAttributesToTimelineKeys' ) ) ) {
|
109 |
+
return false;
|
110 |
+
}
|
111 |
+
$timeline = $timeline_class::fromArray( $shortcode_class::shortcodeAttributesToTimelineKeys( $new_instance ) );
|
112 |
+
if ( ! ($timeline && method_exists( $timeline, 'toArray' ) ) ) {
|
113 |
+
return false;
|
114 |
+
}
|
115 |
+
|
116 |
+
$data_attributes = $timeline->toArray();
|
117 |
+
// convert data-* dashes to shortcode underscores
|
118 |
+
if ( isset( $data_attributes['screen-name'] ) ) {
|
119 |
+
$data_attributes['screen_name'] = $data_attributes['screen-name'];
|
120 |
+
unset( $data_attributes['screen-name'] );
|
121 |
+
}
|
122 |
+
if ( isset( $data_attributes['tweet-limit'] ) ) {
|
123 |
+
$data_attributes['limit'] = $data_attributes['tweet-limit'];
|
124 |
+
}
|
125 |
+
|
126 |
+
return array_merge( $instance, $data_attributes );
|
127 |
+
}
|
128 |
+
}
|
src/Twitter/WordPress/Widgets/Embeds/Timeline/Search.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2017 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add embedded search timeline as a WordPress widget
|
30 |
+
*
|
31 |
+
* @see http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
class Search extends \Twitter\WordPress\Widgets\Embeds\Timeline
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class of the related PHP object builder and validator
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const TIMELINE_CLASS = '\Twitter\Widgets\Embeds\Timeline\Search';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Class of the related shortcode handler
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const SHORTCODE_CLASS = '\Twitter\WordPress\Shortcodes\Embeds\Timeline\Search';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Describe the functionality offered by the widget
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @return string description of the widget functionality
|
61 |
+
*/
|
62 |
+
public static function getDescription()
|
63 |
+
{
|
64 |
+
return __( 'Recent Tweets matching a Twitter search', 'twitter' );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Fields specific to the timeline datasource configured in the widget
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*
|
72 |
+
* @param array $instance widget instance
|
73 |
+
*
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
protected function dataSourceFormElements( $instance )
|
77 |
+
{
|
78 |
+
$close_html_element = \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
79 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'widget_id' ) ); ?>"><?php echo esc_html( __( 'Twitter widget ID', 'twitter' ) . ':' ); ?></label>
|
80 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'widget_id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'widget_id' ) ); ?>" type="text" pattern="[0-9]+" inputmode="verbatim" spellcheck="false" value="<?php echo esc_attr( $instance['widget_id'] ); ?>" required<?php
|
81 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
82 |
+
echo $close_html_element;
|
83 |
+
?>><br<?php
|
84 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
85 |
+
echo $close_html_element;
|
86 |
+
?>><small><?php
|
87 |
+
printf(
|
88 |
+
esc_html( _x( 'Create a new widget ID at %s', 'Create a widget identifier at a URL', 'twitter' ) ),
|
89 |
+
'<a href="' . esc_url( 'https://twitter.com/settings/widgets/new/search', array( 'https', 'http' ) ) . '">' . esc_html( 'twitter.com/settings/widgets' ) . '</a>'
|
90 |
+
);
|
91 |
+
?></small></p><p><label for="<?php echo esc_attr( $this->get_field_id( 'terms' ) ); ?>"><?php echo esc_html( __( 'Search terms', 'twitter' ) . ':' ); ?></label><input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'terms' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'terms' ) ); ?>" type="text" maxlength="450" value="<?php echo esc_attr( $instance['terms'] ); ?>"<?php
|
92 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
93 |
+
echo $close_html_element;
|
94 |
+
?>></p>
|
95 |
+
<?php
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Update a widget instance
|
100 |
+
*
|
101 |
+
* @since 2.0.0
|
102 |
+
*
|
103 |
+
* @param array $new_instance New settings for this instance as input by the user via form()
|
104 |
+
* @param array $old_instance Old settings for this instance
|
105 |
+
*
|
106 |
+
* @return bool|array settings to save or false to cancel saving
|
107 |
+
*/
|
108 |
+
public function update( $new_instance, $old_instance )
|
109 |
+
{
|
110 |
+
$instance = array();
|
111 |
+
$new_instance = (array) $new_instance;
|
112 |
+
$title = sanitize_text_field( $new_instance['title'] );
|
113 |
+
if ( $title ) {
|
114 |
+
$instance['title'] = $title;
|
115 |
+
}
|
116 |
+
unset( $new_instance['title'] );
|
117 |
+
|
118 |
+
// process widget parameters as if they were parsed shortcode attributes
|
119 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
120 |
+
$timeline_class = static::TIMELINE_CLASS;
|
121 |
+
if ( ! ( method_exists( $timeline_class, 'fromArray' ) && method_exists( $shortcode_class, 'shortcodeAttributesToTimelineKeys' ) ) ) {
|
122 |
+
return false;
|
123 |
+
}
|
124 |
+
$timeline = $timeline_class::fromArray( $shortcode_class::shortcodeAttributesToTimelineKeys( $new_instance ) );
|
125 |
+
if ( ! ($timeline && $timeline->getWidgetID() && method_exists( $timeline, 'toArray' ) ) ) {
|
126 |
+
return false;
|
127 |
+
}
|
128 |
+
|
129 |
+
$data_attributes = $timeline->toArray();
|
130 |
+
// convert data-* dashes to shortcode underscores
|
131 |
+
if ( isset( $data_attributes['widget-id'] ) ) {
|
132 |
+
$data_attributes['widget_id'] = $data_attributes['widget-id'];
|
133 |
+
unset( $data_attributes['widget-id'] );
|
134 |
+
}
|
135 |
+
$data_attributes['terms'] = $timeline->getSearchTerms();
|
136 |
+
|
137 |
+
return array_merge( $instance, $data_attributes );
|
138 |
+
}
|
139 |
+
}
|
src/Twitter/WordPress/Widgets/Embeds/Timeline/TwitterList.php
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2016 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets\Embeds\Timeline;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add embedded list timeline as a WordPress widget
|
30 |
+
*
|
31 |
+
* @link http://codex.wordpress.org/Widgets_API WordPress widgets API
|
32 |
+
*
|
33 |
+
* @since 2.0.0
|
34 |
+
*/
|
35 |
+
class TwitterList extends Profile
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class of the related PHP object builder and validator
|
39 |
+
*
|
40 |
+
* @since 2.0.0
|
41 |
+
*
|
42 |
+
* @type string
|
43 |
+
*/
|
44 |
+
const TIMELINE_CLASS = '\Twitter\Widgets\Embeds\Timeline\TwitterList';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Class of the related shortcode handler
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @type string
|
52 |
+
*/
|
53 |
+
const SHORTCODE_CLASS = '\Twitter\WordPress\Shortcodes\Embeds\Timeline\TwitterList';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Describe the functionality offered by the widget
|
57 |
+
*
|
58 |
+
* @since 2.0.0
|
59 |
+
*
|
60 |
+
* @return string description of the widget functionality
|
61 |
+
*/
|
62 |
+
public static function getDescription()
|
63 |
+
{
|
64 |
+
return __( 'The latest Tweets from a list of Twitter accounts', 'twitter' );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Fields specific to the timeline datasource configured in the widget
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*
|
72 |
+
* @param array $instance widget instance
|
73 |
+
*
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
protected function dataSourceFormElements( $instance )
|
77 |
+
{
|
78 |
+
parent::dataSourceFormElements( $instance );
|
79 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'slug' ) ); ?>"><?php echo esc_html( _x( 'List slug', 'Unique identifier for Twitter user list', 'twitter' ) . ':' ); ?></label><input id="<?php echo esc_attr( $this->get_field_id( 'slug' ) ); ?>" class="widefat" name="<?php echo esc_attr( $this->get_field_name( 'slug' ) ); ?>" type="text" pattern="[a-z][a-z0-9_\\-]{0,24}" inputmode="verbatim" spellcheck="false" maxlength="24" value="<?php echo esc_attr( $instance['slug'] ); ?>"<?php
|
80 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
81 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
82 |
+
?>></p><?php
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Update a widget instance
|
87 |
+
*
|
88 |
+
* @since 2.0.0
|
89 |
+
*
|
90 |
+
* @param array $new_instance New settings for this instance as input by the user via form()
|
91 |
+
* @param array $old_instance Old settings for this instance
|
92 |
+
*
|
93 |
+
* @return bool|array settings to save or false to cancel saving
|
94 |
+
*/
|
95 |
+
public function update( $new_instance, $old_instance )
|
96 |
+
{
|
97 |
+
$new_instance = (array) $new_instance;
|
98 |
+
// a list must have a creator and a slug
|
99 |
+
if ( ! (isset( $new_instance['screen_name'] ) && $new_instance['screen_name'] && isset( $new_instance['slug'] ) && $new_instance['slug']) ) {
|
100 |
+
return false;
|
101 |
+
}
|
102 |
+
|
103 |
+
$instance = array();
|
104 |
+
$title = sanitize_text_field( $new_instance['title'] );
|
105 |
+
if ( $title ) {
|
106 |
+
$instance['title'] = $title;
|
107 |
+
}
|
108 |
+
unset( $new_instance['title'] );
|
109 |
+
|
110 |
+
// process widget parameters as if they were parsed shortcode attributes
|
111 |
+
$shortcode_class = static::SHORTCODE_CLASS;
|
112 |
+
$timeline_class = static::TIMELINE_CLASS;
|
113 |
+
if ( ! ( method_exists( $timeline_class, 'fromArray' ) && method_exists( $shortcode_class, 'shortcodeAttributesToTimelineKeys' ) ) ) {
|
114 |
+
return false;
|
115 |
+
}
|
116 |
+
$timeline = $timeline_class::fromArray( $shortcode_class::shortcodeAttributesToTimelineKeys( $new_instance ) );
|
117 |
+
if ( ! ($timeline && method_exists( $timeline, 'getScreenName' ) && $timeline->getScreenName() && method_exists( $timeline, 'getSlug' ) && $timeline->getSlug() && method_exists( $timeline, 'toArray' )) ) {
|
118 |
+
return false;
|
119 |
+
}
|
120 |
+
|
121 |
+
$data_attributes = $timeline->toArray();
|
122 |
+
// convert data-* dashes to shortcode underscores
|
123 |
+
if ( isset( $data_attributes['screen-name'] ) ) {
|
124 |
+
$data_attributes['screen_name'] = $data_attributes['screen-name'];
|
125 |
+
unset( $data_attributes['screen-name'] );
|
126 |
+
}
|
127 |
+
if ( isset( $data_attributes['tweet-limit'] ) ) {
|
128 |
+
$data_attributes['limit'] = $data_attributes['tweet-limit'];
|
129 |
+
}
|
130 |
+
|
131 |
+
return array_merge( $instance, $data_attributes );
|
132 |
+
}
|
133 |
+
}
|
src/Twitter/WordPress/Widgets/Widget.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2017 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Describe functions expected to be implemented by every widget class
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
abstract class Widget extends \WP_Widget
|
34 |
+
{
|
35 |
+
/**
|
36 |
+
* Allow a site author to include a title before the widget area
|
37 |
+
*
|
38 |
+
* @since 2.0.0
|
39 |
+
*
|
40 |
+
* @param array $instance settings for a particular instance of the widget
|
41 |
+
*
|
42 |
+
* @return void
|
43 |
+
*/
|
44 |
+
protected function titleFormElements( $instance )
|
45 |
+
{
|
46 |
+
?><p><label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php echo esc_html( __( 'Title', 'twitter' ) . ':' ); ?></label>
|
47 |
+
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( trim( strip_tags( $instance['title'] ) ) ); ?>"<?php
|
48 |
+
// @codingStandardsIgnoreLine WordPress.XSS.EscapeOutput.OutputNotEscaped
|
49 |
+
echo \Twitter\WordPress\Helpers\HTMLBuilder::closeVoidHTMLElement();
|
50 |
+
?>></p><?php
|
51 |
+
}
|
52 |
+
}
|
src/Twitter/WordPress/Widgets/WidgetInterface.php
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The MIT License (MIT)
|
4 |
+
|
5 |
+
Copyright (c) 2017 Twitter Inc.
|
6 |
+
|
7 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
of this software and associated documentation files (the "Software"), to deal
|
9 |
+
in the Software without restriction, including without limitation the rights
|
10 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
copies of the Software, and to permit persons to whom the Software is
|
12 |
+
furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
The above copyright notice and this permission notice shall be included in
|
15 |
+
all copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
THE SOFTWARE.
|
24 |
+
*/
|
25 |
+
|
26 |
+
namespace Twitter\WordPress\Widgets;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Describe functions expected to be implemented by every widget class
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*/
|
33 |
+
interface WidgetInterface
|
34 |
+
{
|
35 |
+
|
36 |
+
/**
|
37 |
+
* An individual widget constructor should call the \WP_Widget constructor
|
38 |
+
*
|
39 |
+
* @since 2.0.0
|
40 |
+
*/
|
41 |
+
function __construct();
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Describe the functionality offered by the widget
|
45 |
+
*
|
46 |
+
* @since 2.0.0
|
47 |
+
*
|
48 |
+
* @return string description of the widget functionality
|
49 |
+
*/
|
50 |
+
public static function getDescription();
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Front-end display of widget
|
54 |
+
*
|
55 |
+
* @since 2.0.0
|
56 |
+
*
|
57 |
+
* @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
|
58 |
+
* @param array $instance The settings for the particular instance of the widget
|
59 |
+
*
|
60 |
+
* @return void
|
61 |
+
*/
|
62 |
+
function widget( $args, $instance );
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Settings update form
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @param array $instance Current settings
|
70 |
+
*
|
71 |
+
* @return void
|
72 |
+
*/
|
73 |
+
public function form( $instance );
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Update a widget instance
|
77 |
+
*
|
78 |
+
* @since 2.0.0
|
79 |
+
*
|
80 |
+
* @param array $new_instance New settings for this instance as input by the user via form()
|
81 |
+
* @param array $old_instance Old settings for this instance
|
82 |
+
*
|
83 |
+
* @return bool|array settings to save or false to cancel saving
|
84 |
+
*/
|
85 |
+
public function update( $new_instance, $old_instance );
|
86 |
+
}
|
twitter.php
CHANGED
@@ -24,13 +24,13 @@ THE SOFTWARE.
|
|
24 |
*/
|
25 |
/**
|
26 |
* @package twitter
|
27 |
-
* @version
|
28 |
*/
|
29 |
/*
|
30 |
Plugin Name: Twitter
|
31 |
Plugin URI: http://wordpress.org/plugins/twitter/
|
32 |
Description: Official Twitter plugin for WordPress. Embed Twitter content and grow your audience on Twitter. Requires PHP 5.4 or greater.
|
33 |
-
Version:
|
34 |
Author: Twitter
|
35 |
Author URI: https://dev.twitter.com/
|
36 |
License: MIT
|
24 |
*/
|
25 |
/**
|
26 |
* @package twitter
|
27 |
+
* @version 2.0.0
|
28 |
*/
|
29 |
/*
|
30 |
Plugin Name: Twitter
|
31 |
Plugin URI: http://wordpress.org/plugins/twitter/
|
32 |
Description: Official Twitter plugin for WordPress. Embed Twitter content and grow your audience on Twitter. Requires PHP 5.4 or greater.
|
33 |
+
Version: 2.0.0
|
34 |
Author: Twitter
|
35 |
Author URI: https://dev.twitter.com/
|
36 |
License: MIT
|