Feeds for YouTube (YouTube video, channel, and gallery plugin) - Version 1.4.2

Version Description

  • Tested with WordPress 5.8 update.
  • Tweak: Added "play" icon to main player for the gallery layout.
  • Fix: Fixed an issue with GDPR Cookie Consent by Web Toffee integration.
  • Fix: Setting the height and width of a feed using a shortcode would not work without including the unit of measure.
Download this release

Release Info

Developer smashballoon
Plugin Icon 128x128 Feeds for YouTube (YouTube video, channel, and gallery plugin)
Version 1.4.2
Comparing to
See all releases

Code changes from version 1.4 to 1.4.2

README.txt CHANGED
@@ -1,11 +1,11 @@
1
- === Feeds for YouTube (YouTube video, channel, and gallery plugin) ===
2
  Author: Smash Balloon
3
  Contributors: smashballoon, craig-at-smash-balloon
4
  Support Website: http://smashballoon/youtube-feed/
5
  Tags: YouTube, YouTube feed, YouTube widget, YouTube channel, YouTube gallery
6
  Requires at least: 3.4
7
- Tested up to: 5.7
8
- Stable tag: 1.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -31,9 +31,9 @@ For simple step-by-step directions on how to set up the Feeds for YouTube plugin
31
 
32
  ### Benefits
33
  * **Increase social engagement** between you and your subscribers
34
- * **Save time** by using the plugin to generate dynamic, search engine crawlable content on your website
35
- * **Get more subscribers** by displaying your videos directly on your site
36
- * Display your channel content **your way** to perfectly match your website's style
37
  * The plugin is **updated regularly** with new features, bug-fixes and API changes
38
  * Support is quick, effective, and always happy to help
39
  * We're dedicated to providing the **most customizable**, **robust** and **well supported** YouTube gallery plugin in the world!
@@ -44,18 +44,16 @@ Customer support is a huge deal to us. We pride ourselves on always providing qu
44
  If you like the plugin then please consider leaving a review, as it really helps to support the plugin. If you have an issue then please allow us to help you fix it before leaving a review. Just [let us know](https://smashballoon.com/youtube-feed/support/?utm_source=wordpress&utm_campaign=sby 'Feeds for YouTube Support') what the problem is and we'll get back to you right away.
45
 
46
  ### Pro Version
47
- In order to maintain the free version of the plugin on an ongoing basis, and to provide quick and effective support for free, we offer a [Pro version](http://smashballoon.com/youtube-feed/?utm_source=wordpress&utm_campaign=sby 'Feeds for YouTube Pro') of the plugin which includes some awesome additional features to help you display your content in even more powerful ways:
48
 
49
  * Display YouTube videos from your **favorites list**
50
- * Integrate the **YouTube Live API** to show live streaming videos on your site.
51
  * Display a YouTube gallery in a carousel slider
52
  * Allow **filtering** of videos using keywords in the description or title
53
- * Fully functional **search endpoint** for display videos from a search result
54
  * **Combine multiple feeds** into one
55
- * Customizable **actions when video completes** like displaying a link to a product page for example, or displaying thumbnails of your other videos.
56
- * Download video data into a **custom post type** to allow visitors to browse and view videos on your website.
57
-
58
- Check out the [Pro version](http://smashballoon.com/youtube-feed/?utm_source=wordpress&utm_campaign=sby 'Feeds for YouTube Pro').
59
 
60
  ### How to use the "Feeds for YouTube" plugin
61
 
@@ -63,9 +61,9 @@ One of our main priorities has always been to make our plugins as easy as possib
63
 
64
  * 1) Click the "Log in to YouTube and connect an account" button on the "Feeds for YouTube" plugin settings page. This will prompt you to log into your Google account to authorize the plugin.
65
  * 2) Once you've connected your account, save the plugin settings.
66
- * 3) Then simply copy and paste the `[youtube-feed]` shortcode onto any page, post, or widget where you want your feed to be displayed.
67
 
68
- That's it! You can then customize the feed as needed using the settings on the plugin "Customize" page.
69
 
70
  For full step-by-step setup directions with screenshots, see [here](https://smashballoon.com/youtube-feed/free/ "YouTube Feed Free Setup Doc").
71
 
@@ -76,7 +74,7 @@ We're Smash Balloon; a fun-loving WordPress plugin development company birthed i
76
  To find out more about the team, see [here](https://smashballoon.com/about/ "Team Smash Balloon").
77
 
78
  == Installation ==
79
- 1. Install the plugin either via the WordPress plugin directory, or by uploading the files to your web server (in the /wp-content/plugins/ directory).
80
  2. Activate the plugin through the 'Plugins' menu in WordPress.
81
  3. Navigate to the 'Feeds for YouTube' settings page to configure your YouTube gallery.
82
  4. Use the shortcode [youtube-feed] in your page, post or widget to display your YouTube feed.
@@ -98,7 +96,7 @@ The Feeds for YouTube plugin is brand new and so we're currently working on impr
98
 
99
  5) Enter a channel name to display videos from.
100
 
101
- 6) Navigate to the Customize and Style pages to customize your feed.
102
 
103
  7) Once you've customized your feed, click on the "Display Your Feed" tab for directions on how to display your YouTube feed (or multiple feeds).
104
 
@@ -114,27 +112,27 @@ The Feeds for YouTube plugin is brand new and so we're currently working on impr
114
 
115
  = Can I display multiple YouTube feeds on my site or on the same page? =
116
 
117
- Yep. You can display multiple feeds by using our built-in shortcode options, for example: `[youtube-feed channel="smashballoon" num=3]`.
118
 
119
  = How do I embed a YouTube gallery directly into a WordPress page template? =
120
 
121
- You can embed a gallery directly into a template file by using the WordPress [do_shortcode](http://codex.wordpress.org/Function_Reference/do_shortcode) function: `<?php echo do_shortcode('[youtube-feed]'); ?>`.
122
 
123
  = Will the plugin work with W3 Total Cache or other caching plugins? =
124
 
125
- The Feeds for YouTube plugin should work in compatibility with most, if not all, caching plugins, but you may need to tweak the settings in order to allow the feed to update successfully and display your latest posts. If you are experiencing problems with your feed not updating then try disabling either 'Page Caching' or 'Object Caching' in W3 Total Cache (or any other similar caching plugin) to see whether that fixes the problem and the feed displays and updates successfully.
126
 
127
- = Can I change whether the video autoplays or plays on click =
128
 
129
  Yep, just use the following setting: Feeds for YouTube > Customize > Video Experience > When does video play? You can then set the video to play when clicked or to autoplay.
130
 
131
- = How can I change the layout of my feed? =
132
 
133
- This free plugin has several layout options built into it. Use the settings in the following location to display your videos in a list, grid, or gallery layout: Feeds for YouTube > Customize > Layout. You can also change the spacing/padding between the videos by using the "Spacing between videos" setting in this same section.
134
 
135
  = Can I select how many YouTube videos should be displayed in the feed? =
136
 
137
- Yep, you can choose to display between 1-50 videos in your feed by using the following setting: Feeds for YouTube > Customize > Layout > Number of Videos. The plugin also contains a "Load More" button to allow you to infinitely load more videos into your feed.
138
 
139
  = Will my YouTube gallery be responsive to accommodate mobile visitors? =
140
 
@@ -142,31 +140,40 @@ Yes. All feed layouts are completely mobile responsive. Using the plugin's galle
142
 
143
  = Will videos from my YouTube channel be cached? =
144
 
145
- Yes. The plugin will cache all of the posts collected from the API. Your YouTube videos and information about your channel can then be retrieved and used for future page loads.
146
 
147
- = How do I find the nickname of channel ID for different channels? =
148
 
149
- You can display videos from any channel using the unique YouTube channel ID. This can be found by viewing the channel page on YouTube and looking at the end of the URL. ex: https://www.youtube.com/channel/UC1a2b3c4D5F6g7i8j9k. You can also use the channel nickname.
150
 
151
  = Will displaying my YouTube channel affect the time it takes to load the page? =
152
 
153
- The plugin has a few features to minimize the impact it has on page load time. For example, iframes for playing YouTube videos are not loaded until the feed is interacted with by a visitor. Thumbnails of your videos are the smallest resolution necessary relative to the size of the feed. Also, these video thumbnails are not loaded until the rest of the content on the page is loaded.
154
 
155
- = How often do new videos from my channel appear in the feed? =
156
 
157
- By default, the plugin retrieves new videos for your YouTube gallery once every hour. You can reduce this to as little as 15 minutes if needed. You can even set your feed to update using WordPress cron in the background so the caching process is not relying on the page with your feed being visited.
158
 
159
  == Screenshots ==
160
 
161
  1. By default the plugin inherits styles from your theme
162
- 2. Display multiple feeds and customize each one
163
  3. When using the "grid" layout, videos open and play in a lightbox
164
  4. Feeds for YouTube Settings pages
165
- 5. Built in customization settings make customizing your feed easy
166
- 6. Use handy shortcode options to customize individual feeds
167
  7. To display a YouTube feed just copy and paste the [youtube-feed] shortcode into a widget or page
168
 
169
  == Changelog ==
 
 
 
 
 
 
 
 
 
170
  = 1.4 =
171
  * New: The locations of the YouTube feeds on your site will now be logged and listed on a single page for easier management. After this feature has been active for awhile, a "Feed Finder" link will appear next to the Feed Type setting on the plugin Settings page which allows you to see a list of all feeds on your site along with their locations.
172
  * Fix: Pro version of the Web Toffee GDPR Cookie Consent plugin was not being detected.
@@ -174,7 +181,7 @@ By default, the plugin retrieves new videos for your YouTube gallery once every
174
 
175
  = 1.3 =
176
  * New: Integrations with popular GDPR cookie consent solutions added. Visit the YouTube Feed settings page, Customize tab, GDPR section for more information.
177
- * Fix: Date that video was published would not always match what was shown on YouTube.com.
178
 
179
  = 1.2.4 =
180
  * Tweak: Minor update to item.php template to accommodate dynamic title attribute in lightbox.
1
+ === Feeds for YouTube (YouTube video, channel, and feed plugin) ===
2
  Author: Smash Balloon
3
  Contributors: smashballoon, craig-at-smash-balloon
4
  Support Website: http://smashballoon/youtube-feed/
5
  Tags: YouTube, YouTube feed, YouTube widget, YouTube channel, YouTube gallery
6
  Requires at least: 3.4
7
+ Tested up to: 5.8
8
+ Stable tag: 1.4.2
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
31
 
32
  ### Benefits
33
  * **Increase social engagement** between you and your subscribers
34
+ * **Save time** by using the plugin to generate dynamic, search engine crawlable YouTube feed content on your website
35
+ * **Get more subscribers** by displaying your YouTube videos directly on your site
36
+ * Display your YouTube channel content **your way** to perfectly match your website's style
37
  * The plugin is **updated regularly** with new features, bug-fixes and API changes
38
  * Support is quick, effective, and always happy to help
39
  * We're dedicated to providing the **most customizable**, **robust** and **well supported** YouTube gallery plugin in the world!
44
  If you like the plugin then please consider leaving a review, as it really helps to support the plugin. If you have an issue then please allow us to help you fix it before leaving a review. Just [let us know](https://smashballoon.com/youtube-feed/support/?utm_source=wordpress&utm_campaign=sby 'Feeds for YouTube Support') what the problem is and we'll get back to you right away.
45
 
46
  ### Pro Version
47
+ We offer a [Pro version](http://smashballoon.com/youtube-feed/?utm_source=wordpress&utm_campaign=sby 'Feeds for YouTube Pro') which includes some awesome additional features to help you display your content in even more powerful ways:
48
 
49
  * Display YouTube videos from your **favorites list**
50
+ * Integrate the **YouTube Live API** to show live streaming YouTube videos on your site.
51
  * Display a YouTube gallery in a carousel slider
52
  * Allow **filtering** of videos using keywords in the description or title
53
+ * Fully functional **search endpoint** for display YouTube videos from a search result
54
  * **Combine multiple feeds** into one
55
+ * Customizable **actions when video completes** like displaying a link to a product page for example, or displaying thumbnails of your other YouTube videos.
56
+ * Download video data into a **custom post type** to allow visitors to browse and view YouTube videos on your website.
 
 
57
 
58
  ### How to use the "Feeds for YouTube" plugin
59
 
61
 
62
  * 1) Click the "Log in to YouTube and connect an account" button on the "Feeds for YouTube" plugin settings page. This will prompt you to log into your Google account to authorize the plugin.
63
  * 2) Once you've connected your account, save the plugin settings.
64
+ * 3) Then simply copy and paste the `[youtube-feed]` shortcode onto any page, post, or widget where you want your YouTube feed to be displayed.
65
 
66
+ That's it! You can then customize the YouTube feed as needed using the settings on the plugin "Customize" page.
67
 
68
  For full step-by-step setup directions with screenshots, see [here](https://smashballoon.com/youtube-feed/free/ "YouTube Feed Free Setup Doc").
69
 
74
  To find out more about the team, see [here](https://smashballoon.com/about/ "Team Smash Balloon").
75
 
76
  == Installation ==
77
+ 1. Install the Feeds for YouTube plugin either via the WordPress plugin directory, or by uploading the files to your web server (in the /wp-content/plugins/ directory).
78
  2. Activate the plugin through the 'Plugins' menu in WordPress.
79
  3. Navigate to the 'Feeds for YouTube' settings page to configure your YouTube gallery.
80
  4. Use the shortcode [youtube-feed] in your page, post or widget to display your YouTube feed.
96
 
97
  5) Enter a channel name to display videos from.
98
 
99
+ 6) Navigate to the Customize and Style pages to customize your YouTube feed.
100
 
101
  7) Once you've customized your feed, click on the "Display Your Feed" tab for directions on how to display your YouTube feed (or multiple feeds).
102
 
112
 
113
  = Can I display multiple YouTube feeds on my site or on the same page? =
114
 
115
+ Yep. You can display multiple YouTube feeds by using our built-in shortcode options, for example: `[youtube-feed channel="smashballoon" num=3]`.
116
 
117
  = How do I embed a YouTube gallery directly into a WordPress page template? =
118
 
119
+ You can embed a YouTube gallery directly into a template file by using the WordPress [do_shortcode](http://codex.wordpress.org/Function_Reference/do_shortcode) function: `<?php echo do_shortcode('[youtube-feed]'); ?>`.
120
 
121
  = Will the plugin work with W3 Total Cache or other caching plugins? =
122
 
123
+ The Feeds for YouTube plugin should work in compatibility with most, if not all, caching plugins, but you may need to tweak the settings in order to allow the feed to update successfully and display your latest posts. If you are experiencing problems with your YouTube feed not updating then try disabling either 'Page Caching' or 'Object Caching' in W3 Total Cache (or any other similar caching plugin) to see whether that fixes the problem and the feed displays and updates successfully.
124
 
125
+ = Can I change whether the YouTube video autoplays or plays on click =
126
 
127
  Yep, just use the following setting: Feeds for YouTube > Customize > Video Experience > When does video play? You can then set the video to play when clicked or to autoplay.
128
 
129
+ = How can I change the layout of my YouTube feed? =
130
 
131
+ This free plugin has several layout options built into it. Use the settings in the following location to display your YouTube videos in a list, grid, or gallery layout: Feeds for YouTube > Customize > Layout. You can also change the spacing/padding between the videos by using the "Spacing between videos" setting in this same section.
132
 
133
  = Can I select how many YouTube videos should be displayed in the feed? =
134
 
135
+ Yep, you can choose to display between 1-50 videos in your YouTube feed by using the following setting: Feeds for YouTube > Customize > Layout > Number of Videos. The plugin also contains a "Load More" button to allow you to infinitely load more videos into your feed.
136
 
137
  = Will my YouTube gallery be responsive to accommodate mobile visitors? =
138
 
140
 
141
  = Will videos from my YouTube channel be cached? =
142
 
143
+ Yes. The plugin will cache all of the posts collected from the YouTube API. Your YouTube videos and information about your YouTube channel can then be retrieved and used for future page loads.
144
 
145
+ = How do I find the nickname or channel ID for different YouTube channels? =
146
 
147
+ You can display videos from any YouTube channel using the unique YouTube channel ID. This can be found by viewing the channel page on YouTube and looking at the end of the URL. ex: https://www.youtube.com/channel/UC1a2b3c4D5F6g7i8j9k. You can also use the YouTube channel nickname.
148
 
149
  = Will displaying my YouTube channel affect the time it takes to load the page? =
150
 
151
+ The plugin has a few features to minimize the impact it has on page load time. For example, iframes for playing YouTube videos are not loaded until the feed is interacted with by a visitor. Thumbnails of your YouTube videos are the smallest resolution necessary relative to the size of the feed. Also, these video thumbnails are not loaded until the rest of the content on the page is loaded.
152
 
153
+ = How often do new videos from my YouTube channel appear in the feed? =
154
 
155
+ By default, the plugin retrieves new videos for your YouTube gallery once every hour. You can reduce this to as little as 15 minutes if needed. You can even set your feed to update using WordPress cron in the background so the caching process is not relying on the page with your YouTube feed being visited.
156
 
157
  == Screenshots ==
158
 
159
  1. By default the plugin inherits styles from your theme
160
+ 2. Display multiple YouTube feeds and customize each one
161
  3. When using the "grid" layout, videos open and play in a lightbox
162
  4. Feeds for YouTube Settings pages
163
+ 5. Built in customization settings make customizing your YouTube feed easy
164
+ 6. Use handy shortcode options to customize individual YouTube feeds
165
  7. To display a YouTube feed just copy and paste the [youtube-feed] shortcode into a widget or page
166
 
167
  == Changelog ==
168
+ = 1.4.2 =
169
+ * Tested with WordPress 5.8 update.
170
+ * Tweak: Added "play" icon to main player for the gallery layout.
171
+ * Fix: Fixed an issue with GDPR Cookie Consent by Web Toffee integration.
172
+ * Fix: Setting the height and width of a feed using a shortcode would not work without including the unit of measure.
173
+
174
+ = 1.4.1 =
175
+ * Fix: Fixed several issues with GDPR Cookie Consent by Web Toffee integration.
176
+
177
  = 1.4 =
178
  * New: The locations of the YouTube feeds on your site will now be logged and listed on a single page for easier management. After this feature has been active for awhile, a "Feed Finder" link will appear next to the Feed Type setting on the plugin Settings page which allows you to see a list of all feeds on your site along with their locations.
179
  * Fix: Pro version of the Web Toffee GDPR Cookie Consent plugin was not being detected.
181
 
182
  = 1.3 =
183
  * New: Integrations with popular GDPR cookie consent solutions added. Visit the YouTube Feed settings page, Customize tab, GDPR section for more information.
184
+ * Fix: Date that YouTube video was published would not always match what was shown on YouTube.com.
185
 
186
  = 1.2.4 =
187
  * Tweak: Minor update to item.php template to accommodate dynamic title attribute in lightbox.
css/admin-notifications.css CHANGED
@@ -1,171 +1,171 @@
1
- #sby-notifications {
2
- position: relative;
3
- background: #FFFFFF 0 0 no-repeat padding-box;
4
- box-shadow: 0px 5px 15px #0000000D;
5
- border-radius: 6px;
6
- opacity: 1;
7
- min-height: 48px;
8
- padding: 15px 102px 15px 72px;
9
- margin: 0 0 14px 0;
10
- }
11
-
12
- #sby-notifications * {
13
- box-sizing: border-box;
14
- }
15
-
16
- #sby-notifications .bell,
17
- #sby-notifications .thumb{
18
- position: absolute;
19
- top: 15px;
20
- left: 15px;
21
- width: 42px;
22
- height: 48px;
23
- }
24
- #sby-notifications .thumb img {
25
- max-width: 100%;
26
- }
27
- #sby-notifications .thumb .img-overlay {
28
- top: 42px;
29
- left: -6px;
30
- width: 54px;
31
- position: absolute;
32
- background: #ca4a1f;
33
- color: #fff;
34
- padding: 2px 4px;
35
- border-radius: 3px;
36
- line-height: 1;
37
- font-size: 11px;
38
- font-weight: bold;
39
- text-align: center;
40
- }
41
-
42
- #sby-notifications .messages .message {
43
- display: none;
44
- }
45
-
46
- #sby-notifications .messages .message.current {
47
- display: block;
48
- }
49
-
50
- #sby-notifications .messages .message .title {
51
- font-weight: bold;
52
- font-size: 17px;
53
- line-height: 20px;
54
- margin: 0;
55
- color: #444;
56
- }
57
-
58
- #sby-notifications .messages .message .content {
59
- font-weight: normal;
60
- font-size: 13px;
61
- line-height: 20px;
62
- margin: 6px 0 40px 0;
63
- }
64
-
65
- #sby-notifications .messages .message .buttons {
66
- margin: -30px 80px 0 0;
67
- }
68
-
69
- #sby-notifications .messages .message .buttons a {
70
- margin: 0 6px 0 0;
71
- padding: 8px 10px;
72
- line-height: 13px;
73
- font-size: 13px;
74
- min-height: unset;
75
- }
76
-
77
- #sby-notifications .messages .message .buttons .button-secondary {
78
- border: 1px solid #0071A1;
79
- }
80
-
81
- #sby-notifications .dismiss {
82
- position: absolute;
83
- top: 15px;
84
- right: 15px;
85
- width: 16px;
86
- height: 16px;
87
- color: #72777C;
88
- font-size: 16px;
89
- cursor: pointer;
90
- text-align: center;
91
- vertical-align: middle;
92
- line-height: 16px;
93
- }
94
-
95
- #sby-notifications .dismiss:hover {
96
- color: #dc3232;
97
- }
98
-
99
- #sby-notifications .navigation {
100
- position: absolute;
101
- bottom: 15px;
102
- right: 15px;
103
- width: 63px;
104
- height: 30px;
105
- }
106
-
107
- #sby-notifications .navigation a {
108
- display: block;
109
- width: 30px;
110
- height: 30px;
111
- border: 1px solid #7E8993;
112
- border-radius: 3px;
113
- font-size: 8px;
114
- text-align: center;
115
- vertical-align: middle;
116
- line-height: 30px;
117
- cursor: pointer;
118
- background-color: #ffffff;
119
- color: #41454A;
120
- }
121
- #sby-notifications .navigation svg {
122
- width: 8px;
123
- height: 8px;
124
- }
125
-
126
- #sby-notifications .navigation a:hover {
127
- background-color: #f1f1f1;
128
- }
129
-
130
- #sby-notifications .navigation .prev {
131
- float: left;
132
- }
133
-
134
- #sby-notifications .navigation .next {
135
- float: right;
136
- }
137
-
138
- #sby-notifications .navigation .disabled {
139
- border-color: #dddddd;
140
- color: #A0A5AA;
141
- cursor: default;
142
- }
143
-
144
- #sby-notifications .navigation .disabled:hover {
145
- background-color: #ffffff;
146
- }
147
-
148
- @media screen and (max-width: 768px) {
149
- #sby-notifications {
150
- padding: 15px 15px 15px 72px;
151
- }
152
- #sby-notifications .messages .message .title {
153
- margin: 0 30px 0 0;
154
- }
155
- #sby-notifications .messages .message .content {
156
- font-size: 16px;
157
- line-height: 24px;
158
- }
159
- #sby-notifications .messages .message .buttons {
160
- margin: -30px 80px 0 0;
161
- }
162
- #sby-notifications .messages .message .buttons a {
163
- margin: 0;
164
- display: table;
165
- }
166
- #sby-notifications .messages .message .buttons .button-secondary {
167
- margin-top: 6px;
168
- }
169
- }
170
-
171
- /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2Nzcy9hZG1pbi1ub3RpZmljYXRpb25zLmNzcyIsInNvdXJjZXMiOlsiYXNzZXRzL3Njc3MvYWRtaW4tbm90aWZpY2F0aW9ucy5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIEFkbWluIG5vdGlmaWNhdGlvbiBzdHlsZXMuXG5cbiN3cGZvcm1zLW5vdGlmaWNhdGlvbnMge1xuXG5cdHBvc2l0aW9uOiByZWxhdGl2ZTtcblx0YmFja2dyb3VuZDogI0ZGRkZGRiAwIDAgbm8tcmVwZWF0IHBhZGRpbmctYm94O1xuXHRib3gtc2hhZG93OiAwcHggNXB4IDE1cHggIzAwMDAwMDBEO1xuXHRib3JkZXItcmFkaXVzOiA2cHg7XG5cdG9wYWNpdHk6IDE7XG5cdG1pbi1oZWlnaHQ6IDQ4cHg7XG5cdHBhZGRpbmc6IDE1cHggMTAycHggMTVweCA3MnB4O1xuXHRtYXJnaW46IDAgMCAxNHB4IDA7XG5cblx0KiB7XG5cdFx0Ym94LXNpemluZzogYm9yZGVyLWJveDtcblx0fVxuXG5cdC5iZWxsIHtcblx0XHRwb3NpdGlvbjogYWJzb2x1dGU7XG5cdFx0dG9wOiAxNXB4O1xuXHRcdGxlZnQ6IDE1cHg7XG5cdFx0d2lkdGg6IDQycHg7XG5cdFx0aGVpZ2h0OiA0OHB4O1xuXHR9XG5cblx0Lm1lc3NhZ2VzIHtcblx0XHQubWVzc2FnZSB7XG5cdFx0XHRkaXNwbGF5OiBub25lO1xuXG5cdFx0XHQmLmN1cnJlbnQge1xuXHRcdFx0XHRkaXNwbGF5OiBibG9jaztcblx0XHRcdH1cblxuXHRcdFx0LnRpdGxlIHtcblx0XHRcdFx0Zm9udC13ZWlnaHQ6IGJvbGQ7XG5cdFx0XHRcdGZvbnQtc2l6ZTogMTdweDtcblx0XHRcdFx0bGluZS1oZWlnaHQ6IDIwcHg7XG5cdFx0XHRcdG1hcmdpbjogMDtcblx0XHRcdFx0Y29sb3I6ICM0NDQ7XG5cdFx0XHR9XG5cblx0XHRcdC5jb250ZW50IHtcblx0XHRcdFx0Zm9udC13ZWlnaHQ6IG5vcm1hbDtcblx0XHRcdFx0Zm9udC1zaXplOiAxM3B4O1xuXHRcdFx0XHRsaW5lLWhlaWdodDogMjBweDtcblx0XHRcdFx0bWFyZ2luOiA2cHggMCA0MHB4IDA7XG5cdFx0XHR9XG5cblx0XHRcdC5idXR0b25zIHtcblx0XHRcdFx0bWFyZ2luOiAtMzBweCA4MHB4IDAgMDtcblxuXHRcdFx0XHRhIHtcblx0XHRcdFx0XHRtYXJnaW46IDAgNnB4IDAgMDtcblx0XHRcdFx0XHRwYWRkaW5nOiA4cHggMTBweDtcblx0XHRcdFx0XHRsaW5lLWhlaWdodDogMTNweDtcblx0XHRcdFx0XHRmb250LXNpemU6IDEzcHg7XG5cdFx0XHRcdFx0bWluLWhlaWdodDogdW5zZXQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQuYnV0dG9uLXNlY29uZGFyeSB7XG5cdFx0XHRcdFx0Ym9yZGVyOiAxcHggc29saWQgIzAwNzFBMTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC5kaXNtaXNzIHtcblx0XHRwb3NpdGlvbjogYWJzb2x1dGU7XG5cdFx0dG9wOiAxNXB4O1xuXHRcdHJpZ2h0OiAxNXB4O1xuXHRcdHdpZHRoOiAxNnB4O1xuXHRcdGhlaWdodDogMTZweDtcblx0XHRjb2xvcjogIzcyNzc3Qztcblx0XHRmb250LXNpemU6IDE2cHg7XG5cdFx0Y3Vyc29yOiBwb2ludGVyO1xuXHRcdHRleHQtYWxpZ246IGNlbnRlcjtcblx0XHR2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xuXHRcdGxpbmUtaGVpZ2h0OiAxNnB4O1xuXG5cdFx0Jjpob3ZlciB7XG5cdFx0XHRjb2xvcjogI2RjMzIzMjtcblx0XHR9XG5cdH1cblxuXHQubmF2aWdhdGlvbiB7XG5cdFx0cG9zaXRpb246IGFic29sdXRlO1xuXHRcdGJvdHRvbTogMTVweDtcblx0XHRyaWdodDogMTVweDtcblx0XHR3aWR0aDogNjNweDtcblx0XHRoZWlnaHQ6IDMwcHg7XG5cblx0XHRhIHtcblx0XHRcdGRpc3BsYXk6IGJsb2NrO1xuXHRcdFx0d2lkdGg6IDMwcHg7XG5cdFx0XHRoZWlnaHQ6IDMwcHg7XG5cdFx0XHRib3JkZXI6IDFweCBzb2xpZCAjN0U4OTkzO1xuXHRcdFx0Ym9yZGVyLXJhZGl1czogM3B4O1xuXHRcdFx0Zm9udC1zaXplOiA4cHg7XG5cdFx0XHR0ZXh0LWFsaWduOiBjZW50ZXI7XG5cdFx0XHR2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xuXHRcdFx0bGluZS1oZWlnaHQ6IDMwcHg7XG5cdFx0XHRjdXJzb3I6IHBvaW50ZXI7XG5cdFx0XHRiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuXHRcdFx0Y29sb3I6ICM0MTQ1NEE7XG5cblx0XHRcdCY6aG92ZXIge1xuXHRcdFx0XHRiYWNrZ3JvdW5kLWNvbG9yOiAjZjFmMWYxO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC5wcmV2IHtcblx0XHRcdGZsb2F0OiBsZWZ0O1xuXHRcdH1cblxuXHRcdC5uZXh0IHtcblx0XHRcdGZsb2F0OiByaWdodDtcblx0XHR9XG5cblx0XHQuZGlzYWJsZWQge1xuXHRcdFx0Ym9yZGVyLWNvbG9yOiAjZGRkZGRkO1xuXHRcdFx0Y29sb3I6ICNBMEE1QUE7XG5cdFx0XHRjdXJzb3I6IGRlZmF1bHQ7XG5cblx0XHRcdCY6aG92ZXIge1xuXHRcdFx0XHRiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG5AbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOiA3NjhweCkge1xuXG5cdCN3cGZvcm1zLW5vdGlmaWNhdGlvbnMge1xuXHRcdHBhZGRpbmc6IDE1cHggMTVweCAxNXB4IDcycHg7XG5cblx0XHQubWVzc2FnZXMge1xuXG5cdFx0XHQubWVzc2FnZSB7XG5cblx0XHRcdFx0LnRpdGxlIHtcblx0XHRcdFx0XHRtYXJnaW46IDAgMzBweCAwIDA7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQuY29udGVudCB7XG5cdFx0XHRcdFx0Zm9udC1zaXplOiAxNnB4O1xuXHRcdFx0XHRcdGxpbmUtaGVpZ2h0OiAyNHB4XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQuYnV0dG9ucyB7XG5cdFx0XHRcdFx0bWFyZ2luOiAtMzBweCA4MHB4IDAgMDtcblxuXHRcdFx0XHRcdGEge1xuXHRcdFx0XHRcdFx0bWFyZ2luOiAwO1xuXHRcdFx0XHRcdFx0ZGlzcGxheTogdGFibGU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0LmJ1dHRvbi1zZWNvbmRhcnkge1xuXHRcdFx0XHRcdFx0bWFyZ2luLXRvcDogNnB4O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxBQUFBLHNCQUFzQixDQUFDO0VBRXRCLFFBQVEsRUFBRSxRQUFRO0VBQ2xCLFVBQVUsRUFBRSxpQ0FBaUM7RUFDN0MsVUFBVSxFQUFFLHNCQUFzQjtFQUNsQyxhQUFhLEVBQUUsR0FBRztFQUNsQixPQUFPLEVBQUUsQ0FBQztFQUNWLFVBQVUsRUFBRSxJQUFJO0VBQ2hCLE9BQU8sRUFBRSxvQkFBb0I7RUFDN0IsTUFBTSxFQUFFLFVBQVU7Q0FxSGxCOztBQTlIRCxBQVdDLHNCQVhxQixDQVdyQixDQUFDLENBQUM7RUFDRCxVQUFVLEVBQUUsVUFBVTtDQUN0Qjs7QUFiRixBQWVDLHNCQWZxQixDQWVyQixLQUFLLENBQUM7RUFDTCxRQUFRLEVBQUUsUUFBUTtFQUNsQixHQUFHLEVBQUUsSUFBSTtFQUNULElBQUksRUFBRSxJQUFJO0VBQ1YsS0FBSyxFQUFFLElBQUk7RUFDWCxNQUFNLEVBQUUsSUFBSTtDQUNaOztBQXJCRixBQXdCRSxzQkF4Qm9CLENBdUJyQixTQUFTLENBQ1IsUUFBUSxDQUFDO0VBQ1IsT0FBTyxFQUFFLElBQUk7Q0FvQ2I7O0FBN0RILEFBMkJHLHNCQTNCbUIsQ0F1QnJCLFNBQVMsQ0FDUixRQUFRLEFBR04sUUFBUSxDQUFDO0VBQ1QsT0FBTyxFQUFFLEtBQUs7Q0FDZDs7QUE3QkosQUErQkcsc0JBL0JtQixDQXVCckIsU0FBUyxDQUNSLFFBQVEsQ0FPUCxNQUFNLENBQUM7RUFDTixXQUFXLEVBQUUsSUFBSTtFQUNqQixTQUFTLEVBQUUsSUFBSTtFQUNmLFdBQVcsRUFBRSxJQUFJO0VBQ2pCLE1BQU0sRUFBRSxDQUFDO0VBQ1QsS0FBSyxFQUFFLElBQUk7Q0FDWDs7QUFyQ0osQUF1Q0csc0JBdkNtQixDQXVCckIsU0FBUyxDQUNSLFFBQVEsQ0FlUCxRQUFRLENBQUM7RUFDUixXQUFXLEVBQUUsTUFBTTtFQUNuQixTQUFTLEVBQUUsSUFBSTtFQUNmLFdBQVcsRUFBRSxJQUFJO0VBQ2pCLE1BQU0sRUFBRSxZQUFZO0NBQ3BCOztBQTVDSixBQThDRyxzQkE5Q21CLENBdUJyQixTQUFTLENBQ1IsUUFBUSxDQXNCUCxRQUFRLENBQUM7RUFDUixNQUFNLEVBQUUsY0FBYztDQWF0Qjs7QUE1REosQUFpREksc0JBakRrQixDQXVCckIsU0FBUyxDQUNSLFFBQVEsQ0FzQlAsUUFBUSxDQUdQLENBQUMsQ0FBQztFQUNELE1BQU0sRUFBRSxTQUFTO0VBQ2pCLE9BQU8sRUFBRSxRQUFRO0VBQ2pCLFdBQVcsRUFBRSxJQUFJO0VBQ2pCLFNBQVMsRUFBRSxJQUFJO0VBQ2YsVUFBVSxFQUFFLEtBQUs7Q0FDakI7O0FBdkRMLEFBeURJLHNCQXpEa0IsQ0F1QnJCLFNBQVMsQ0FDUixRQUFRLENBc0JQLFFBQVEsQ0FXUCxpQkFBaUIsQ0FBQztFQUNqQixNQUFNLEVBQUUsaUJBQWlCO0NBQ3pCOztBQTNETCxBQWdFQyxzQkFoRXFCLENBZ0VyQixRQUFRLENBQUM7RUFDUixRQUFRLEVBQUUsUUFBUTtFQUNsQixHQUFHLEVBQUUsSUFBSTtFQUNULEtBQUssRUFBRSxJQUFJO0VBQ1gsS0FBSyxFQUFFLElBQUk7RUFDWCxNQUFNLEVBQUUsSUFBSTtFQUNaLEtBQUssRUFBRSxPQUFPO0VBQ2QsU0FBUyxFQUFFLElBQUk7RUFDZixNQUFNLEVBQUUsT0FBTztFQUNmLFVBQVUsRUFBRSxNQUFNO0VBQ2xCLGNBQWMsRUFBRSxNQUFNO0VBQ3RCLFdBQVcsRUFBRSxJQUFJO0NBS2pCOztBQWhGRixBQTZFRSxzQkE3RW9CLENBZ0VyQixRQUFRLEFBYU4sTUFBTSxDQUFDO0VBQ1AsS0FBSyxFQUFFLE9BQU87Q0FDZDs7QUEvRUgsQUFrRkMsc0JBbEZxQixDQWtGckIsV0FBVyxDQUFDO0VBQ1gsUUFBUSxFQUFFLFFBQVE7RUFDbEIsTUFBTSxFQUFFLElBQUk7RUFDWixLQUFLLEVBQUUsSUFBSTtFQUNYLEtBQUssRUFBRSxJQUFJO0VBQ1gsTUFBTSxFQUFFLElBQUk7Q0FzQ1o7O0FBN0hGLEFBeUZFLHNCQXpGb0IsQ0FrRnJCLFdBQVcsQ0FPVixDQUFDLENBQUM7RUFDRCxPQUFPLEVBQUUsS0FBSztFQUNkLEtBQUssRUFBRSxJQUFJO0VBQ1gsTUFBTSxFQUFFLElBQUk7RUFDWixNQUFNLEVBQUUsaUJBQWlCO0VBQ3pCLGFBQWEsRUFBRSxHQUFHO0VBQ2xCLFNBQVMsRUFBRSxHQUFHO0VBQ2QsVUFBVSxFQUFFLE1BQU07RUFDbEIsY0FBYyxFQUFFLE1BQU07RUFDdEIsV0FBVyxFQUFFLElBQUk7RUFDakIsTUFBTSxFQUFFLE9BQU87RUFDZixnQkFBZ0IsRUFBRSxPQUFPO0VBQ3pCLEtBQUssRUFBRSxPQUFPO0NBS2Q7O0FBMUdILEFBdUdHLHNCQXZHbUIsQ0FrRnJCLFdBQVcsQ0FPVixDQUFDLEFBY0MsTUFBTSxDQUFDO0VBQ1AsZ0JBQWdCLEVBQUUsT0FBTztDQUN6Qjs7QUF6R0osQUE0R0Usc0JBNUdvQixDQWtGckIsV0FBVyxDQTBCVixLQUFLLENBQUM7RUFDTCxLQUFLLEVBQUUsSUFBSTtDQUNYOztBQTlHSCxBQWdIRSxzQkFoSG9CLENBa0ZyQixXQUFXLENBOEJWLEtBQUssQ0FBQztFQUNMLEtBQUssRUFBRSxLQUFLO0NBQ1o7O0FBbEhILEFBb0hFLHNCQXBIb0IsQ0FrRnJCLFdBQVcsQ0FrQ1YsU0FBUyxDQUFDO0VBQ1QsWUFBWSxFQUFFLE9BQU87RUFDckIsS0FBSyxFQUFFLE9BQU87RUFDZCxNQUFNLEVBQUUsT0FBTztDQUtmOztBQTVISCxBQXlIRyxzQkF6SG1CLENBa0ZyQixXQUFXLENBa0NWLFNBQVMsQUFLUCxNQUFNLENBQUM7RUFDUCxnQkFBZ0IsRUFBRSxPQUFPO0NBQ3pCOztBQUtKLE1BQU0sQ0FBQyxNQUFNLE1BQU0sU0FBUyxFQUFFLEtBQUs7RUFFbEMsQUFBQSxzQkFBc0IsQ0FBQztJQUN0QixPQUFPLEVBQUUsbUJBQW1CO0dBNkI1QjtFQTlCRCxBQU9HLHNCQVBtQixDQUdyQixTQUFTLENBRVIsUUFBUSxDQUVQLE1BQU0sQ0FBQztJQUNOLE1BQU0sRUFBRSxVQUFVO0dBQ2xCO0VBVEosQUFXRyxzQkFYbUIsQ0FHckIsU0FBUyxDQUVSLFFBQVEsQ0FNUCxRQUFRLENBQUM7SUFDUixTQUFTLEVBQUUsSUFBSTtJQUNmLFdBQVcsRUFBRSxJQUNkO0dBQUM7RUFkSixBQWdCRyxzQkFoQm1CLENBR3JCLFNBQVMsQ0FFUixRQUFRLENBV1AsUUFBUSxDQUFDO0lBQ1IsTUFBTSxFQUFFLGNBQWM7R0FVdEI7RUEzQkosQUFtQkksc0JBbkJrQixDQUdyQixTQUFTLENBRVIsUUFBUSxDQVdQLFFBQVEsQ0FHUCxDQUFDLENBQUM7SUFDRCxNQUFNLEVBQUUsQ0FBQztJQUNULE9BQU8sRUFBRSxLQUFLO0dBQ2Q7RUF0QkwsQUF3Qkksc0JBeEJrQixDQUdyQixTQUFTLENBRVIsUUFBUSxDQVdQLFFBQVEsQ0FRUCxpQkFBaUIsQ0FBQztJQUNqQixVQUFVLEVBQUUsR0FBRztHQUNmIn0= */
1
+ #sby-notifications {
2
+ position: relative;
3
+ background: #FFFFFF 0 0 no-repeat padding-box;
4
+ box-shadow: 0px 5px 15px #0000000D;
5
+ border-radius: 6px;
6
+ opacity: 1;
7
+ min-height: 48px;
8
+ padding: 15px 102px 15px 72px;
9
+ margin: 0 0 14px 0;
10
+ }
11
+
12
+ #sby-notifications * {
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ #sby-notifications .bell,
17
+ #sby-notifications .thumb{
18
+ position: absolute;
19
+ top: 15px;
20
+ left: 15px;
21
+ width: 42px;
22
+ height: 48px;
23
+ }
24
+ #sby-notifications .thumb img {
25
+ max-width: 100%;
26
+ }
27
+ #sby-notifications .thumb .img-overlay {
28
+ top: 42px;
29
+ left: -6px;
30
+ width: 54px;
31
+ position: absolute;
32
+ background: #ca4a1f;
33
+ color: #fff;
34
+ padding: 2px 4px;
35
+ border-radius: 3px;
36
+ line-height: 1;
37
+ font-size: 11px;
38
+ font-weight: bold;
39
+ text-align: center;
40
+ }
41
+
42
+ #sby-notifications .messages .message {
43
+ display: none;
44
+ }
45
+
46
+ #sby-notifications .messages .message.current {
47
+ display: block;
48
+ }
49
+
50
+ #sby-notifications .messages .message .title {
51
+ font-weight: bold;
52
+ font-size: 17px;
53
+ line-height: 20px;
54
+ margin: 0;
55
+ color: #444;
56
+ }
57
+
58
+ #sby-notifications .messages .message .content {
59
+ font-weight: normal;
60
+ font-size: 13px;
61
+ line-height: 20px;
62
+ margin: 6px 0 40px 0;
63
+ }
64
+
65
+ #sby-notifications .messages .message .buttons {
66
+ margin: -30px 80px 0 0;
67
+ }
68
+
69
+ #sby-notifications .messages .message .buttons a {
70
+ margin: 0 6px 0 0;
71
+ padding: 8px 10px;
72
+ line-height: 13px;
73
+ font-size: 13px;
74
+ min-height: unset;
75
+ }
76
+
77
+ #sby-notifications .messages .message .buttons .button-secondary {
78
+ border: 1px solid #0071A1;
79
+ }
80
+
81
+ #sby-notifications .dismiss {
82
+ position: absolute;
83
+ top: 15px;
84
+ right: 15px;
85
+ width: 16px;
86
+ height: 16px;
87
+ color: #72777C;
88
+ font-size: 16px;
89
+ cursor: pointer;
90
+ text-align: center;
91
+ vertical-align: middle;
92
+ line-height: 16px;
93
+ }
94
+
95
+ #sby-notifications .dismiss:hover {
96
+ color: #dc3232;
97
+ }
98
+
99
+ #sby-notifications .navigation {
100
+ position: absolute;
101
+ bottom: 15px;
102
+ right: 15px;
103
+ width: 63px;
104
+ height: 30px;
105
+ }
106
+
107
+ #sby-notifications .navigation a {
108
+ display: block;
109
+ width: 30px;
110
+ height: 30px;
111
+ border: 1px solid #7E8993;
112
+ border-radius: 3px;
113
+ font-size: 8px;
114
+ text-align: center;
115
+ vertical-align: middle;
116
+ line-height: 30px;
117
+ cursor: pointer;
118
+ background-color: #ffffff;
119
+ color: #41454A;
120
+ }
121
+ #sby-notifications .navigation svg {
122
+ width: 8px;
123
+ height: 8px;
124
+ }
125
+
126
+ #sby-notifications .navigation a:hover {
127
+ background-color: #f1f1f1;
128
+ }
129
+
130
+ #sby-notifications .navigation .prev {
131
+ float: left;
132
+ }
133
+
134
+ #sby-notifications .navigation .next {
135
+ float: right;
136
+ }
137
+
138
+ #sby-notifications .navigation .disabled {
139
+ border-color: #dddddd;
140
+ color: #A0A5AA;
141
+ cursor: default;
142
+ }
143
+
144
+ #sby-notifications .navigation .disabled:hover {
145
+ background-color: #ffffff;
146
+ }
147
+
148
+ @media screen and (max-width: 768px) {
149
+ #sby-notifications {
150
+ padding: 15px 15px 15px 72px;
151
+ }
152
+ #sby-notifications .messages .message .title {
153
+ margin: 0 30px 0 0;
154
+ }
155
+ #sby-notifications .messages .message .content {
156
+ font-size: 16px;
157
+ line-height: 24px;
158
+ }
159
+ #sby-notifications .messages .message .buttons {
160
+ margin: -30px 80px 0 0;
161
+ }
162
+ #sby-notifications .messages .message .buttons a {
163
+ margin: 0;
164
+ display: table;
165
+ }
166
+ #sby-notifications .messages .message .buttons .button-secondary {
167
+ margin-top: 6px;
168
+ }
169
+ }
170
+
171
+ /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2Nzcy9hZG1pbi1ub3RpZmljYXRpb25zLmNzcyIsInNvdXJjZXMiOlsiYXNzZXRzL3Njc3MvYWRtaW4tbm90aWZpY2F0aW9ucy5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIEFkbWluIG5vdGlmaWNhdGlvbiBzdHlsZXMuXG5cbiN3cGZvcm1zLW5vdGlmaWNhdGlvbnMge1xuXG5cdHBvc2l0aW9uOiByZWxhdGl2ZTtcblx0YmFja2dyb3VuZDogI0ZGRkZGRiAwIDAgbm8tcmVwZWF0IHBhZGRpbmctYm94O1xuXHRib3gtc2hhZG93OiAwcHggNXB4IDE1cHggIzAwMDAwMDBEO1xuXHRib3JkZXItcmFkaXVzOiA2cHg7XG5cdG9wYWNpdHk6IDE7XG5cdG1pbi1oZWlnaHQ6IDQ4cHg7XG5cdHBhZGRpbmc6IDE1cHggMTAycHggMTVweCA3MnB4O1xuXHRtYXJnaW46IDAgMCAxNHB4IDA7XG5cblx0KiB7XG5cdFx0Ym94LXNpemluZzogYm9yZGVyLWJveDtcblx0fVxuXG5cdC5iZWxsIHtcblx0XHRwb3NpdGlvbjogYWJzb2x1dGU7XG5cdFx0dG9wOiAxNXB4O1xuXHRcdGxlZnQ6IDE1cHg7XG5cdFx0d2lkdGg6IDQycHg7XG5cdFx0aGVpZ2h0OiA0OHB4O1xuXHR9XG5cblx0Lm1lc3NhZ2VzIHtcblx0XHQubWVzc2FnZSB7XG5cdFx0XHRkaXNwbGF5OiBub25lO1xuXG5cdFx0XHQmLmN1cnJlbnQge1xuXHRcdFx0XHRkaXNwbGF5OiBibG9jaztcblx0XHRcdH1cblxuXHRcdFx0LnRpdGxlIHtcblx0XHRcdFx0Zm9udC13ZWlnaHQ6IGJvbGQ7XG5cdFx0XHRcdGZvbnQtc2l6ZTogMTdweDtcblx0XHRcdFx0bGluZS1oZWlnaHQ6IDIwcHg7XG5cdFx0XHRcdG1hcmdpbjogMDtcblx0XHRcdFx0Y29sb3I6ICM0NDQ7XG5cdFx0XHR9XG5cblx0XHRcdC5jb250ZW50IHtcblx0XHRcdFx0Zm9udC13ZWlnaHQ6IG5vcm1hbDtcblx0XHRcdFx0Zm9udC1zaXplOiAxM3B4O1xuXHRcdFx0XHRsaW5lLWhlaWdodDogMjBweDtcblx0XHRcdFx0bWFyZ2luOiA2cHggMCA0MHB4IDA7XG5cdFx0XHR9XG5cblx0XHRcdC5idXR0b25zIHtcblx0XHRcdFx0bWFyZ2luOiAtMzBweCA4MHB4IDAgMDtcblxuXHRcdFx0XHRhIHtcblx0XHRcdFx0XHRtYXJnaW46IDAgNnB4IDAgMDtcblx0XHRcdFx0XHRwYWRkaW5nOiA4cHggMTBweDtcblx0XHRcdFx0XHRsaW5lLWhlaWdodDogMTNweDtcblx0XHRcdFx0XHRmb250LXNpemU6IDEzcHg7XG5cdFx0XHRcdFx0bWluLWhlaWdodDogdW5zZXQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQuYnV0dG9uLXNlY29uZGFyeSB7XG5cdFx0XHRcdFx0Ym9yZGVyOiAxcHggc29saWQgIzAwNzFBMTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC5kaXNtaXNzIHtcblx0XHRwb3NpdGlvbjogYWJzb2x1dGU7XG5cdFx0dG9wOiAxNXB4O1xuXHRcdHJpZ2h0OiAxNXB4O1xuXHRcdHdpZHRoOiAxNnB4O1xuXHRcdGhlaWdodDogMTZweDtcblx0XHRjb2xvcjogIzcyNzc3Qztcblx0XHRmb250LXNpemU6IDE2cHg7XG5cdFx0Y3Vyc29yOiBwb2ludGVyO1xuXHRcdHRleHQtYWxpZ246IGNlbnRlcjtcblx0XHR2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xuXHRcdGxpbmUtaGVpZ2h0OiAxNnB4O1xuXG5cdFx0Jjpob3ZlciB7XG5cdFx0XHRjb2xvcjogI2RjMzIzMjtcblx0XHR9XG5cdH1cblxuXHQubmF2aWdhdGlvbiB7XG5cdFx0cG9zaXRpb246IGFic29sdXRlO1xuXHRcdGJvdHRvbTogMTVweDtcblx0XHRyaWdodDogMTVweDtcblx0XHR3aWR0aDogNjNweDtcblx0XHRoZWlnaHQ6IDMwcHg7XG5cblx0XHRhIHtcblx0XHRcdGRpc3BsYXk6IGJsb2NrO1xuXHRcdFx0d2lkdGg6IDMwcHg7XG5cdFx0XHRoZWlnaHQ6IDMwcHg7XG5cdFx0XHRib3JkZXI6IDFweCBzb2xpZCAjN0U4OTkzO1xuXHRcdFx0Ym9yZGVyLXJhZGl1czogM3B4O1xuXHRcdFx0Zm9udC1zaXplOiA4cHg7XG5cdFx0XHR0ZXh0LWFsaWduOiBjZW50ZXI7XG5cdFx0XHR2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xuXHRcdFx0bGluZS1oZWlnaHQ6IDMwcHg7XG5cdFx0XHRjdXJzb3I6IHBvaW50ZXI7XG5cdFx0XHRiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuXHRcdFx0Y29sb3I6ICM0MTQ1NEE7XG5cblx0XHRcdCY6aG92ZXIge1xuXHRcdFx0XHRiYWNrZ3JvdW5kLWNvbG9yOiAjZjFmMWYxO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC5wcmV2IHtcblx0XHRcdGZsb2F0OiBsZWZ0O1xuXHRcdH1cblxuXHRcdC5uZXh0IHtcblx0XHRcdGZsb2F0OiByaWdodDtcblx0XHR9XG5cblx0XHQuZGlzYWJsZWQge1xuXHRcdFx0Ym9yZGVyLWNvbG9yOiAjZGRkZGRkO1xuXHRcdFx0Y29sb3I6ICNBMEE1QUE7XG5cdFx0XHRjdXJzb3I6IGRlZmF1bHQ7XG5cblx0XHRcdCY6aG92ZXIge1xuXHRcdFx0XHRiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG5AbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOiA3NjhweCkge1xuXG5cdCN3cGZvcm1zLW5vdGlmaWNhdGlvbnMge1xuXHRcdHBhZGRpbmc6IDE1cHggMTVweCAxNXB4IDcycHg7XG5cblx0XHQubWVzc2FnZXMge1xuXG5cdFx0XHQubWVzc2FnZSB7XG5cblx0XHRcdFx0LnRpdGxlIHtcblx0XHRcdFx0XHRtYXJnaW46IDAgMzBweCAwIDA7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQuY29udGVudCB7XG5cdFx0XHRcdFx0Zm9udC1zaXplOiAxNnB4O1xuXHRcdFx0XHRcdGxpbmUtaGVpZ2h0OiAyNHB4XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQuYnV0dG9ucyB7XG5cdFx0XHRcdFx0bWFyZ2luOiAtMzBweCA4MHB4IDAgMDtcblxuXHRcdFx0XHRcdGEge1xuXHRcdFx0XHRcdFx0bWFyZ2luOiAwO1xuXHRcdFx0XHRcdFx0ZGlzcGxheTogdGFibGU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0LmJ1dHRvbi1zZWNvbmRhcnkge1xuXHRcdFx0XHRcdFx0bWFyZ2luLXRvcDogNnB4O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxBQUFBLHNCQUFzQixDQUFDO0VBRXRCLFFBQVEsRUFBRSxRQUFRO0VBQ2xCLFVBQVUsRUFBRSxpQ0FBaUM7RUFDN0MsVUFBVSxFQUFFLHNCQUFzQjtFQUNsQyxhQUFhLEVBQUUsR0FBRztFQUNsQixPQUFPLEVBQUUsQ0FBQztFQUNWLFVBQVUsRUFBRSxJQUFJO0VBQ2hCLE9BQU8sRUFBRSxvQkFBb0I7RUFDN0IsTUFBTSxFQUFFLFVBQVU7Q0FxSGxCOztBQTlIRCxBQVdDLHNCQVhxQixDQVdyQixDQUFDLENBQUM7RUFDRCxVQUFVLEVBQUUsVUFBVTtDQUN0Qjs7QUFiRixBQWVDLHNCQWZxQixDQWVyQixLQUFLLENBQUM7RUFDTCxRQUFRLEVBQUUsUUFBUTtFQUNsQixHQUFHLEVBQUUsSUFBSTtFQUNULElBQUksRUFBRSxJQUFJO0VBQ1YsS0FBSyxFQUFFLElBQUk7RUFDWCxNQUFNLEVBQUUsSUFBSTtDQUNaOztBQXJCRixBQXdCRSxzQkF4Qm9CLENBdUJyQixTQUFTLENBQ1IsUUFBUSxDQUFDO0VBQ1IsT0FBTyxFQUFFLElBQUk7Q0FvQ2I7O0FBN0RILEFBMkJHLHNCQTNCbUIsQ0F1QnJCLFNBQVMsQ0FDUixRQUFRLEFBR04sUUFBUSxDQUFDO0VBQ1QsT0FBTyxFQUFFLEtBQUs7Q0FDZDs7QUE3QkosQUErQkcsc0JBL0JtQixDQXVCckIsU0FBUyxDQUNSLFFBQVEsQ0FPUCxNQUFNLENBQUM7RUFDTixXQUFXLEVBQUUsSUFBSTtFQUNqQixTQUFTLEVBQUUsSUFBSTtFQUNmLFdBQVcsRUFBRSxJQUFJO0VBQ2pCLE1BQU0sRUFBRSxDQUFDO0VBQ1QsS0FBSyxFQUFFLElBQUk7Q0FDWDs7QUFyQ0osQUF1Q0csc0JBdkNtQixDQXVCckIsU0FBUyxDQUNSLFFBQVEsQ0FlUCxRQUFRLENBQUM7RUFDUixXQUFXLEVBQUUsTUFBTTtFQUNuQixTQUFTLEVBQUUsSUFBSTtFQUNmLFdBQVcsRUFBRSxJQUFJO0VBQ2pCLE1BQU0sRUFBRSxZQUFZO0NBQ3BCOztBQTVDSixBQThDRyxzQkE5Q21CLENBdUJyQixTQUFTLENBQ1IsUUFBUSxDQXNCUCxRQUFRLENBQUM7RUFDUixNQUFNLEVBQUUsY0FBYztDQWF0Qjs7QUE1REosQUFpREksc0JBakRrQixDQXVCckIsU0FBUyxDQUNSLFFBQVEsQ0FzQlAsUUFBUSxDQUdQLENBQUMsQ0FBQztFQUNELE1BQU0sRUFBRSxTQUFTO0VBQ2pCLE9BQU8sRUFBRSxRQUFRO0VBQ2pCLFdBQVcsRUFBRSxJQUFJO0VBQ2pCLFNBQVMsRUFBRSxJQUFJO0VBQ2YsVUFBVSxFQUFFLEtBQUs7Q0FDakI7O0FBdkRMLEFBeURJLHNCQXpEa0IsQ0F1QnJCLFNBQVMsQ0FDUixRQUFRLENBc0JQLFFBQVEsQ0FXUCxpQkFBaUIsQ0FBQztFQUNqQixNQUFNLEVBQUUsaUJBQWlCO0NBQ3pCOztBQTNETCxBQWdFQyxzQkFoRXFCLENBZ0VyQixRQUFRLENBQUM7RUFDUixRQUFRLEVBQUUsUUFBUTtFQUNsQixHQUFHLEVBQUUsSUFBSTtFQUNULEtBQUssRUFBRSxJQUFJO0VBQ1gsS0FBSyxFQUFFLElBQUk7RUFDWCxNQUFNLEVBQUUsSUFBSTtFQUNaLEtBQUssRUFBRSxPQUFPO0VBQ2QsU0FBUyxFQUFFLElBQUk7RUFDZixNQUFNLEVBQUUsT0FBTztFQUNmLFVBQVUsRUFBRSxNQUFNO0VBQ2xCLGNBQWMsRUFBRSxNQUFNO0VBQ3RCLFdBQVcsRUFBRSxJQUFJO0NBS2pCOztBQWhGRixBQTZFRSxzQkE3RW9CLENBZ0VyQixRQUFRLEFBYU4sTUFBTSxDQUFDO0VBQ1AsS0FBSyxFQUFFLE9BQU87Q0FDZDs7QUEvRUgsQUFrRkMsc0JBbEZxQixDQWtGckIsV0FBVyxDQUFDO0VBQ1gsUUFBUSxFQUFFLFFBQVE7RUFDbEIsTUFBTSxFQUFFLElBQUk7RUFDWixLQUFLLEVBQUUsSUFBSTtFQUNYLEtBQUssRUFBRSxJQUFJO0VBQ1gsTUFBTSxFQUFFLElBQUk7Q0FzQ1o7O0FBN0hGLEFBeUZFLHNCQXpGb0IsQ0FrRnJCLFdBQVcsQ0FPVixDQUFDLENBQUM7RUFDRCxPQUFPLEVBQUUsS0FBSztFQUNkLEtBQUssRUFBRSxJQUFJO0VBQ1gsTUFBTSxFQUFFLElBQUk7RUFDWixNQUFNLEVBQUUsaUJBQWlCO0VBQ3pCLGFBQWEsRUFBRSxHQUFHO0VBQ2xCLFNBQVMsRUFBRSxHQUFHO0VBQ2QsVUFBVSxFQUFFLE1BQU07RUFDbEIsY0FBYyxFQUFFLE1BQU07RUFDdEIsV0FBVyxFQUFFLElBQUk7RUFDakIsTUFBTSxFQUFFLE9BQU87RUFDZixnQkFBZ0IsRUFBRSxPQUFPO0VBQ3pCLEtBQUssRUFBRSxPQUFPO0NBS2Q7O0FBMUdILEFBdUdHLHNCQXZHbUIsQ0FrRnJCLFdBQVcsQ0FPVixDQUFDLEFBY0MsTUFBTSxDQUFDO0VBQ1AsZ0JBQWdCLEVBQUUsT0FBTztDQUN6Qjs7QUF6R0osQUE0R0Usc0JBNUdvQixDQWtGckIsV0FBVyxDQTBCVixLQUFLLENBQUM7RUFDTCxLQUFLLEVBQUUsSUFBSTtDQUNYOztBQTlHSCxBQWdIRSxzQkFoSG9CLENBa0ZyQixXQUFXLENBOEJWLEtBQUssQ0FBQztFQUNMLEtBQUssRUFBRSxLQUFLO0NBQ1o7O0FBbEhILEFBb0hFLHNCQXBIb0IsQ0FrRnJCLFdBQVcsQ0FrQ1YsU0FBUyxDQUFDO0VBQ1QsWUFBWSxFQUFFLE9BQU87RUFDckIsS0FBSyxFQUFFLE9BQU87RUFDZCxNQUFNLEVBQUUsT0FBTztDQUtmOztBQTVISCxBQXlIRyxzQkF6SG1CLENBa0ZyQixXQUFXLENBa0NWLFNBQVMsQUFLUCxNQUFNLENBQUM7RUFDUCxnQkFBZ0IsRUFBRSxPQUFPO0NBQ3pCOztBQUtKLE1BQU0sQ0FBQyxNQUFNLE1BQU0sU0FBUyxFQUFFLEtBQUs7RUFFbEMsQUFBQSxzQkFBc0IsQ0FBQztJQUN0QixPQUFPLEVBQUUsbUJBQW1CO0dBNkI1QjtFQTlCRCxBQU9HLHNCQVBtQixDQUdyQixTQUFTLENBRVIsUUFBUSxDQUVQLE1BQU0sQ0FBQztJQUNOLE1BQU0sRUFBRSxVQUFVO0dBQ2xCO0VBVEosQUFXRyxzQkFYbUIsQ0FHckIsU0FBUyxDQUVSLFFBQVEsQ0FNUCxRQUFRLENBQUM7SUFDUixTQUFTLEVBQUUsSUFBSTtJQUNmLFdBQVcsRUFBRSxJQUNkO0dBQUM7RUFkSixBQWdCRyxzQkFoQm1CLENBR3JCLFNBQVMsQ0FFUixRQUFRLENBV1AsUUFBUSxDQUFDO0lBQ1IsTUFBTSxFQUFFLGNBQWM7R0FVdEI7RUEzQkosQUFtQkksc0JBbkJrQixDQUdyQixTQUFTLENBRVIsUUFBUSxDQVdQLFFBQVEsQ0FHUCxDQUFDLENBQUM7SUFDRCxNQUFNLEVBQUUsQ0FBQztJQUNULE9BQU8sRUFBRSxLQUFLO0dBQ2Q7RUF0QkwsQUF3Qkksc0JBeEJrQixDQUdyQixTQUFTLENBRVIsUUFBUSxDQVdQLFFBQVEsQ0FRUCxpQkFBaUIsQ0FBQztJQUNqQixVQUFVLEVBQUUsR0FBRztHQUNmIn0= */
css/admin.css CHANGED
@@ -1,1183 +1,1183 @@
1
- #sbspf_admin h2{
2
- padding: 15px 0 0 0;
3
- clear: both;
4
- }
5
- #sbspf_admin hr {
6
- border: none;
7
- margin: 15px 0;
8
- border-bottom: 1px solid #ccc;
9
- }
10
- #sbspf_admin .sbspf_spinner {
11
- float: none;
12
- }
13
- #sbspf_admin .sbspf_success {
14
- display: inline-block;
15
- position: relative;
16
- margin: 4px 12px 0;
17
- }
18
- #sbspf_admin .sbspf_success svg {
19
- vertical-align: bottom;
20
- width: 16px;
21
- color: #7ad03a;
22
- }
23
- #sbspf_admin .sbspf_fade {
24
- opacity: .6;
25
- }
26
- #sbspf_admin .sbspf_aside {
27
- font-style: italic;
28
- font-weight: normal;
29
- font-size: 12px;
30
- margin: .3em 0;
31
- }
32
- #sbspf_admin .sbspf_red {
33
- color: #eb381c;
34
- }
35
- #sbspf_admin #sbspf_get_token:hover{
36
- background-color: #3880c4;
37
- color: #fff;
38
-
39
- -moz-transition: all 0.1s ease-in-out;
40
- -webkit-transition: all 0.1s ease-in-out;
41
- -o-transition: all 0.1s ease-in-out;
42
- transition: all 0.1s ease-in-out;
43
- }
44
- /* Quick Links */
45
- #sbspf_admin .sbspf-contents-links a,
46
- #sbspf_admin .sbspf-contents-links span {
47
- display: block;
48
- float: left;
49
- padding: 2px 5px;
50
- }
51
- #sbspf_admin .sbspf-contents-links{
52
- float: left;
53
- clear: both;
54
- width: 100%;
55
- padding-bottom: 12px;
56
- border-bottom: 1px solid #ccc;
57
- margin-bottom: 15px;
58
- }
59
- /* Tooltips */
60
- #sbspf_admin .sbspf_tooltip {
61
- display: none;
62
- }
63
- #sbspf_admin .sbspf_tooltip_link {
64
- font-size: 13px;
65
- margin-left: 10px;
66
- }
67
- #sbspf_admin .sbspf_tooltip_link svg,
68
- #sbspf_admin .sbspf_layouts svg,
69
- .sbspf_small_svg {
70
- width: 13px;
71
- }
72
- #sbspf_admin .sbspf_more_info{
73
- clear: both;
74
- padding: 10px 15px;
75
- margin: 10px 0;
76
- font-size: 13px;
77
- background: #f9f9f9;
78
- background: rgba(255,255,255,0.8);
79
- -moz-border-radius: 8px;
80
- -webkit-border-radius: 8px;
81
- border-radius: 8px;
82
- }
83
- #sbspf_admin .postbox .sbspf_more_info{
84
- background: #eee;
85
- background: rgba(0,0,0,0.05);
86
- }
87
- #sbspf_admin .sbspf_more_info p{
88
- font-size: 13px;
89
- }
90
- #sbspf_admin .sbspf_tooltip_link {
91
- vertical-align: top;
92
- }
93
- #sbspf_admin .sbspf_tooltip_link svg {
94
- vertical-align: bottom;
95
- }
96
- #sbspf_admin .sbspf-highlight{
97
- background: #ffed51;
98
- font-weight: bold;
99
- color: black;
100
- }
101
-
102
- /* Quick Start */
103
- #sbspf_admin .sbspf-quick-start{
104
- display: block;
105
- float: left;
106
- clear: both;
107
- width: 808px;
108
- max-width: 100%;
109
- margin: 15px 0 0 0;
110
- padding: 15px 20px;
111
-
112
- border: 1px solid #ccc;
113
- background: #eee;
114
- background: rgba(255,255,255,0.5);
115
-
116
- -moz-border-radius: 5px;
117
- -webkit-border-radius: 5px;
118
- border-radius: 5px;
119
- }
120
- #sbspf_admin .sbspf-quick-start h3,
121
- #sbspf_admin .sbspf-quick-start p{
122
- margin: 0;
123
- padding: 5px 0;
124
- }
125
- #sbspf_admin .sbspf-success{
126
- font-size: 14px;
127
- }
128
- #sbspf_admin .sbspf-footnote{
129
- width: 100%;
130
- float: left;
131
- clear: both;
132
- padding: 20px 0 0 0;
133
- border-top: 1px solid #ccc;
134
- margin: 20px 0 0 0;
135
- }
136
- #sbspf_have_own_tokens {
137
- margin: 1px 6px 0 0;
138
- }
139
- #sbspf_width_options {
140
- margin-top: 8px;
141
- }
142
- /* Pro Notice */
143
- #sbspf_admin .sbspf-pro-notice,
144
- #sbspf_admin .sbspf-pro-notice img{
145
- display: block;
146
- float: left;
147
- clear: both;
148
- margin: 20px 0 0 0;
149
- overflow: hidden;
150
- max-width: 100%;
151
-
152
- -moz-border-radius: 4px;
153
- -webkit-border-radius: 4px;
154
- border-radius: 4px;
155
-
156
- -moz-transition: all 0.5s ease-in-out;
157
- -webkit-transition: all 0.5s ease-in-out;
158
- -o-transition: all 0.5s ease-in-out;
159
- transition: all 0.5s ease-in-out;
160
- }
161
- #sbspf_admin .sbspf-pro-notice img{
162
- margin: 0;
163
- }
164
- #sbspf_admin .sbspf-pro-notice:hover{
165
- opacity: 0.95;
166
-
167
- -moz-transition: all 0.1s ease-in-out;
168
- -webkit-transition: all 0.1s ease-in-out;
169
- -o-transition: all 0.1s ease-in-out;
170
- transition: all 0.1s ease-in-out;
171
- }
172
-
173
- /* General Formatting */
174
- #sbspf_admin .sbspf_note {
175
- font-size: 12px;
176
- font-style: italic;
177
- margin-left: 5px;
178
- }
179
- #sbspf_admin .sbspf_shortcode {
180
- position: absolute;
181
- z-index: 10;
182
- font-size: 11px;
183
- float: left;
184
- width: auto;
185
- white-space: pre-line;
186
- line-height: 1.4;
187
- max-width: 195px;
188
- }
189
- .sbspf_size_4 {
190
- max-width: 60px;
191
- }
192
- #sbspf_admin td textarea {
193
- width: 100%;
194
- max-width: 700px;
195
- }
196
-
197
- /* Lock floating on top */
198
- .sbspf_lock {
199
- position: absolute;
200
- top: 50%;
201
- right: 50%;
202
- height: 18px;
203
- padding: 4px 10px;
204
- background: rgba(255,255,255,1);
205
- border-radius: 5px;
206
- box-shadow: 0 0 5px 0 rgba(0,0,0,0.1);
207
- color: #333;
208
- z-index: 99;
209
- font-size: 14px;
210
- font-weight: 700;
211
- text-decoration: none;
212
- border: 1px solid #333;
213
- }
214
-
215
- .sbspf_lock svg {
216
- height: 11px;
217
- margin-right: 4px;
218
- }
219
-
220
- /* Types */
221
- #sbspf_admin .sbspf_row{
222
- width: 100%;
223
- float: left;
224
- clear: both;
225
- margin-bottom: 5px;
226
- }
227
- #sbspf_admin .sbspf_col{
228
- float: left;
229
- }
230
- #sbspf_admin .sbspf_col.sbspf_one{
231
- width: 138px;
232
- }
233
- #sbspf_admin .sbspf_col.sbspf_two{
234
- width: 73%;
235
- }
236
- #sbspf_admin .sbspf_row input[type=radio]{
237
- margin: 5px 2px 0 0;
238
- }
239
- #sbspf_admin .sbspf_radio_label {
240
- padding-top: 4px;
241
- display: -moz-inline-stack;
242
- display: inline-block;
243
- vertical-align: top;
244
- zoom: 1;
245
- *display: inline;
246
- }
247
-
248
- /* Log In Get Access Token Button */
249
- #sbspf_admin #sbspf_get_token{
250
- display: block;
251
- float: left;
252
- clear: both;
253
- padding: 0 21px;
254
- height: 47px;
255
- line-height: 47px;
256
- font-size: 14px;
257
-
258
- background: #386793;
259
-
260
- color: #e9eef3;
261
- text-decoration: none;
262
-
263
- -moz-border-radius: 5px;
264
- -webkit-border-radius: 5px;
265
- border-radius: 5px;
266
-
267
- -moz-transition: all 0.5s ease-in-out;
268
- -webkit-transition: all 0.5s ease-in-out;
269
- -o-transition: all 0.5s ease-in-out;
270
- transition: all 0.5s ease-in-out;
271
- }
272
-
273
- /* Connected Accounts */
274
- #sbspf_get_token svg {
275
- width: 29px;
276
- margin-right: 10px;
277
- position: relative;
278
- top: 7px;
279
- }
280
- #sbspf_admin .sbspf_connected_account {
281
- position: relative;
282
- box-sizing: border-box;
283
- padding: 10px 35px 10px 10px;
284
- border-radius: 5px;
285
- background: #fff;
286
- margin-bottom: 5px;
287
- overflow: hidden;
288
- clear: both;
289
- border: 1px solid #ddd;
290
- max-width: 700px;
291
- }
292
- #sbspf_admin .sbspf_connected_account .sbspf_ca_accesstoken input {
293
- min-height: auto;
294
- line-height: 1;
295
- }
296
- #sbspf_admin .sbspf_ca_user_id{
297
- width: 275px;
298
- }
299
- #sbspf_admin .sbspf_ca_refresh_token {
300
- width: 510px;
301
- }
302
- #sbspf_admin .sbspf_connected_account svg {
303
- vertical-align: bottom;
304
- }
305
- #sbspf_admin .sbspf_ca_username {
306
- line-height: 1.4;
307
- margin-left: 15px;
308
- float: left;
309
- font-size: 18px;
310
- }
311
- #sbspf_admin .sbspf_connected_account .sbspf_ca_avatar{
312
- margin-right: 15px;
313
- }
314
- #sbspf_admin .sbspf_connected_account .sbspf_ca_username {
315
- margin-left: 0;
316
- margin-right: 15px;
317
- }
318
- #sbspf_admin .sbspf_connected_account .sbspf_ca_username strong{
319
- float: left;
320
- }
321
- #sbspf_admin .sbspf_connected_account .sbspf_ca_username span{
322
- font-size: 10px;
323
- font-weight: normal;
324
- padding: 0;
325
- margin: 0;
326
- display: block;
327
- }
328
-
329
- #sbspf_admin .sbspf_ca_actions {
330
- display: inline-block;
331
- }
332
- #sbspf_admin .sbspf_ca_actions .fa,
333
- #sbspf_admin .sbspf_ca_actions svg{
334
- margin-right: 5px;
335
- }
336
- #sbspf_admin .sbspf_ca_actions a.button-primary,
337
- #sbspf_admin .sbspf_ca_actions a.button-secondary,
338
- #sbspf_admin .sbspf_ca_accesstoken a.sbspf_ca_token_shortcode {
339
- font-size: 12px;
340
- padding: 6px;
341
- height: auto;
342
- line-height: 1;
343
- margin: 7px 5px 0 0;
344
- vertical-align: top;
345
- }
346
- #sbspf_admin .sbspf_ca_at_is_valid {
347
- margin-top: 10px;
348
- display: none;
349
- }
350
-
351
- @-webkit-keyframes sbspf_flash {
352
- 0% {
353
- background-color: #cae2a5;
354
- opacity:1;
355
- border: 1px solid #b2ce88;
356
- }
357
- 100% {
358
- background-color: #fff;
359
- }
360
- }
361
- #sbspf_admin .sbspf_account_updated{
362
- border: 1px solid #ddd;
363
- background: #fff;
364
-
365
- -webkit-animation-name: sbspf_flash;
366
- -webkit-animation-duration: 700ms;
367
- -webkit-animation-iteration-count: 1;
368
- -webkit-animation-timing-function: linear;
369
- -moz-animation-name: sbspf_flash;
370
- -moz-animation-duration: 700ms;
371
- -moz-animation-iteration-count: 1;
372
- -moz-animation-timing-function: linear;
373
- }
374
-
375
- #sbspf_admin .sbspf_account_active{
376
- border: 1px solid #b2ce88;
377
- background: #ecf2e3;
378
- }
379
-
380
- #sbspf_admin .sbspf_ca_alert {
381
- display: none;
382
- }
383
- #sbspf_admin .sbspf_ca_alert {
384
- padding: 5px 10px;
385
- margin: 0px 0 12px 0;
386
- border-radius: 5px;
387
- font-size: 13px;
388
- border: 1px solid;
389
- }
390
- #sbspf_admin .sbspf_ca_updated {
391
- display: inline-block;
392
- background: #d3dec1;
393
- color: #2e4506;
394
- border-color: #a9b594;
395
- }
396
- #sbspf_admin .sbspf_account_invalid .sbspf_ca_alert {
397
- display: inline-block;
398
- }
399
- #sbspf_admin .sbspf_ca_avatar{
400
- float: left;
401
- width: 40px;
402
- height: 40px;
403
- border-radius: 5px;
404
- }
405
- #sbspf_admin .sbspf_ca_accesstoken{
406
- display: none;
407
- width: 100%;
408
- float: left;
409
- clear: both;
410
- margin-top: 10px;
411
- }
412
- #sbspf_admin .sbspf_ca_token_label{
413
- display: inline-block;
414
- position: relative;
415
- background: #f9f9f9;
416
- color: #555;
417
- padding: 3px 5px;
418
- font-size: 12px;
419
- border: 1px solid #d6d6d6;
420
- height: 16px;
421
- line-height: 15px;
422
- border-radius: 4px 0 0 4px;
423
- min-width: 80px;
424
- margin-bottom: 2px;
425
- }
426
- #sbspf_admin .sbspf_permissions_desc,
427
- #sbspf_admin .sbspf_ca_token,
428
- #sbspf_admin .sbspf_ca_refresh_token,
429
- #sbspf_admin .sbspf_ca_user_id {
430
- padding: 3px 10px;
431
- }
432
-
433
- #sbspf_admin .sbspf_ca_token,
434
- #sbspf_admin .sbspf_ca_user_id,
435
- #sbspf_admin .sbspf_ca_refresh_token{
436
- position: relative;
437
- top: 1px;
438
- border: 1px solid #d6d6d6;
439
- border-left: none;
440
- font-size: 13px;
441
- border-radius: 0 4px 4px 0;
442
- background: rgba(255,255,255,0.8);
443
- display: inline-block;
444
- margin-left: 0;
445
- }
446
- #sbspf_admin .sbspf_ca_token {
447
- width: 510px;
448
- }
449
- #sbspf_admin .sbspf_ca_accesstoken a.sbspf_ca_token_shortcode{
450
- margin: 0 8px 8px;
451
- padding: 6px;
452
- height: auto;
453
- line-height: 1;
454
- }
455
-
456
- #sbspf_admin .sbspf_delete_account{
457
- position: absolute;
458
- right: 10px;
459
- top: 10px;
460
-
461
- padding: 5px 10px;
462
- background: rgba(0,0,0,0.05);
463
- color: #666;
464
- border-radius: 50px;
465
- text-decoration: none;
466
- font-size: 12px;
467
- }
468
- #sbspf_admin .sbspf_delete_account:hover,
469
- #sbspf_admin .sbspf_delete_account:focus{
470
- background: #333;
471
- color: #ddd;
472
- }
473
- #sbspf_admin .sbspf_ca_delete a {
474
- display: block;
475
- height: 13px;
476
- padding: 5px 6px;
477
- }
478
- #sbspf_admin .sbspf_ca_delete svg {
479
- height: 12px;
480
- line-height: 1;
481
- padding-bottom: 2px;
482
- }
483
- #sbspf_admin .sbspf_delete_account .sbspf_remove_text{
484
- margin-left: 5px;
485
- }
486
-
487
- .sbspf_connected_accounts_wrap{
488
- vertical-align: top;
489
- }
490
- #sbspf_admin .sbspf_no_accounts{
491
- display: inline-block;
492
- padding: 4px 15px;
493
- border-radius: 8px;
494
- background: rgba(255,255,255,0.8);
495
- margin-bottom: 3px;
496
- }
497
- #sbspf_admin #sbspf_manual_submit:active{
498
- vertical-align: unset;
499
- }
500
- #sbspf_admin .sbspf_manually_connect_wrap{
501
- padding-top: 5px;
502
- }
503
- #sbspf_admin .sbspf_user_feed_account_wrap:first-child,
504
- #sbspf_admin .sbspf_tagged_feed_account_wrap:first-child{
505
- padding-top: 5px;
506
- }
507
- #sbspf_admin .sbspf_user_feed_account_wrap:last-child,
508
- #sbspf_admin .sbspf_tagged_feed_account_wrap:last-child{
509
- padding-bottom: 6px;
510
- }
511
- #sbspf_admin .sbspf_user_feed_account_wrap,
512
- #sbspf_admin .sbspf_tagged_feed_account_wrap{
513
- padding-bottom: 5px;
514
- padding-left: 2px;
515
- }
516
- #sbspf_admin .sbspf_user_feed_account_wrap span,
517
- #sbspf_admin .sbspf_tagged_feed_account_wrap span{
518
- font-size: 13px;
519
- }
520
- #sbspf_admin .sbspf_manual_account_id_toggle label{
521
- display: block;
522
- margin: 10px 0 0 0;
523
- font-size: 13px;
524
- }
525
- #sbspf_admin .sbspf_business_profile_tag{
526
- display: none;
527
- padding: 8px 10px;
528
- background: rgba(0,0,0,0.05);
529
- border-radius: 0 5px 5px 0;
530
- margin: 0 0 0 -2px;
531
- font-size: 13px;
532
- height: 15px;
533
- line-height: 15px;
534
- box-shadow: inset 0 0 1px rgba(0,0,0,.5);
535
- }
536
- #sbspf_admin .sbspf_ca_info{
537
- overflow: hidden;
538
- }
539
- #sbspf_admin .sbspf_ca_show_token .fa,
540
- #sbspf_admin .sbspf_ca_show_token svg{
541
- margin-right: 0;
542
- }
543
- #sbspf_admin .sbspf_ca_show_token{
544
- display: inline-block;
545
- padding: 10px 5px 0px 5px;
546
- margin: 0;
547
- font-size: 12px;
548
- vertical-align: top;
549
- }
550
- #sbspf_admin .sbspf_ca_shortcode{
551
- display: none;
552
- padding: 0;
553
- width: 100%;
554
- float: left;
555
- clear: both;
556
- margin: 10px 0 0 0;
557
- }
558
- #sbspf_admin .sbspf_ca_shortcode p{
559
- padding-bottom: 10px;
560
- font-size: 13px;
561
- }
562
- #sbspf_admin .sbspf_ca_shortcode code{
563
- margin-top: 5px;
564
- display: inline-block;
565
- }
566
- #sbspf_admin .sbspf_user_feed_ids_wrap .sbspf_ca_avatar{
567
- width: 20px;
568
- height: 20px;
569
- position: relative;
570
- top: 5px;
571
- margin-right: 8px;
572
- border-radius: 4px;
573
- }
574
-
575
-
576
- @media all and (max-width: 1200px){
577
- #sbspf_admin .sbspf_delete_account .sbspf_remove_text{
578
- display: none;
579
- }
580
- #sbspf_admin .sbspf_ca_token,
581
- #sbspf_admin .sbspf_ca_user_id{
582
- border-left: 1px solid #d6d6d6;
583
- border-radius: 4px;
584
- }
585
- }
586
- @media all and (max-width: 800px){
587
- #sbspf_admin .sbspf_col.sbspf_one {
588
- width: 25%;
589
- margin-right: 5%;
590
- }
591
- #sbspf_admin .sbspf_col.sbspf_two{
592
- width: 70%;
593
- }
594
- }
595
- /* GDPR Settings */
596
- #sbspf_admin .sby-list{
597
- list-style: inside disc;
598
- }
599
- .gdpr_tooltip p{
600
- padding: 0 0 10px 0;
601
- }
602
- .gdpr_tooltip span{
603
- display: inline-block;
604
- margin: 0;
605
- font-weight: bold;
606
- font-size: 14px;
607
- }
608
- .gdpr_tooltip .sby-list{
609
- padding: 0 0 10px 0;
610
- }
611
- .gdpr_tooltip li{
612
- padding: 0;
613
- }
614
- .sbspf_gdpr_plugin_active .sbspf_active{
615
- display: inline-block;
616
- padding: 10px 20px 15px 20px;
617
- border-radius: 5px;
618
- background: #edf4f0;
619
- border: 1px solid #2c8649;
620
- color: #2c8649;
621
- margin: 8px 0 0 0;
622
- }
623
- .sbspf_gdpr_plugin_active svg{
624
- width: 16px;
625
- height: 16px;
626
- position: relative;
627
- top: 3px;
628
- margin-right: 2px;
629
- }
630
- .sbspf_gdpr_plugin_active path{
631
- fill: green;
632
- }
633
- .sbspf_gdpr_list,
634
- .sbspf_gdpr_yes,
635
- .sbspf_gdpr_no{
636
- display: none;
637
- }
638
- #sbspf_admin .sbspf_gdpr_error{
639
- padding: 10px 20px 15px 20px;
640
- border-radius: 5px;
641
- background: #F7E6E6;
642
- border: 1px solid #BA7B7B;
643
- color: #592626;
644
- }
645
- /* Configure */
646
- #sbspf_config {
647
- float: left;
648
- width: 100%;
649
- clear: both;
650
- margin: 10px 0 10px 0;
651
- }
652
- #sbspf_config .sbspf_not_working {
653
- position: relative;
654
- top: 14px;
655
- left: 15px;
656
- }
657
- /* Caching settings */
658
- #sbspf_admin #sbspf-caching-time-settings{
659
- display: inline-block;
660
- }
661
- #sbspf_admin .sbspf-caching-cron-options .submit{
662
- display: inline-block;
663
- margin: 0;
664
- padding: 0;
665
- }
666
- #sbspf_admin .sbspf-caching-sched-notice{
667
- font-size: 11px;
668
- display: block;
669
- width: 100%;
670
- }
671
- #sbspf_admin .sbspf-caching-sched-notice span{
672
- color: green;
673
- background: #e5eae1;
674
- padding: 5px 10px;
675
- border-radius: 5px;
676
- border: 1px solid #ccd3c6;
677
- display: inline-block;
678
- }
679
- #sbspf_admin .sbspf_cron_cache_opts .sbspf_row{
680
- padding: 3px 0;
681
- }
682
- #sbspf_admin .sbspf_cron_cache_opts .sbspf_row label {
683
- display: inline-block;
684
- margin: 5px 2px 0 0;
685
- }
686
-
687
- /* Layout */
688
- .form-table .sbspf_layout_type {
689
- display: inline-block;
690
- margin-left: 20px;
691
- }
692
- .form-table .sbspf_layout_type:first-child {
693
- margin-left: 0;
694
- }
695
- .sbspf_layout_setting,
696
- .sbspf_sub_option_setting{
697
- margin-bottom: 20px;
698
- }
699
- .sbspf_layout_setting:last-child,
700
- .sbspf_box_setting:last-child,
701
- .sbspf_sub_option_setting:last-child{
702
- margin-bottom: 0;
703
- }
704
- .sbspf_layout_setting label,
705
- .sbspf_box_setting label {
706
- display: inline-block;
707
- font-weight: bold;
708
- font-size: 14px;
709
- padding-bottom: 5px;
710
- padding-right: 5px;
711
- }
712
- #sbspf_admin .sbspf_layout_options_wrap .sbspf_shortcode_symbol{
713
- bottom: 4px;
714
- right: -20px;
715
- }
716
- #sbspf_admin .sbspf_layout_options_wrap .sbspf_shortcode,
717
- #sbspf_admin .sbspf_box_setting .sbspf_shortcode{
718
- position: relative;
719
- float: none;
720
- top: -4px
721
- }
722
- .sbspf_layout_cell,
723
- .sbspf_sub_option_cell{
724
- padding: 0;
725
- display: inline-block;
726
- float: left;
727
- width: 155px;
728
- padding: 15px 15px 10px 15px;
729
- margin-right: 10px;
730
- margin-bottom: 10px;
731
- background: #f6f6f6;
732
- border: 1px solid #ddd;
733
- -moz-border-radius: 5px;
734
- -webkit-border-radius: 5px;
735
- border-radius: 5px;
736
- vertical-align: top;
737
- }
738
- .sbspf_layout_cell:nth-child(4) {
739
- margin-right: 0;
740
- }
741
- @media all and (max-width: 1200px){
742
- .sbspf_layout_cell,
743
- .sbspf_sub_option_cell{
744
- width: 21%;
745
- padding: 1%;
746
- margin-right: 1%;
747
- }
748
- .sbspf_sub_option_cell {
749
- width: 30%;
750
- }
751
- }
752
- @media all and (max-width: 480px){
753
- .sbspf_layout_cell,
754
- .sbspf_sub_option_cell{
755
- width: 98%;
756
- padding: 1%;
757
- margin: 5px 0;
758
- }
759
- }
760
- .sbspf_label {
761
- font-size: 16px;
762
- font-weight: bold;
763
- padding-left: 2px;
764
- }
765
- .sbspf_layout_cell:hover,
766
- .sbspf_layout_cell:focus,
767
- .sbspf_sub_option_cell:hover,
768
- .sbspf_sub_option_cell:focus{
769
- background: #fcfcfc;
770
- cursor: pointer;
771
- }
772
- .sbspf_layout_cell.sbspf_layout_selected,
773
- .sbspf_sub_option_cell.sbspf_sub_option_selected{
774
- background: #f7faf1;
775
- border: 1px solid #7ad03a;
776
- }
777
- .sbspf_layout_cell h3
778
- .sbspf_sub_option_cell h3 {
779
- font-size: 15px;
780
- margin-top: 0;
781
- }
782
- .sbspf_layout_cell img,
783
- .sbspf_sub_option_cell img {
784
- width: 100%;
785
- border: 1px solid #ddd;
786
- margin-top: 5px;
787
- }
788
- .sbspf_box {
789
- margin-top: 10px;
790
- margin-bottom: 5px;
791
- }
792
- #sbspf_admin .sbspf_layout_settings,
793
- #sbspf_admin .sbspf_sub_option_settings,
794
- .sbspf_box_setting{
795
- float: left;
796
- clear: both;
797
- width: 96%;
798
- max-width: 700px;
799
-
800
- padding: 15px;
801
- margin: 0 0 10px 0;
802
- font-size: 13px;
803
- background: #f9f9f9;
804
- background: rgba(255,255,255,0.8);
805
-
806
- -moz-border-radius: 8px;
807
- -webkit-border-radius: 8px;
808
- border-radius: 8px;
809
- }
810
- .sbspf_layout_setting,
811
- .sbspf_sub_option_setting{
812
- clear:left;
813
- margin-bottom: 20px;
814
- }
815
- #sbspf_admin .sbspf_layout_options_wrap .sbspf-tooltip,
816
- #sbspf_admin .sbspf_box_setting .sbspf-tooltip{
817
- width: 98%;
818
- padding: 10px 1%;
819
- background: #eee;
820
- background: rgba(0,0,0,0.05);
821
- }
822
- #sbspf_admin .sbspf_layout_mobile_layout_setting {
823
- width: auto;
824
- }
825
-
826
-
827
- /* Display Tab */
828
- #sbspf_admin table.sbspf_shortcode_table{
829
- border-collapse: collapse;
830
- }
831
- #sbspf_admin table.sbspf_shortcode_table th,
832
- #sbspf_admin table.sbspf_shortcode_table td{
833
- border: 1px solid #999;
834
- padding: 0.5rem;
835
- text-align: left;
836
- }
837
- #sbspf_admin table.sbspf_shortcode_table th{
838
- background: rgba(0,0,0,0.1);
839
- }
840
- #sbspf_admin table.sbspf_shortcode_table td{
841
- background: rgba(255,255,255,0.5);
842
- }
843
- #sbspf_admin .sbspf_table_header{
844
- background: #ddd;
845
- font-weight: bold;
846
- }
847
-
848
- /* Modal */
849
-
850
- #sbspf_modal_overlay{
851
- position: fixed;
852
- z-index: 999;
853
- width: 100%;
854
- top: 0;
855
- right: 0;
856
- bottom: 0;
857
- left: 0;
858
-
859
- background: rgba(0,0,0,0.3);
860
- }
861
- #sbspf_modal_overlay .sbspf_modal{
862
- position: absolute;
863
- top: 160px;
864
- left: 50%;
865
- width: 450px;
866
-
867
- margin: 0 0 0 -230px;
868
- padding: 20px 30px;
869
- background: #fff;
870
-
871
- -webkit-box-shadow: 0 1px 20px rgba(0,0,0,0.2);
872
- box-shadow: 0 1px 20px rgba(0,0,0,0.2);
873
-
874
- -moz-border-radius: 3px;
875
- -webkit-border-radius: 3px;
876
- border-radius: 3px;
877
- }
878
- #sbspf_modal_overlay .sbspf_modal p{
879
- margin: 8px 0;
880
- }
881
- #sbspf_modal_overlay .sbspf_modal .sbspf_submit{
882
- margin-top: 20px;
883
- }
884
- #sbspf_modal_overlay .sbspf_modal .heading{
885
- font-weight: 500;
886
- font-size: 15px;
887
- }
888
- @media all and (max-width: 480px){
889
- #sbspf_modal_overlay .sbspf_modal{
890
- max-width: 100%;
891
- margin: 0 0 0 -50%;
892
- box-sizing: border-box;
893
- }
894
- }
895
- .sbspf_emphasis {
896
- display: block;
897
- font-size: 16px;
898
- text-align: center;
899
- margin-bottom: 20px;
900
- }
901
- .sbspf_emphasis svg {
902
- height: 14px;
903
- }
904
- .sbspf_modal_message h3 {
905
- font-size: 14px;
906
- }
907
- .sbspf_modal .sbspf_modal_close{
908
- position: absolute;
909
- top: 0;
910
- right: 0;
911
- padding: 10px;
912
- font-size: 14px;
913
- color: #ccc;
914
- margin: 0;
915
- }
916
- .sbspf_modal .sbspf_modal_close:focus,
917
- .sbspf_modal .sbspf_modal_close:hover{
918
- color: #333;
919
- }
920
- /* Pro only notices */
921
- #sbspf_admin .sbspf_sub_options,
922
- #sbspf_admin .sbspf_layout_cell,
923
- #sbspf_admin .sbspf_layout_settings,
924
- #sbspf_admin .sbspf_disabled_wrap{
925
- position: relative;
926
- }
927
- #sbspf_admin .sbspf_sub_options:after,
928
- #sbspf_admin .sbspf_disabled_wrap,
929
- .sbspf_box:after{
930
- clear: both;
931
- display: table;
932
- content: ""
933
- }
934
- #sbspf_admin .sbspf_disabled_wrap{
935
- width: 100%;
936
- max-width: 520px;
937
- }
938
- #sbspf_admin .sby_includes_pro_only .sbspf_pro_tooltip {
939
- top: 50%;
940
- left: 30px;
941
- bottom: auto;
942
- margin-top: -96px;
943
- }
944
- #sbspf_admin .sbspf-show-pro{
945
- margin-top: 10px;
946
- text-align: center;
947
- }
948
- .sbspf_layout_cell.sbspf_pro_only .sbspf_lock{
949
- margin-top: -4px;
950
- }
951
- #sbspf_admin .sbspf_layout_cell.sbspf_pro_only .sbspf_pro_tooltip {
952
- margin-top: -38px;
953
- left: 54px;
954
- }
955
- #sbspf_admin .sbspf_pro_only,
956
- #sbspf_admin .sbspf_pro_only label,
957
- #sbspf_admin .sbspf_pro_only input,
958
- #sbspf_admin .sbspf_pro_only select,
959
- #sbspf_admin .sbspf_pro_only_row,
960
- #sbspf_admin .sbspf_pro_only_row label,
961
- #sbspf_admin .sbspf_pro_only_row input,
962
- #sbspf_admin .sbspf_pro_only_row select{
963
- color: #999 !important;
964
- }
965
- #sbspf_admin tr.sbspf_pro_only{
966
- background: #eacccc;
967
- }
968
- #sbspf_admin .sbspf_type_row.sbspf_pro_only input[type=text]{
969
- opacity: 0.5;
970
- background: white;
971
- }
972
- .sbspf_lock.sbspf_pro_lock {
973
- background: rgba(255,255,255,0.8);
974
- color: #666;
975
- border: 1px solid #ccc;
976
- margin-right: -34px;
977
- }
978
- .sbspf_lock.sbspf_pro_lock i {
979
- margin-right: 8px;
980
- }
981
- #sbspf_admin .sbspf_pro_lock:hover,
982
- #sbspf_admin .sbspf_pro_lock:hover{
983
- background: #fff;
984
- border: 1px solid #ccc;
985
- color: #333;
986
- box-shadow: 0 0 8px 0 rgba(0,0,0,0.15);
987
- }
988
- #sbspf_admin .sbspf_pro_tooltip{
989
- text-align: center;
990
- z-index:99;
991
- display: none;
992
- position: absolute;
993
- bottom: 22px;
994
- left: -8px;
995
-
996
- background: #333;
997
- color: #eee;
998
- width: 90%;
999
- padding: 8px 10px 10px 10px;
1000
- border-radius: 3px;
1001
- line-height: 1.3;
1002
- font-size: 12px;
1003
- width: 190px;
1004
- }
1005
- #sbspf_admin .sbspf_pro_tooltip .fa-caret-down {
1006
- position: absolute;
1007
- bottom: -12px;
1008
- font-size: 20px;
1009
- left: 49%;
1010
- color: #333;
1011
- }
1012
- #sbspf_admin .sbspf_layouts .sbspf_pro_tooltip,
1013
- #sbspf_admin .sbspf_sub_options .sbspf_pro_tooltip{
1014
- left: 284px;
1015
- top: -21px;
1016
- bottom: auto;
1017
- margin-left: -101px;
1018
- }
1019
- #sbspf_admin .sbspf_layouts .sbspf_layout_cell .sbspf_pro_tooltip{
1020
- left: 84px;
1021
- top: 32px;
1022
- }
1023
- #sbspf_admin .sbspf_table_key{
1024
- display: block;
1025
- float: left;
1026
- width: 11px;
1027
- height: 11px;
1028
- border: 1px solid #999;
1029
- background: #eacccc;
1030
- margin: 3px 6px 0 0;
1031
- }
1032
-
1033
- /* SBY Specific */
1034
- #sbspf_admin .sby_mode_option {
1035
- position: relative;
1036
- margin-bottom: 20px;
1037
- }
1038
- #sbspf_admin .sby_mode_option label {
1039
- display: inline-block;
1040
- font-weight: bold;
1041
- }
1042
- #sbspf_admin .sby_mode_option .sbspf_note {
1043
- display: block;
1044
- margin-left: 0;
1045
- }
1046
- #sbspf_admin .sby_mode_option .sbspf_note,
1047
- #sbspf_admin .sby_mode_option label {
1048
- margin-bottom: 5px;
1049
- }
1050
- #sbspf_admin .sby_mode_option input[type=radio] {
1051
- position: absolute;
1052
- top: 6px;
1053
- }
1054
- #sbspf_admin .sby_mode_option_text {
1055
- margin-left: 22px;
1056
- }
1057
- #sbspf_admin .sby_mode_option.sbspf_fade .sby_important,
1058
- #sbspf_admin .sby_mode_option.sbspf_fade .sbspf_note {
1059
- opacity: 1;
1060
- }
1061
-
1062
- /* Notices */
1063
- .sby_includes_pro_only .sbspf_lock {
1064
- left: 100px;
1065
- right: auto;
1066
- margin-top: -40px;
1067
- }
1068
- .sbspf_sub_options .sbspf_lock {
1069
- top: 38px;
1070
- left: 260px;
1071
- right: auto;
1072
- }
1073
- .sby_types_disabled_wrap .sbspf_lock {
1074
- margin-top: -20px;
1075
- }
1076
- #sbspf_admin .sby_types_disabled_wrap .sbspf_pro_tooltip {
1077
- top: 50%;
1078
- margin-left: -112px;
1079
- margin-top: -78px;
1080
- bottom: auto;
1081
- left: 50%;
1082
- }
1083
- @media screen and (max-width: 480px) {
1084
- .sbspf_sub_options .sbspf_lock {
1085
- top: 60px;
1086
- left: 50%;
1087
- margin-left: -40px;
1088
- right: auto;
1089
- }
1090
- #sbspf_admin .sbspf_sub_options .sbspf_pro_tooltip {
1091
- top: 0px;
1092
- left: 50%;
1093
- margin-left: -112px;
1094
- }
1095
- }
1096
-
1097
- /* Lite Notice */
1098
- @media screen and (max-width: 600px) {
1099
- #sbspf-notice-bar {
1100
- display:none !important
1101
- }
1102
- }
1103
-
1104
- #sbspf-notice-bar {
1105
- background-color: #DDDDDD;
1106
- color: #777777;
1107
- text-align: center;
1108
- position: relative;
1109
- padding: 7px;
1110
- margin-bottom: 0;
1111
- opacity: 1;
1112
- transition: all .3s ease-in-out;
1113
- max-height: 100px;
1114
- overflow: hidden
1115
- }
1116
-
1117
- #sbspf-notice-bar.out {
1118
- opacity: .5;
1119
- max-height: 0
1120
- }
1121
-
1122
- #sbspf-notice-bar a {
1123
- color: #e34f0e;
1124
- }
1125
-
1126
- #sbspf-notice-bar a:hover {
1127
- color: #b85a1b
1128
- }
1129
-
1130
- #sbspf-notice-bar .dismiss {
1131
- position: absolute;
1132
- top: 0;
1133
- right: 0;
1134
- border: none;
1135
- padding: 5px;
1136
- margin-top: 1px;
1137
- background: 0 0;
1138
- color: #72777c;
1139
- cursor: pointer
1140
- }
1141
-
1142
- #sbspf-notice-bar .dismiss:before {
1143
- background: 0 0;
1144
- color: #72777c;
1145
- content: "\f335";
1146
- display: block;
1147
- font: normal 20px/20px dashicons;
1148
- speak: none;
1149
- height: 20px;
1150
- text-align: center;
1151
- width: 20px;
1152
- -webkit-font-smoothing: antialiased
1153
- }
1154
-
1155
- /* Locator Summary */
1156
- .sby-feed-locator-summary-wrap {
1157
- max-width: 1100px;
1158
- margin-bottom: 40px;
1159
- }
1160
- .sby-full-wrap {
1161
- display: none;
1162
- }
1163
- .sby-locator-more {
1164
- display: inline-block;
1165
- margin: 0 0 0 1px;
1166
- padding: 0 5px;
1167
- border: 1px solid rgba(0,0,0,0.1);
1168
- border-radius: 3px;
1169
- line-height: 1.6;
1170
- }
1171
-
1172
- .sby_shortcode_visible .sby_locations_link {
1173
- display: none;
1174
- }
1175
- .sby_locations_link a {
1176
- font-weight: normal;
1177
- text-decoration: none;
1178
- }
1179
- .sby_locations_link svg {
1180
- width: 11px;
1181
- position: relative;
1182
- top: 1px;
1183
  }
1
+ #sbspf_admin h2{
2
+ padding: 15px 0 0 0;
3
+ clear: both;
4
+ }
5
+ #sbspf_admin hr {
6
+ border: none;
7
+ margin: 15px 0;
8
+ border-bottom: 1px solid #ccc;
9
+ }
10
+ #sbspf_admin .sbspf_spinner {
11
+ float: none;
12
+ }
13
+ #sbspf_admin .sbspf_success {
14
+ display: inline-block;
15
+ position: relative;
16
+ margin: 4px 12px 0;
17
+ }
18
+ #sbspf_admin .sbspf_success svg {
19
+ vertical-align: bottom;
20
+ width: 16px;
21
+ color: #7ad03a;
22
+ }
23
+ #sbspf_admin .sbspf_fade {
24
+ opacity: .6;
25
+ }
26
+ #sbspf_admin .sbspf_aside {
27
+ font-style: italic;
28
+ font-weight: normal;
29
+ font-size: 12px;
30
+ margin: .3em 0;
31
+ }
32
+ #sbspf_admin .sbspf_red {
33
+ color: #eb381c;
34
+ }
35
+ #sbspf_admin #sbspf_get_token:hover{
36
+ background-color: #3880c4;
37
+ color: #fff;
38
+
39
+ -moz-transition: all 0.1s ease-in-out;
40
+ -webkit-transition: all 0.1s ease-in-out;
41
+ -o-transition: all 0.1s ease-in-out;
42
+ transition: all 0.1s ease-in-out;
43
+ }
44
+ /* Quick Links */
45
+ #sbspf_admin .sbspf-contents-links a,
46
+ #sbspf_admin .sbspf-contents-links span {
47
+ display: block;
48
+ float: left;
49
+ padding: 2px 5px;
50
+ }
51
+ #sbspf_admin .sbspf-contents-links{
52
+ float: left;
53
+ clear: both;
54
+ width: 100%;
55
+ padding-bottom: 12px;
56
+ border-bottom: 1px solid #ccc;
57
+ margin-bottom: 15px;
58
+ }
59
+ /* Tooltips */
60
+ #sbspf_admin .sbspf_tooltip {
61
+ display: none;
62
+ }
63
+ #sbspf_admin .sbspf_tooltip_link {
64
+ font-size: 13px;
65
+ margin-left: 10px;
66
+ }
67
+ #sbspf_admin .sbspf_tooltip_link svg,
68
+ #sbspf_admin .sbspf_layouts svg,
69
+ .sbspf_small_svg {
70
+ width: 13px;
71
+ }
72
+ #sbspf_admin .sbspf_more_info{
73
+ clear: both;
74
+ padding: 10px 15px;
75
+ margin: 10px 0;
76
+ font-size: 13px;
77
+ background: #f9f9f9;
78
+ background: rgba(255,255,255,0.8);
79
+ -moz-border-radius: 8px;
80
+ -webkit-border-radius: 8px;
81
+ border-radius: 8px;
82
+ }
83
+ #sbspf_admin .postbox .sbspf_more_info{
84
+ background: #eee;
85
+ background: rgba(0,0,0,0.05);
86
+ }
87
+ #sbspf_admin .sbspf_more_info p{
88
+ font-size: 13px;
89
+ }
90
+ #sbspf_admin .sbspf_tooltip_link {
91
+ vertical-align: top;
92
+ }
93
+ #sbspf_admin .sbspf_tooltip_link svg {
94
+ vertical-align: bottom;
95
+ }
96
+ #sbspf_admin .sbspf-highlight{
97
+ background: #ffed51;
98
+ font-weight: bold;
99
+ color: black;
100
+ }
101
+
102
+ /* Quick Start */
103
+ #sbspf_admin .sbspf-quick-start{
104
+ display: block;
105
+ float: left;
106
+ clear: both;
107
+ width: 808px;
108
+ max-width: 100%;
109
+ margin: 15px 0 0 0;
110
+ padding: 15px 20px;
111
+
112
+ border: 1px solid #ccc;
113
+ background: #eee;
114
+ background: rgba(255,255,255,0.5);
115
+
116
+ -moz-border-radius: 5px;
117
+ -webkit-border-radius: 5px;
118
+ border-radius: 5px;
119
+ }
120
+ #sbspf_admin .sbspf-quick-start h3,
121
+ #sbspf_admin .sbspf-quick-start p{
122
+ margin: 0;
123
+ padding: 5px 0;
124
+ }
125
+ #sbspf_admin .sbspf-success{
126
+ font-size: 14px;
127
+ }
128
+ #sbspf_admin .sbspf-footnote{
129
+ width: 100%;
130
+ float: left;
131
+ clear: both;
132
+ padding: 20px 0 0 0;
133
+ border-top: 1px solid #ccc;
134
+ margin: 20px 0 0 0;
135
+ }
136
+ #sbspf_have_own_tokens {
137
+ margin: 1px 6px 0 0;
138
+ }
139
+ #sbspf_width_options {
140
+ margin-top: 8px;
141
+ }
142
+ /* Pro Notice */
143
+ #sbspf_admin .sbspf-pro-notice,
144
+ #sbspf_admin .sbspf-pro-notice img{
145
+ display: block;
146
+ float: left;
147
+ clear: both;
148
+ margin: 20px 0 0 0;
149
+ overflow: hidden;
150
+ max-width: 100%;
151
+
152
+ -moz-border-radius: 4px;
153
+ -webkit-border-radius: 4px;
154
+ border-radius: 4px;
155
+
156
+ -moz-transition: all 0.5s ease-in-out;
157
+ -webkit-transition: all 0.5s ease-in-out;
158
+ -o-transition: all 0.5s ease-in-out;
159
+ transition: all 0.5s ease-in-out;
160
+ }
161
+ #sbspf_admin .sbspf-pro-notice img{
162
+ margin: 0;
163
+ }
164
+ #sbspf_admin .sbspf-pro-notice:hover{
165
+ opacity: 0.95;
166
+
167
+ -moz-transition: all 0.1s ease-in-out;
168
+ -webkit-transition: all 0.1s ease-in-out;
169
+ -o-transition: all 0.1s ease-in-out;
170
+ transition: all 0.1s ease-in-out;
171
+ }
172
+
173
+ /* General Formatting */
174
+ #sbspf_admin .sbspf_note {
175
+ font-size: 12px;
176
+ font-style: italic;
177
+ margin-left: 5px;
178
+ }
179
+ #sbspf_admin .sbspf_shortcode {
180
+ position: absolute;
181
+ z-index: 10;
182
+ font-size: 11px;
183
+ float: left;
184
+ width: auto;
185
+ white-space: pre-line;
186
+ line-height: 1.4;
187
+ max-width: 195px;
188
+ }
189
+ .sbspf_size_4 {
190
+ max-width: 60px;
191
+ }
192
+ #sbspf_admin td textarea {
193
+ width: 100%;
194
+ max-width: 700px;
195
+ }
196
+
197
+ /* Lock floating on top */
198
+ .sbspf_lock {
199
+ position: absolute;
200
+ top: 50%;
201
+ right: 50%;
202
+ height: 18px;
203
+ padding: 4px 10px;
204
+ background: rgba(255,255,255,1);
205
+ border-radius: 5px;
206
+ box-shadow: 0 0 5px 0 rgba(0,0,0,0.1);
207
+ color: #333;
208
+ z-index: 99;
209
+ font-size: 14px;
210
+ font-weight: 700;
211
+ text-decoration: none;
212
+ border: 1px solid #333;
213
+ }
214
+
215
+ .sbspf_lock svg {
216
+ height: 11px;
217
+ margin-right: 4px;
218
+ }
219
+
220
+ /* Types */
221
+ #sbspf_admin .sbspf_row{
222
+ width: 100%;
223
+ float: left;
224
+ clear: both;
225
+ margin-bottom: 5px;
226
+ }
227
+ #sbspf_admin .sbspf_col{
228
+ float: left;
229
+ }
230
+ #sbspf_admin .sbspf_col.sbspf_one{
231
+ width: 138px;
232
+ }
233
+ #sbspf_admin .sbspf_col.sbspf_two{
234
+ width: 73%;
235
+ }
236
+ #sbspf_admin .sbspf_row input[type=radio]{
237
+ margin: 5px 2px 0 0;
238
+ }
239
+ #sbspf_admin .sbspf_radio_label {
240
+ padding-top: 4px;
241
+ display: -moz-inline-stack;
242
+ display: inline-block;
243
+ vertical-align: top;
244
+ zoom: 1;
245
+ *display: inline;
246
+ }
247
+
248
+ /* Log In Get Access Token Button */
249
+ #sbspf_admin #sbspf_get_token{
250
+ display: block;
251
+ float: left;
252
+ clear: both;
253
+ padding: 0 21px;
254
+ height: 47px;
255
+ line-height: 47px;
256
+ font-size: 14px;
257
+
258
+ background: #386793;
259
+
260
+ color: #e9eef3;
261
+ text-decoration: none;
262
+
263
+ -moz-border-radius: 5px;
264
+ -webkit-border-radius: 5px;
265
+ border-radius: 5px;
266
+
267
+ -moz-transition: all 0.5s ease-in-out;
268
+ -webkit-transition: all 0.5s ease-in-out;
269
+ -o-transition: all 0.5s ease-in-out;
270
+ transition: all 0.5s ease-in-out;
271
+ }
272
+
273
+ /* Connected Accounts */
274
+ #sbspf_get_token svg {
275
+ width: 29px;
276
+ margin-right: 10px;
277
+ position: relative;
278
+ top: 7px;
279
+ }
280
+ #sbspf_admin .sbspf_connected_account {
281
+ position: relative;
282
+ box-sizing: border-box;
283
+ padding: 10px 35px 10px 10px;
284
+ border-radius: 5px;
285
+ background: #fff;
286
+ margin-bottom: 5px;
287
+ overflow: hidden;
288
+ clear: both;
289
+ border: 1px solid #ddd;
290
+ max-width: 700px;
291
+ }
292
+ #sbspf_admin .sbspf_connected_account .sbspf_ca_accesstoken input {
293
+ min-height: auto;
294
+ line-height: 1;
295
+ }
296
+ #sbspf_admin .sbspf_ca_user_id{
297
+ width: 275px;
298
+ }
299
+ #sbspf_admin .sbspf_ca_refresh_token {
300
+ width: 510px;
301
+ }
302
+ #sbspf_admin .sbspf_connected_account svg {
303
+ vertical-align: bottom;
304
+ }
305
+ #sbspf_admin .sbspf_ca_username {
306
+ line-height: 1.4;
307
+ margin-left: 15px;
308
+ float: left;
309
+ font-size: 18px;
310
+ }
311
+ #sbspf_admin .sbspf_connected_account .sbspf_ca_avatar{
312
+ margin-right: 15px;
313
+ }
314
+ #sbspf_admin .sbspf_connected_account .sbspf_ca_username {
315
+ margin-left: 0;
316
+ margin-right: 15px;
317
+ }
318
+ #sbspf_admin .sbspf_connected_account .sbspf_ca_username strong{
319
+ float: left;
320
+ }
321
+ #sbspf_admin .sbspf_connected_account .sbspf_ca_username span{
322
+ font-size: 10px;
323
+ font-weight: normal;
324
+ padding: 0;
325
+ margin: 0;
326
+ display: block;
327
+ }
328
+
329
+ #sbspf_admin .sbspf_ca_actions {
330
+ display: inline-block;
331
+ }
332
+ #sbspf_admin .sbspf_ca_actions .fa,
333
+ #sbspf_admin .sbspf_ca_actions svg{
334
+ margin-right: 5px;
335
+ }
336
+ #sbspf_admin .sbspf_ca_actions a.button-primary,
337
+ #sbspf_admin .sbspf_ca_actions a.button-secondary,
338
+ #sbspf_admin .sbspf_ca_accesstoken a.sbspf_ca_token_shortcode {
339
+ font-size: 12px;
340
+ padding: 6px;
341
+ height: auto;
342
+ line-height: 1;
343
+ margin: 7px 5px 0 0;
344
+ vertical-align: top;
345
+ }
346
+ #sbspf_admin .sbspf_ca_at_is_valid {
347
+ margin-top: 10px;
348
+ display: none;
349
+ }
350
+
351
+ @-webkit-keyframes sbspf_flash {
352
+ 0% {
353
+ background-color: #cae2a5;
354
+ opacity:1;
355
+ border: 1px solid #b2ce88;
356
+ }
357
+ 100% {
358
+ background-color: #fff;
359
+ }
360
+ }
361
+ #sbspf_admin .sbspf_account_updated{
362
+ border: 1px solid #ddd;
363
+ background: #fff;
364
+
365
+ -webkit-animation-name: sbspf_flash;
366
+ -webkit-animation-duration: 700ms;
367
+ -webkit-animation-iteration-count: 1;
368
+ -webkit-animation-timing-function: linear;
369
+ -moz-animation-name: sbspf_flash;
370
+ -moz-animation-duration: 700ms;
371
+ -moz-animation-iteration-count: 1;
372
+ -moz-animation-timing-function: linear;
373
+ }
374
+
375
+ #sbspf_admin .sbspf_account_active{
376
+ border: 1px solid #b2ce88;
377
+ background: #ecf2e3;
378
+ }
379
+
380
+ #sbspf_admin .sbspf_ca_alert {
381
+ display: none;
382
+ }
383
+ #sbspf_admin .sbspf_ca_alert {
384
+ padding: 5px 10px;
385
+ margin: 0px 0 12px 0;
386
+ border-radius: 5px;
387
+ font-size: 13px;
388
+ border: 1px solid;
389
+ }
390
+ #sbspf_admin .sbspf_ca_updated {
391
+ display: inline-block;
392
+ background: #d3dec1;
393
+ color: #2e4506;
394
+ border-color: #a9b594;
395
+ }
396
+ #sbspf_admin .sbspf_account_invalid .sbspf_ca_alert {
397
+ display: inline-block;
398
+ }
399
+ #sbspf_admin .sbspf_ca_avatar{
400
+ float: left;
401
+ width: 40px;
402
+ height: 40px;
403
+ border-radius: 5px;
404
+ }
405
+ #sbspf_admin .sbspf_ca_accesstoken{
406
+ display: none;
407
+ width: 100%;
408
+ float: left;
409
+ clear: both;
410
+ margin-top: 10px;
411
+ }
412
+ #sbspf_admin .sbspf_ca_token_label{
413
+ display: inline-block;
414
+ position: relative;
415
+ background: #f9f9f9;
416
+ color: #555;
417
+ padding: 3px 5px;
418
+ font-size: 12px;
419
+ border: 1px solid #d6d6d6;
420
+ height: 16px;
421
+ line-height: 15px;
422
+ border-radius: 4px 0 0 4px;
423
+ min-width: 80px;
424
+ margin-bottom: 2px;
425
+ }
426
+ #sbspf_admin .sbspf_permissions_desc,
427
+ #sbspf_admin .sbspf_ca_token,
428
+ #sbspf_admin .sbspf_ca_refresh_token,
429
+ #sbspf_admin .sbspf_ca_user_id {
430
+ padding: 3px 10px;
431
+ }
432
+
433
+ #sbspf_admin .sbspf_ca_token,
434
+ #sbspf_admin .sbspf_ca_user_id,
435
+ #sbspf_admin .sbspf_ca_refresh_token{
436
+ position: relative;
437
+ top: 1px;
438
+ border: 1px solid #d6d6d6;
439
+ border-left: none;
440
+ font-size: 13px;
441
+ border-radius: 0 4px 4px 0;
442
+ background: rgba(255,255,255,0.8);
443
+ display: inline-block;
444
+ margin-left: 0;
445
+ }
446
+ #sbspf_admin .sbspf_ca_token {
447
+ width: 510px;
448
+ }
449
+ #sbspf_admin .sbspf_ca_accesstoken a.sbspf_ca_token_shortcode{
450
+ margin: 0 8px 8px;
451
+ padding: 6px;
452
+ height: auto;
453
+ line-height: 1;
454
+ }
455
+
456
+ #sbspf_admin .sbspf_delete_account{
457
+ position: absolute;
458
+ right: 10px;
459
+ top: 10px;
460
+
461
+ padding: 5px 10px;
462
+ background: rgba(0,0,0,0.05);
463
+ color: #666;
464
+ border-radius: 50px;
465
+ text-decoration: none;
466
+ font-size: 12px;
467
+ }
468
+ #sbspf_admin .sbspf_delete_account:hover,
469
+ #sbspf_admin .sbspf_delete_account:focus{
470
+ background: #333;
471
+ color: #ddd;
472
+ }
473
+ #sbspf_admin .sbspf_ca_delete a {
474
+ display: block;
475
+ height: 13px;
476
+ padding: 5px 6px;
477
+ }
478
+ #sbspf_admin .sbspf_ca_delete svg {
479
+ height: 12px;
480
+ line-height: 1;
481
+ padding-bottom: 2px;
482
+ }
483
+ #sbspf_admin .sbspf_delete_account .sbspf_remove_text{
484
+ margin-left: 5px;
485
+ }
486
+
487
+ .sbspf_connected_accounts_wrap{
488
+ vertical-align: top;
489
+ }
490
+ #sbspf_admin .sbspf_no_accounts{
491
+ display: inline-block;
492
+ padding: 4px 15px;
493
+ border-radius: 8px;
494
+ background: rgba(255,255,255,0.8);
495
+ margin-bottom: 3px;
496
+ }
497
+ #sbspf_admin #sbspf_manual_submit:active{
498
+ vertical-align: unset;
499
+ }
500
+ #sbspf_admin .sbspf_manually_connect_wrap{
501
+ padding-top: 5px;
502
+ }
503
+ #sbspf_admin .sbspf_user_feed_account_wrap:first-child,
504
+ #sbspf_admin .sbspf_tagged_feed_account_wrap:first-child{
505
+ padding-top: 5px;
506
+ }
507
+ #sbspf_admin .sbspf_user_feed_account_wrap:last-child,
508
+ #sbspf_admin .sbspf_tagged_feed_account_wrap:last-child{
509
+ padding-bottom: 6px;
510
+ }
511
+ #sbspf_admin .sbspf_user_feed_account_wrap,
512
+ #sbspf_admin .sbspf_tagged_feed_account_wrap{
513
+ padding-bottom: 5px;
514
+ padding-left: 2px;
515
+ }
516
+ #sbspf_admin .sbspf_user_feed_account_wrap span,
517
+ #sbspf_admin .sbspf_tagged_feed_account_wrap span{
518
+ font-size: 13px;
519
+ }
520
+ #sbspf_admin .sbspf_manual_account_id_toggle label{
521
+ display: block;
522
+ margin: 10px 0 0 0;
523
+ font-size: 13px;
524
+ }
525
+ #sbspf_admin .sbspf_business_profile_tag{
526
+ display: none;
527
+ padding: 8px 10px;
528
+ background: rgba(0,0,0,0.05);
529
+ border-radius: 0 5px 5px 0;
530
+ margin: 0 0 0 -2px;
531
+ font-size: 13px;
532
+ height: 15px;
533
+ line-height: 15px;
534
+ box-shadow: inset 0 0 1px rgba(0,0,0,.5);
535
+ }
536
+ #sbspf_admin .sbspf_ca_info{
537
+ overflow: hidden;
538
+ }
539
+ #sbspf_admin .sbspf_ca_show_token .fa,
540
+ #sbspf_admin .sbspf_ca_show_token svg{
541
+ margin-right: 0;
542
+ }
543
+ #sbspf_admin .sbspf_ca_show_token{
544
+ display: inline-block;
545
+ padding: 10px 5px 0px 5px;
546
+ margin: 0;
547
+ font-size: 12px;
548
+ vertical-align: top;
549
+ }
550
+ #sbspf_admin .sbspf_ca_shortcode{
551
+ display: none;
552
+ padding: 0;
553
+ width: 100%;
554
+ float: left;
555
+ clear: both;
556
+ margin: 10px 0 0 0;
557
+ }
558
+ #sbspf_admin .sbspf_ca_shortcode p{
559
+ padding-bottom: 10px;
560
+ font-size: 13px;
561
+ }
562
+ #sbspf_admin .sbspf_ca_shortcode code{
563
+ margin-top: 5px;
564
+ display: inline-block;
565
+ }
566
+ #sbspf_admin .sbspf_user_feed_ids_wrap .sbspf_ca_avatar{
567
+ width: 20px;
568
+ height: 20px;
569
+ position: relative;
570
+ top: 5px;
571
+ margin-right: 8px;
572
+ border-radius: 4px;
573
+ }
574
+
575
+
576
+ @media all and (max-width: 1200px){
577
+ #sbspf_admin .sbspf_delete_account .sbspf_remove_text{
578
+ display: none;
579
+ }
580
+ #sbspf_admin .sbspf_ca_token,
581
+ #sbspf_admin .sbspf_ca_user_id{
582
+ border-left: 1px solid #d6d6d6;
583
+ border-radius: 4px;
584
+ }
585
+ }
586
+ @media all and (max-width: 800px){
587
+ #sbspf_admin .sbspf_col.sbspf_one {
588
+ width: 25%;
589
+ margin-right: 5%;
590
+ }
591
+ #sbspf_admin .sbspf_col.sbspf_two{
592
+ width: 70%;
593
+ }
594
+ }
595
+ /* GDPR Settings */
596
+ #sbspf_admin .sby-list{
597
+ list-style: inside disc;
598
+ }
599
+ .gdpr_tooltip p{
600
+ padding: 0 0 10px 0;
601
+ }
602
+ .gdpr_tooltip span{
603
+ display: inline-block;
604
+ margin: 0;
605
+ font-weight: bold;
606
+ font-size: 14px;
607
+ }
608
+ .gdpr_tooltip .sby-list{
609
+ padding: 0 0 10px 0;
610
+ }
611
+ .gdpr_tooltip li{
612
+ padding: 0;
613
+ }
614
+ .sbspf_gdpr_plugin_active .sbspf_active{
615
+ display: inline-block;
616
+ padding: 10px 20px 15px 20px;
617
+ border-radius: 5px;
618
+ background: #edf4f0;
619
+ border: 1px solid #2c8649;
620
+ color: #2c8649;
621
+ margin: 8px 0 0 0;
622
+ }
623
+ .sbspf_gdpr_plugin_active svg{
624
+ width: 16px;
625
+ height: 16px;
626
+ position: relative;
627
+ top: 3px;
628
+ margin-right: 2px;
629
+ }
630
+ .sbspf_gdpr_plugin_active path{
631
+ fill: green;
632
+ }
633
+ .sbspf_gdpr_list,
634
+ .sbspf_gdpr_yes,
635
+ .sbspf_gdpr_no{
636
+ display: none;
637
+ }
638
+ #sbspf_admin .sbspf_gdpr_error{
639
+ padding: 10px 20px 15px 20px;
640
+ border-radius: 5px;
641
+ background: #F7E6E6;
642
+ border: 1px solid #BA7B7B;
643
+ color: #592626;
644
+ }
645
+ /* Configure */
646
+ #sbspf_config {
647
+ float: left;
648
+ width: 100%;
649
+ clear: both;
650
+ margin: 10px 0 10px 0;
651
+ }
652
+ #sbspf_config .sbspf_not_working {
653
+ position: relative;
654
+ top: 14px;
655
+ left: 15px;
656
+ }
657
+ /* Caching settings */
658
+ #sbspf_admin #sbspf-caching-time-settings{
659
+ display: inline-block;
660
+ }
661
+ #sbspf_admin .sbspf-caching-cron-options .submit{
662
+ display: inline-block;
663
+ margin: 0;
664
+ padding: 0;
665
+ }
666
+ #sbspf_admin .sbspf-caching-sched-notice{
667
+ font-size: 11px;
668
+ display: block;
669
+ width: 100%;
670
+ }
671
+ #sbspf_admin .sbspf-caching-sched-notice span{
672
+ color: green;
673
+ background: #e5eae1;
674
+ padding: 5px 10px;
675
+ border-radius: 5px;
676
+ border: 1px solid #ccd3c6;
677
+ display: inline-block;
678
+ }
679
+ #sbspf_admin .sbspf_cron_cache_opts .sbspf_row{
680
+ padding: 3px 0;
681
+ }
682
+ #sbspf_admin .sbspf_cron_cache_opts .sbspf_row label {
683
+ display: inline-block;
684
+ margin: 5px 2px 0 0;
685
+ }
686
+
687
+ /* Layout */
688
+ .form-table .sbspf_layout_type {
689
+ display: inline-block;
690
+ margin-left: 20px;
691
+ }
692
+ .form-table .sbspf_layout_type:first-child {
693
+ margin-left: 0;
694
+ }
695
+ .sbspf_layout_setting,
696
+ .sbspf_sub_option_setting{
697
+ margin-bottom: 20px;
698
+ }
699
+ .sbspf_layout_setting:last-child,
700
+ .sbspf_box_setting:last-child,
701
+ .sbspf_sub_option_setting:last-child{
702
+ margin-bottom: 0;
703
+ }
704
+ .sbspf_layout_setting label,
705
+ .sbspf_box_setting label {
706
+ display: inline-block;
707
+ font-weight: bold;
708
+ font-size: 14px;
709
+ padding-bottom: 5px;
710
+ padding-right: 5px;
711
+ }
712
+ #sbspf_admin .sbspf_layout_options_wrap .sbspf_shortcode_symbol{
713
+ bottom: 4px;
714
+ right: -20px;
715
+ }
716
+ #sbspf_admin .sbspf_layout_options_wrap .sbspf_shortcode,
717
+ #sbspf_admin .sbspf_box_setting .sbspf_shortcode{
718
+ position: relative;
719
+ float: none;
720
+ top: -4px
721
+ }
722
+ .sbspf_layout_cell,
723
+ .sbspf_sub_option_cell{
724
+ padding: 0;
725
+ display: inline-block;
726
+ float: left;
727
+ width: 155px;
728
+ padding: 15px 15px 10px 15px;
729
+ margin-right: 10px;
730
+ margin-bottom: 10px;
731
+ background: #f6f6f6;
732
+ border: 1px solid #ddd;
733
+ -moz-border-radius: 5px;
734
+ -webkit-border-radius: 5px;
735
+ border-radius: 5px;
736
+ vertical-align: top;
737
+ }
738
+ .sbspf_layout_cell:nth-child(4) {
739
+ margin-right: 0;
740
+ }
741
+ @media all and (max-width: 1200px){
742
+ .sbspf_layout_cell,
743
+ .sbspf_sub_option_cell{
744
+ width: 21%;
745
+ padding: 1%;
746
+ margin-right: 1%;
747
+ }
748
+ .sbspf_sub_option_cell {
749
+ width: 30%;
750
+ }
751
+ }
752
+ @media all and (max-width: 480px){
753
+ .sbspf_layout_cell,
754
+ .sbspf_sub_option_cell{
755
+ width: 98%;
756
+ padding: 1%;
757
+ margin: 5px 0;
758
+ }
759
+ }
760
+ .sbspf_label {
761
+ font-size: 16px;
762
+ font-weight: bold;
763
+ padding-left: 2px;
764
+ }
765
+ .sbspf_layout_cell:hover,
766
+ .sbspf_layout_cell:focus,
767
+ .sbspf_sub_option_cell:hover,
768
+ .sbspf_sub_option_cell:focus{
769
+ background: #fcfcfc;
770
+ cursor: pointer;
771
+ }
772
+ .sbspf_layout_cell.sbspf_layout_selected,
773
+ .sbspf_sub_option_cell.sbspf_sub_option_selected{
774
+ background: #f7faf1;
775
+ border: 1px solid #7ad03a;
776
+ }
777
+ .sbspf_layout_cell h3
778
+ .sbspf_sub_option_cell h3 {
779
+ font-size: 15px;
780
+ margin-top: 0;
781
+ }
782
+ .sbspf_layout_cell img,
783
+ .sbspf_sub_option_cell img {
784
+ width: 100%;
785
+ border: 1px solid #ddd;
786
+ margin-top: 5px;
787
+ }
788
+ .sbspf_box {
789
+ margin-top: 10px;
790
+ margin-bottom: 5px;
791
+ }
792
+ #sbspf_admin .sbspf_layout_settings,
793
+ #sbspf_admin .sbspf_sub_option_settings,
794
+ .sbspf_box_setting{
795
+ float: left;
796
+ clear: both;
797
+ width: 96%;
798
+ max-width: 700px;
799
+
800
+ padding: 15px;
801
+ margin: 0 0 10px 0;
802
+ font-size: 13px;
803
+ background: #f9f9f9;
804
+ background: rgba(255,255,255,0.8);
805
+
806
+ -moz-border-radius: 8px;
807
+ -webkit-border-radius: 8px;
808
+ border-radius: 8px;
809
+ }
810
+ .sbspf_layout_setting,
811
+ .sbspf_sub_option_setting{
812
+ clear:left;
813
+ margin-bottom: 20px;
814
+ }
815
+ #sbspf_admin .sbspf_layout_options_wrap .sbspf-tooltip,
816
+ #sbspf_admin .sbspf_box_setting .sbspf-tooltip{
817
+ width: 98%;
818
+ padding: 10px 1%;
819
+ background: #eee;
820
+ background: rgba(0,0,0,0.05);
821
+ }
822
+ #sbspf_admin .sbspf_layout_mobile_layout_setting {
823
+ width: auto;
824
+ }
825
+
826
+
827
+ /* Display Tab */
828
+ #sbspf_admin table.sbspf_shortcode_table{
829
+ border-collapse: collapse;
830
+ }
831
+ #sbspf_admin table.sbspf_shortcode_table th,
832
+ #sbspf_admin table.sbspf_shortcode_table td{
833
+ border: 1px solid #999;
834
+ padding: 0.5rem;
835
+ text-align: left;
836
+ }
837
+ #sbspf_admin table.sbspf_shortcode_table th{
838
+ background: rgba(0,0,0,0.1);
839
+ }
840
+ #sbspf_admin table.sbspf_shortcode_table td{
841
+ background: rgba(255,255,255,0.5);
842
+ }
843
+ #sbspf_admin .sbspf_table_header{
844
+ background: #ddd;
845
+ font-weight: bold;
846
+ }
847
+
848
+ /* Modal */
849
+
850
+ #sbspf_modal_overlay{
851
+ position: fixed;
852
+ z-index: 999;
853
+ width: 100%;
854
+ top: 0;
855
+ right: 0;
856
+ bottom: 0;
857
+ left: 0;
858
+
859
+ background: rgba(0,0,0,0.3);
860
+ }
861
+ #sbspf_modal_overlay .sbspf_modal{
862
+ position: absolute;
863
+ top: 160px;
864
+ left: 50%;
865
+ width: 450px;
866
+
867
+ margin: 0 0 0 -230px;
868
+ padding: 20px 30px;
869
+ background: #fff;
870
+
871
+ -webkit-box-shadow: 0 1px 20px rgba(0,0,0,0.2);
872
+ box-shadow: 0 1px 20px rgba(0,0,0,0.2);
873
+
874
+ -moz-border-radius: 3px;
875
+ -webkit-border-radius: 3px;
876
+ border-radius: 3px;
877
+ }
878
+ #sbspf_modal_overlay .sbspf_modal p{
879
+ margin: 8px 0;
880
+ }
881
+ #sbspf_modal_overlay .sbspf_modal .sbspf_submit{
882
+ margin-top: 20px;
883
+ }
884
+ #sbspf_modal_overlay .sbspf_modal .heading{
885
+ font-weight: 500;
886
+ font-size: 15px;
887
+ }
888
+ @media all and (max-width: 480px){
889
+ #sbspf_modal_overlay .sbspf_modal{
890
+ max-width: 100%;
891
+ margin: 0 0 0 -50%;
892
+ box-sizing: border-box;
893
+ }
894
+ }
895
+ .sbspf_emphasis {
896
+ display: block;
897
+ font-size: 16px;
898
+ text-align: center;
899
+ margin-bottom: 20px;
900
+ }
901
+ .sbspf_emphasis svg {
902
+ height: 14px;
903
+ }
904
+ .sbspf_modal_message h3 {
905
+ font-size: 14px;
906
+ }
907
+ .sbspf_modal .sbspf_modal_close{
908
+ position: absolute;
909
+ top: 0;
910
+ right: 0;
911
+ padding: 10px;
912
+ font-size: 14px;
913
+ color: #ccc;
914
+ margin: 0;
915
+ }
916
+ .sbspf_modal .sbspf_modal_close:focus,
917
+ .sbspf_modal .sbspf_modal_close:hover{
918
+ color: #333;
919
+ }
920
+ /* Pro only notices */
921
+ #sbspf_admin .sbspf_sub_options,
922
+ #sbspf_admin .sbspf_layout_cell,
923
+ #sbspf_admin .sbspf_layout_settings,
924
+ #sbspf_admin .sbspf_disabled_wrap{
925
+ position: relative;
926
+ }
927
+ #sbspf_admin .sbspf_sub_options:after,
928
+ #sbspf_admin .sbspf_disabled_wrap,
929
+ .sbspf_box:after{
930
+ clear: both;
931
+ display: table;
932
+ content: ""
933
+ }
934
+ #sbspf_admin .sbspf_disabled_wrap{
935
+ width: 100%;
936
+ max-width: 520px;
937
+ }
938
+ #sbspf_admin .sby_includes_pro_only .sbspf_pro_tooltip {
939
+ top: 50%;
940
+ left: 30px;
941
+ bottom: auto;
942
+ margin-top: -96px;
943
+ }
944
+ #sbspf_admin .sbspf-show-pro{
945
+ margin-top: 10px;
946
+ text-align: center;
947
+ }
948
+ .sbspf_layout_cell.sbspf_pro_only .sbspf_lock{
949
+ margin-top: -4px;
950
+ }
951
+ #sbspf_admin .sbspf_layout_cell.sbspf_pro_only .sbspf_pro_tooltip {
952
+ margin-top: -38px;
953
+ left: 54px;
954
+ }
955
+ #sbspf_admin .sbspf_pro_only,
956
+ #sbspf_admin .sbspf_pro_only label,
957
+ #sbspf_admin .sbspf_pro_only input,
958
+ #sbspf_admin .sbspf_pro_only select,
959
+ #sbspf_admin .sbspf_pro_only_row,
960
+ #sbspf_admin .sbspf_pro_only_row label,
961
+ #sbspf_admin .sbspf_pro_only_row input,
962
+ #sbspf_admin .sbspf_pro_only_row select{
963
+ color: #999 !important;
964
+ }
965
+ #sbspf_admin tr.sbspf_pro_only{
966
+ background: #eacccc;
967
+ }
968
+ #sbspf_admin .sbspf_type_row.sbspf_pro_only input[type=text]{
969
+ opacity: 0.5;
970
+ background: white;
971
+ }
972
+ .sbspf_lock.sbspf_pro_lock {
973
+ background: rgba(255,255,255,0.8);
974
+ color: #666;
975
+ border: 1px solid #ccc;
976
+ margin-right: -34px;
977
+ }
978
+ .sbspf_lock.sbspf_pro_lock i {
979
+ margin-right: 8px;
980
+ }
981
+ #sbspf_admin .sbspf_pro_lock:hover,
982
+ #sbspf_admin .sbspf_pro_lock:hover{
983
+ background: #fff;
984
+ border: 1px solid #ccc;
985
+ color: #333;
986
+ box-shadow: 0 0 8px 0 rgba(0,0,0,0.15);
987
+ }
988
+ #sbspf_admin .sbspf_pro_tooltip{
989
+ text-align: center;
990
+ z-index:99;
991
+ display: none;
992
+ position: absolute;
993
+ bottom: 22px;
994
+ left: -8px;
995
+
996
+ background: #333;
997
+ color: #eee;
998
+ width: 90%;
999
+ padding: 8px 10px 10px 10px;
1000
+ border-radius: 3px;
1001
+ line-height: 1.3;
1002
+ font-size: 12px;
1003
+ width: 190px;
1004
+ }
1005
+ #sbspf_admin .sbspf_pro_tooltip .fa-caret-down {
1006
+ position: absolute;
1007
+ bottom: -12px;
1008
+ font-size: 20px;
1009
+ left: 49%;
1010
+ color: #333;
1011
+ }
1012
+ #sbspf_admin .sbspf_layouts .sbspf_pro_tooltip,
1013
+ #sbspf_admin .sbspf_sub_options .sbspf_pro_tooltip{
1014
+ left: 284px;
1015
+ top: -21px;
1016
+ bottom: auto;
1017
+ margin-left: -101px;
1018
+ }
1019
+ #sbspf_admin .sbspf_layouts .sbspf_layout_cell .sbspf_pro_tooltip{
1020
+ left: 84px;
1021
+ top: 32px;
1022
+ }
1023
+ #sbspf_admin .sbspf_table_key{
1024
+ display: block;
1025
+ float: left;
1026
+ width: 11px;
1027
+ height: 11px;
1028
+ border: 1px solid #999;
1029
+ background: #eacccc;
1030
+ margin: 3px 6px 0 0;
1031
+ }
1032
+
1033
+ /* SBY Specific */
1034
+ #sbspf_admin .sby_mode_option {
1035
+ position: relative;
1036
+ margin-bottom: 20px;
1037
+ }
1038
+ #sbspf_admin .sby_mode_option label {
1039
+ display: inline-block;
1040
+ font-weight: bold;
1041
+ }
1042
+ #sbspf_admin .sby_mode_option .sbspf_note {
1043
+ display: block;
1044
+ margin-left: 0;
1045
+ }
1046
+ #sbspf_admin .sby_mode_option .sbspf_note,
1047
+ #sbspf_admin .sby_mode_option label {
1048
+ margin-bottom: 5px;
1049
+ }
1050
+ #sbspf_admin .sby_mode_option input[type=radio] {
1051
+ position: absolute;
1052
+ top: 6px;
1053
+ }
1054
+ #sbspf_admin .sby_mode_option_text {
1055
+ margin-left: 22px;
1056
+ }
1057
+ #sbspf_admin .sby_mode_option.sbspf_fade .sby_important,
1058
+ #sbspf_admin .sby_mode_option.sbspf_fade .sbspf_note {
1059
+ opacity: 1;
1060
+ }
1061
+
1062
+ /* Notices */
1063
+ .sby_includes_pro_only .sbspf_lock {
1064
+ left: 100px;
1065
+ right: auto;
1066
+ margin-top: -40px;
1067
+ }
1068
+ .sbspf_sub_options .sbspf_lock {
1069
+ top: 38px;
1070
+ left: 260px;
1071
+ right: auto;
1072
+ }
1073
+ .sby_types_disabled_wrap .sbspf_lock {
1074
+ margin-top: -20px;
1075
+ }
1076
+ #sbspf_admin .sby_types_disabled_wrap .sbspf_pro_tooltip {
1077
+ top: 50%;
1078
+ margin-left: -112px;
1079
+ margin-top: -78px;
1080
+ bottom: auto;
1081
+ left: 50%;
1082
+ }
1083
+ @media screen and (max-width: 480px) {
1084
+ .sbspf_sub_options .sbspf_lock {
1085
+ top: 60px;
1086
+ left: 50%;
1087
+ margin-left: -40px;
1088
+ right: auto;
1089
+ }
1090
+ #sbspf_admin .sbspf_sub_options .sbspf_pro_tooltip {
1091
+ top: 0px;
1092
+ left: 50%;
1093
+ margin-left: -112px;
1094
+ }
1095
+ }
1096
+
1097
+ /* Lite Notice */
1098
+ @media screen and (max-width: 600px) {
1099
+ #sbspf-notice-bar {
1100
+ display:none !important
1101
+ }
1102
+ }
1103
+
1104
+ #sbspf-notice-bar {
1105
+ background-color: #DDDDDD;
1106
+ color: #777777;
1107
+ text-align: center;
1108
+ position: relative;
1109
+ padding: 7px;
1110
+ margin-bottom: 0;
1111
+ opacity: 1;
1112
+ transition: all .3s ease-in-out;
1113
+ max-height: 100px;
1114
+ overflow: hidden
1115
+ }
1116
+
1117
+ #sbspf-notice-bar.out {
1118
+ opacity: .5;
1119
+ max-height: 0
1120
+ }
1121
+
1122
+ #sbspf-notice-bar a {
1123
+ color: #e34f0e;
1124
+ }
1125
+
1126
+ #sbspf-notice-bar a:hover {
1127
+ color: #b85a1b
1128
+ }
1129
+
1130
+ #sbspf-notice-bar .dismiss {
1131
+ position: absolute;
1132
+ top: 0;
1133
+ right: 0;
1134
+ border: none;
1135
+ padding: 5px;
1136
+ margin-top: 1px;
1137
+ background: 0 0;
1138
+ color: #72777c;
1139
+ cursor: pointer
1140
+ }
1141
+
1142
+ #sbspf-notice-bar .dismiss:before {
1143
+ background: 0 0;
1144
+ color: #72777c;
1145
+ content: "\f335";
1146
+ display: block;
1147
+ font: normal 20px/20px dashicons;
1148
+ speak: none;
1149
+ height: 20px;
1150
+ text-align: center;
1151
+ width: 20px;
1152
+ -webkit-font-smoothing: antialiased
1153
+ }
1154
+
1155
+ /* Locator Summary */
1156
+ .sby-feed-locator-summary-wrap {
1157
+ max-width: 1100px;
1158
+ margin-bottom: 40px;
1159
+ }
1160
+ .sby-full-wrap {
1161
+ display: none;
1162
+ }
1163
+ .sby-locator-more {
1164
+ display: inline-block;
1165
+ margin: 0 0 0 1px;
1166
+ padding: 0 5px;
1167
+ border: 1px solid rgba(0,0,0,0.1);
1168
+ border-radius: 3px;
1169
+ line-height: 1.6;
1170
+ }
1171
+
1172
+ .sby_shortcode_visible .sby_locations_link {
1173
+ display: none;
1174
+ }
1175
+ .sby_locations_link a {
1176
+ font-weight: normal;
1177
+ text-decoration: none;
1178
+ }
1179
+ .sby_locations_link svg {
1180
+ width: 11px;
1181
+ position: relative;
1182
+ top: 1px;
1183
  }
css/sb-youtube.css CHANGED
@@ -1,1394 +1,1398 @@
1
- /**************/
2
- /*** LAYOUT ***/
3
- /**************/
4
-
5
- /* Feed container */
6
- [id^=sb_youtube_].sb_youtube {
7
- width: 100%;
8
- margin: 0 auto;
9
- padding: 0;
10
- -webkit-box-sizing: border-box;
11
- -moz-box-sizing: border-box;
12
- box-sizing: border-box;
13
- }
14
- [id^=sb_youtube_].sb_youtube * {
15
- -webkit-box-sizing: border-box;
16
- -moz-box-sizing: border-box;
17
- box-sizing: border-box
18
- }
19
- [id^=sb_youtube_].sb_youtube:after{
20
- content: "";
21
- display: table;
22
- clear: both;
23
- }
24
- [id^=sb_youtube_].sb_youtube iframe,
25
- #sby_lightbox iframe{
26
- pointer-events: all !important;
27
- }
28
-
29
- /*********************/
30
- /*** STYLE OPTIONS ***/
31
- /*********************/
32
- [id^=sb_youtube_].sb_youtube.sby_fixed_height{
33
- overflow: hidden;
34
- overflow-y: auto;
35
- -webkit-box-sizing: border-box;
36
- -moz-box-sizing: border-box;
37
- box-sizing: border-box;
38
- }
39
- [id^=sb_youtube_].sb_youtube .sby_items_wrap{
40
- width: 100%;
41
- float: left;
42
- line-height: 0;
43
-
44
- -webkit-box-sizing: border-box;
45
- -moz-box-sizing: border-box;
46
- box-sizing: border-box;
47
- }
48
-
49
- /* Items */
50
- [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item,
51
- [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_video_thumbnail_wrap,
52
- [id^=sb_youtube_].sb_youtube .sby_player_wrap{
53
- display: -moz-inline-stack;
54
- display: inline-block;
55
- vertical-align: top;
56
- zoom: 1;
57
- *display: inline;
58
-
59
- max-height: 1000px;
60
- padding: inherit !important;
61
- text-decoration: none;
62
- opacity: 1;
63
- overflow: hidden;
64
-
65
- -webkit-box-sizing: border-box;
66
- -moz-box-sizing: border-box;
67
- box-sizing: border-box;
68
-
69
- -webkit-transition: all 0.5s ease;
70
- -moz-transition: all 0.5s ease;
71
- -o-transition: all 0.5s ease;
72
- -ms-transition: all 0.5s ease;
73
- transition: all 0.5s ease;
74
- }
75
- [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_no_margin {
76
- margin: 0 !important;
77
- }
78
- [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item {
79
- float: left;
80
- }
81
- /* Transition items in */
82
- [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_transition{
83
- opacity: 0;
84
- max-height: 0;
85
- }
86
-
87
- /* Cols */
88
- [id^=sb_youtube_].sb_youtube.sby_col_0 .sby_items_wrap .sby_item{ width: 100%; }
89
- [id^=sb_youtube_].sb_youtube.sby_col_1 .sby_items_wrap .sby_item{ width: 100%; }
90
- [id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{ width: 50%; }
91
- [id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{ width: 33.33%; }
92
- [id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{ width: 25%; }
93
- [id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{ width: 20%; }
94
- [id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{ width: 16.66%; }
95
- [id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{ width: 14.28%; }
96
- [id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{ width: 12.5%; }
97
- [id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{ width: 11.11%; }
98
- [id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{ width: 10%; }
99
-
100
- /* Disable mobile layout */
101
- /*
102
- [id^=sb_youtube_].sb_youtube.sby_col_1.sby_disable_mobile .sby_items_wrap .sby_item{ width: 100%; }
103
- [id^=sb_youtube_].sb_youtube.sby_col_2.sby_disable_mobile .sby_items_wrap .sby_item{ width: 50%; }
104
- [id^=sb_youtube_].sb_youtube.sby_col_3.sby_disable_mobile .sby_items_wrap .sby_item{ width: 33.33%; }
105
- [id^=sb_youtube_].sb_youtube.sby_col_4.sby_disable_mobile .sby_items_wrap .sby_item{ width: 25%; }
106
- [id^=sb_youtube_].sb_youtube.sby_col_5.sby_disable_mobile .sby_items_wrap .sby_item{ width: 20%; }
107
- [id^=sb_youtube_].sb_youtube.sby_col_6.sby_disable_mobile .sby_items_wrap .sby_item{ width: 16.66%; }
108
- [id^=sb_youtube_].sb_youtube.sby_col_7.sby_disable_mobile .sby_items_wrap .sby_item{ width: 14.28%; }
109
- [id^=sb_youtube_].sb_youtube.sby_col_8.sby_disable_mobile .sby_items_wrap .sby_item{ width: 12.5%; }
110
- [id^=sb_youtube_].sb_youtube.sby_col_9.sby_disable_mobile .sby_items_wrap .sby_item{ width: 11.11%; }
111
- [id^=sb_youtube_].sb_youtube.sby_col_10.sby_disable_mobile .sby_items_wrap .sby_item{ width: 10%; }
112
- */
113
- /* Photos */
114
- .sby-screenreader{text-indent: -9999px !important;display: block !important;width: 0 !important;height: 0 !important;line-height: 0 !important;}
115
- [id^=sb_youtube_].sb_youtube .sby_video_thumbnail_wrap,
116
- [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap {
117
- width: 100%;
118
- position: relative;
119
- float: left;
120
- }
121
- [id^=sb_youtube_].sb_youtube .sby_video_thumbnail{
122
- display: block;
123
- position: relative;
124
- text-decoration: none;
125
- line-height: 0;
126
- z-index: 5;
127
- }
128
- [id^=sb_youtube_].sb_youtube .sby_video_thumbnail img{
129
- width: 100%;
130
- height: auto;
131
- border-radius: 0;
132
- }
133
- [id^=sb_youtube_].sb_youtube .sby_link{
134
- display: none;
135
- position: absolute;
136
- z-index: 1;
137
- top: 0;
138
- right: 0;
139
- bottom: 0;
140
- left: 0;
141
-
142
- width: 100%;
143
- padding: 0;
144
- background: #333;
145
- background: rgba(0,0,0,0.6);
146
- text-align: center;
147
- color: #fff;
148
- font-size: 12px;
149
- line-height: 1.1;
150
- overflow: hidden;
151
- }
152
- [id^=sb_youtube_].sb_youtube .sby_link.sby_default p,
153
- [id^=sb_youtube_].sb_youtube .sby_link.sby_default span,
154
- [id^=sb_youtube_].sb_youtube .sby_link.sby_default a{
155
- text-shadow: 0px 0px 10px #000;
156
- }
157
- [id^=sb_youtube_].sb_youtube .sby_link .sby_username a,
158
- [id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link,
159
- [id^=sb_youtube_].sb_youtube .sby_link .sby_hover_bottom,
160
- [id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn,
161
- [id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link,
162
- [id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play{
163
- filter: alpha(opacity=90);
164
- opacity: 0.9;
165
- }
166
- [id^=sb_youtube_].sb_youtube .sby_link .sby_username a:hover,
167
- [id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link:hover,
168
- [id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn:hover,
169
- [id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link:hover,
170
- [id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play:hover{
171
- filter: alpha(opacity=100);
172
- opacity: 1;
173
- }
174
- [id^=sb_youtube_].sb_youtube .sby_link_area{
175
- position: absolute;
176
- top: 0;
177
- right: 0;
178
- bottom: 0;
179
- left: 0;
180
- z-index: 1;
181
- }
182
-
183
- [id^=sb_youtube_].sb_youtube .sby_link a{
184
- padding: 0;
185
- text-decoration: none;
186
- color: #ddd;
187
- color: rgba(255,255,255,0.7);
188
- line-height: 1.1;
189
- background: none;
190
-
191
- display: -moz-inline-stack;
192
- display: inline-block;
193
- vertical-align: top;
194
- zoom: 1;
195
- *display: inline;
196
- }
197
- [id^=sb_youtube_].sb_youtube .sby_link a:hover,
198
- [id^=sb_youtube_].sb_youtube .sby_link a:active{
199
- color: #fff;
200
- }
201
-
202
- [id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link{
203
- display: block;
204
- /*display: none;*/
205
- position: absolute;
206
- z-index: 2;
207
- top: 50%;
208
- left: 50%;
209
-
210
- margin-top: -24px;
211
- margin-left: -21px;
212
- padding: 0;
213
- font-size: 49px;
214
- font-style: normal !important;
215
- }
216
- [id^=sb_youtube_].sb_youtube .sby_type_video .sby_lightbox_link,
217
- [id^=sb_youtube_].sb_youtube .sby_carousel_vid_first .sby_lightbox_link{
218
- display: none;
219
- }
220
-
221
- [id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link{
222
- /*float: right;*/
223
- font-size: 30px;
224
- position: absolute;
225
- z-index: 100;
226
- bottom: 0;
227
- right: 2px;
228
- padding: 8px;
229
- }
230
- [id^=sb_youtube_].sb_youtube .sby_link a:hover,
231
- [id^=sb_youtube_].sb_youtube .sby_link a:focus{
232
- text-decoration: underline;
233
- }
234
-
235
- /* Player */
236
- [id^=sb_youtube_].sb_youtube .sby_player_wrap {
237
- z-index: 1;
238
- width: 100% !important;
239
- height: 100% !important;
240
- position: absolute;
241
- top: 0;
242
- left: 0;
243
- }
244
- [id^=sb_youtube_].sb_youtube .sby_player_wrap iframe {
245
- width: 100% !important;
246
- height: 100% !important;
247
- }
248
-
249
- /* Use CSS for lightbox fade instead of JS */
250
- [id^=sb_youtube_].sb_youtube .sby_thumbnail_hover {
251
- opacity: 0;
252
- display: block;
253
- position: absolute;
254
- top: 0;
255
- right: 0;
256
- bottom: 0;
257
- left: 0;
258
- z-index: 10;
259
- color: #fff;
260
- background: #333;
261
- background: rgba(0,0,0,.6);
262
- transition: opacity .6s ease-in-out;
263
- -moz-transition: opacity .6s ease-in-out;
264
- -webkit-transition: opacity .6s ease-in-out;
265
- }
266
- [id^=sb_youtube_].sb_youtube.sby_layout_list .sby_thumbnail_hover {
267
- display: none;
268
- }
269
- .sby_video_title {
270
- display: inline-block;
271
- height: 100%;
272
- padding: 10px;
273
- overflow: hidden;
274
- font-size: 13px;
275
- line-height: 1.2;
276
- }
277
- [id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_thumbnail_hover {
278
- opacity: 1;
279
- display: block;
280
- transition: opacity .2s ease-in-out;
281
- -moz-transition: opacity .2s ease-in-out;
282
- -webkit-transition: opacity .2s ease-in-out;
283
- }
284
- [id^=sb_youtube_].sb_youtube .sby_current .sby_thumbnail_hover {
285
- opacity: 1;
286
- }
287
- [id^=sb_youtube_].sb_youtube.sby_layout_list .sby_video_thumbnail:hover .sby_thumbnail_hover {
288
- opacity: 0;
289
- display: none;
290
- transition: none;
291
- -moz-transition: none;
292
- -webkit-transition: none;
293
- }
294
-
295
- a.sby_video_thumbnail:after {
296
- box-shadow: inset 0 0 1px 0 rgba(0,0,0,0.7);
297
- bottom: 0;
298
- content: '';
299
- left: 0;
300
- position: absolute;
301
- z-index: 1;
302
- right: 0;
303
- top: 0;
304
- width: 100%;
305
- }
306
-
307
- /* Play Button */
308
- [id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_play_btn {
309
- opacity: .5;
310
- }
311
- [id^=sb_youtube_].sb_youtube .sby_play_btn {
312
- position: absolute;
313
- z-index: 1;
314
- left: 50%;
315
- bottom: 50%;
316
- top: 50%;
317
- right: 50%;
318
- margin-top: -25px;
319
- margin-left: -28px;
320
- color: #fff;
321
- width: 57px;
322
- height: 50px;
323
- opacity: 1;
324
- transition: opacity .2s ease-in-out;
325
- -moz-transition: opacity .2s ease-in-out;
326
- -webkit-transition: opacity .2s ease-in-out;
327
- }
328
- [id^=sb_youtube_].sb_youtube .sby_play_btn_bg {
329
- display: block;
330
- position: absolute;
331
- z-index: -1;
332
- top: 17px;
333
- left: 22px;
334
- width: 0;
335
- height: 0;
336
- border: 0 solid transparent;
337
- border-bottom-width: 9px;
338
- border-top-width: 9px;
339
- border-left: 16px solid #fff;
340
- }
341
- [id^=sb_youtube_].sb_youtube .sby_play_btn svg:not(:root).svg-inline--fa{
342
- width: 57px;
343
- height: auto;
344
- opacity: 0.75;
345
- }
346
-
347
- [id^=sb_youtube_].sb_youtube .sby_play_btn svg,
348
- [id^=sb_youtube_].sb_youtube .sby_play_btn i{
349
- color: #000;
350
- }
351
- /* Medium */
352
- [id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn {
353
- margin-top: -20px;
354
- margin-left: -22px;
355
- width: 45px;
356
- height: 40px;
357
- }
358
- [id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn_bg {
359
- top: 13px;
360
- left: 18px;
361
- border-bottom-width: 7px;
362
- border-top-width: 7px;
363
- border-left: 12px solid #fff;
364
- }
365
- [id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn svg:not(:root).svg-inline--fa{
366
- width: 45px;
367
- }
368
-
369
- /* Small */
370
- [id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn{
371
- margin-top: -16px;
372
- margin-left: -18px;
373
- width: 36px;
374
- height: 32px;
375
- }
376
- [id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn_bg {
377
- top: 10px;
378
- left: 14px;
379
- border-bottom-width: 6px;
380
- border-top-width: 6px;
381
- border-left: 10px solid #fff;
382
- }
383
- [id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn svg:not(:root).svg-inline--fa{
384
- width: 36px;
385
- }
386
-
387
- /* Loader */
388
- [id^=sb_youtube_].sb_youtube .sby_loader{
389
- width: 20px;
390
- height: 20px;
391
-
392
- position: relative;
393
- top: 50%;
394
- left: 50%;
395
- margin: -10px 0 0 -10px;
396
- background-color: #000;
397
- background-color: rgba(0,0,0,0.5);
398
-
399
- border-radius: 100%;
400
- -webkit-animation: sby-sk-scaleout 1.0s infinite ease-in-out;
401
- animation: sby-sk-scaleout 1.0s infinite ease-in-out;
402
- }
403
- [id^=sb_youtube_].sb_youtube .sb_youtube_header br,
404
- [id^=sb_youtube_].sb_youtube .sby_items_wrap br,
405
- [id^=sb_youtube_].sb_youtube .sby_footer br{
406
- display: none;
407
- }
408
- .sby_footer p {
409
- display: inline;
410
- padding: 0;
411
- margin: 0;
412
- }
413
- /* Loader in button */
414
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_loader,
415
- [id^=sb_youtube_].sb_youtube .sby_item .sby_loader,
416
- [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_loader{
417
- position: absolute;
418
- margin-top: -11px;
419
- background-color: #fff;
420
- }
421
- [id^=sb_youtube_].sb_youtube .sby_item.sby_player_loading,
422
- [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap.sby_player_loading {
423
- opacity: .8;
424
- }
425
- @-webkit-keyframes sby-sk-scaleout {
426
- 0% { -webkit-transform: scale(0) }
427
- 100% {
428
- -webkit-transform: scale(1.0);
429
- opacity: 0;
430
- }
431
- }
432
- @keyframes sby-sk-scaleout {
433
- 0% {
434
- -webkit-transform: scale(0);
435
- -ms-transform: scale(0);
436
- transform: scale(0);
437
- } 100% {
438
- -webkit-transform: scale(1.0);
439
- -ms-transform: scale(1.0);
440
- transform: scale(1.0);
441
- opacity: 0;
442
- }
443
- }
444
-
445
- [id^=sb_youtube_].sb_youtube .fa-spin,
446
- #sby_lightbox .fa-spin{
447
- -webkit-animation: fa-spin 2s infinite linear;
448
- animation: fa-spin 2s infinite linear
449
- }
450
-
451
- [id^=sb_youtube_].sb_youtube .fa-pulse,
452
- #sby_lightbox .fa-pulse{
453
- -webkit-animation: fa-spin 1s infinite steps(8);
454
- animation: fa-spin 1s infinite steps(8)
455
- }
456
-
457
- @-webkit-keyframes fa-spin {
458
- 0% {
459
- -webkit-transform: rotate(0deg);
460
- transform: rotate(0deg)
461
- }
462
- 100% {
463
- -webkit-transform: rotate(359deg);
464
- transform: rotate(359deg)
465
- }
466
- }
467
-
468
- @keyframes fa-spin {
469
- 0% {
470
- -webkit-transform: rotate(0deg);
471
- transform: rotate(0deg)
472
- }
473
- 100% {
474
- -webkit-transform: rotate(359deg);
475
- transform: rotate(359deg)
476
- }
477
- }
478
-
479
- /* HEADER */
480
- [id^=sb_youtube_].sb_youtube .sb_youtube_header{
481
- float: left;
482
- clear: both;
483
- margin: 0 0 15px 0;
484
- padding: 0;
485
- line-height: 1.2;
486
- width: 100%;
487
- }
488
- [id^=sb_youtube_].sb_youtube .sb_youtube_header a{
489
- float: left;
490
- display: block;
491
- /*width: 100%;*/
492
- min-width: 100%\9;
493
- text-decoration: none;
494
- transition: color 0.5s ease;
495
- }
496
- /** Medium Header */
497
- /* Only use medium & large headers on devices above 480px */
498
- @media all and (min-width: 480px){
499
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img {
500
- width: 80px;
501
- height: 80px;
502
- border-radius: 40px;
503
- }
504
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img img {
505
- width: 80px;
506
- height: 80px;
507
- border-radius: 40px;
508
- }
509
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3 {
510
- font-size: 20px;
511
- }
512
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info,
513
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio{
514
- font-size: 14px;
515
- }
516
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3,
517
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info,
518
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio{
519
- margin-left: 95px !important;
520
- line-height: 1.4
521
- }
522
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{
523
- margin-right: -85px !important;
524
- }
525
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info{
526
- margin-top: 4px !important;
527
- }
528
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text.sby_no_bio h3{
529
- padding-top: 20px !important;
530
- }
531
- /** Large Header */
532
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img {
533
- width: 120px;
534
- height: 120px;
535
- border-radius: 60px;
536
- }
537
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img img {
538
- width: 120px;
539
- height: 120px;
540
- border-radius: 60px;
541
- }
542
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3 {
543
- font-size: 28px;
544
- }
545
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info,
546
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio{
547
- font-size: 16px;
548
- }
549
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3,
550
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info,
551
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio{
552
- margin-left: 140px !important;
553
- line-height: 1.5;
554
- }
555
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{
556
- margin-right: -120px !important;
557
- }
558
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info{
559
- margin-top: 12px !important;
560
- }
561
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text.sby_no_bio h3{
562
- padding-top: 32px !important;
563
- }
564
- }
565
-
566
- /* Header profile pic */
567
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img{
568
- float: left;
569
- position: relative;
570
- width: 50px;
571
- margin: 0 0 0 -100% !important;
572
- overflow: hidden;
573
-
574
- -moz-border-radius: 40px;
575
- -webkit-border-radius: 40px;
576
- border-radius: 40px;
577
- }
578
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img img{
579
- float: left;
580
- margin: 0 !important;
581
- padding: 0 !important;
582
- border: none !important;
583
-
584
- -moz-border-radius: 40px;
585
- -webkit-border-radius: 40px;
586
- border-radius: 40px;
587
- }
588
- /* Profile pic hover */
589
- /* Profile pic hover */
590
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{
591
- opacity: 0;
592
- position: absolute;
593
- width: 100%;
594
- top: 0;
595
- bottom: 0;
596
- left: 0;
597
- text-align: center;
598
- color: #fff;
599
- background: rgba(0,0,0,0.75);
600
- }
601
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img {
602
- height: 50px;
603
- }
604
- [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img_hover{
605
- opacity: 1;
606
- }
607
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover .sby_new_logo{
608
- position: absolute;
609
- top: 50%;
610
- left: 50%;
611
- margin-top: -12px;
612
- margin-left: -12px;
613
- width: 24px;
614
- height: 24px;
615
- font-size: 24px;
616
- }
617
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover i {
618
- overflow: hidden;
619
- background: url('../img/small-logo.png') no-repeat 0 0;
620
- }
621
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{
622
- z-index: 2;
623
- transition: opacity 0.4s ease-in-out;
624
- }
625
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_fade_in{
626
- opacity: 1;
627
- transition: opacity 0.2s ease-in-out;
628
- }
629
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{
630
- position: absolute;
631
- width: 100%;
632
- top: 0;
633
- bottom: 0;
634
- left: 0;
635
- text-align: center;
636
- color: #fff;
637
- background: rgba(0,0,0,0.75);
638
-
639
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
640
- filter: alpha(opacity=0);
641
- -moz-opacity: 0;
642
- -khtml-opacity: 0;
643
- opacity: 0;
644
- border-radius: 40px;
645
- transition: opacity 0.2s;
646
- }
647
- /* Fade the Youtube icon in when hovering on the header */
648
- [id^=sb_youtube_].sb_youtube .sb_youtube_header a:hover .sby_header_img_hover,
649
- [id^=sb_youtube_].sb_youtube .sb_youtube_header a:focus .sby_header_img_hover{
650
- opacity: 1;
651
- }
652
- /* Header text */
653
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text{
654
- float: left;
655
- width: 100%;
656
- padding-top: 5px;
657
- }
658
- [id^=sb_youtube_].sb_youtube .sb_youtube_header a{
659
- text-decoration: none;
660
- }
661
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text .sby_bio,
662
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text h3{
663
- float: left;
664
- clear: both;
665
- width: auto;
666
- margin: 0 0 0 60px !important;
667
- padding: 0 !important;
668
- }
669
- [id^=sb_youtube_].sb_youtube .sb_youtube_header h3{
670
- font-size: 16px;
671
- line-height: 1.3;
672
- }
673
- [id^=sb_youtube_].sb_youtube .sb_youtube_header p{
674
- font-size: 13px;
675
- line-height: 1.3;
676
- margin: 0;
677
- padding: 0;
678
- }
679
- [id^=sb_youtube_].sb_youtube p:empty { display: none; }
680
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text img.emoji{
681
- margin-right: 3px !important;
682
- }
683
-
684
- /* No bio */
685
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio h3{
686
- padding-top: 9px !important;
687
- }
688
- [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio .sby_bio_info{
689
- clear: both;
690
- }
691
-
692
- /* Buttons */
693
- [id^=sb_youtube_].sb_youtube .sby_footer{
694
- float: left;
695
- clear: both;
696
- width: 100%;
697
- text-align: center;
698
- }
699
- [id^=sb_youtube_].sb_youtube .sby_footer .fa-spinner{
700
- display: none;
701
- position: absolute;
702
- top: 50%;
703
- left: 50%;
704
- margin: -8px 0 0 -7px;
705
- font-size: 15px;
706
- }
707
- [id^=sb_youtube_].sb_youtube .sby_footer{
708
- opacity: 1;
709
- transition: all 0.5s ease-in;
710
- }
711
- [id^=sb_youtube_].sb_youtube .sby_load_btn .sby_btn_text, [id^=sb_youtube_].sb_youtube .sby_load_btn .sby_loader{
712
- opacity: 1;
713
- transition: all 0.1s ease-in;
714
- }
715
- [id^=sb_youtube_].sb_youtube .sby_hidden{
716
- opacity: 0 !important;
717
- }
718
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn,
719
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a{
720
- display: -moz-inline-stack;
721
- display: inline-block;
722
- vertical-align: top;
723
- zoom: 1;
724
- *display: inline;
725
-
726
- padding: 7px 14px;
727
- margin: 5px auto 0 auto;
728
- background: #333;
729
- color: #eee;
730
- border: none;
731
- color: #fff;
732
- text-decoration: none;
733
- font-size: 13px;
734
- line-height: 1.5;
735
-
736
- -moz-border-radius: 4px;
737
- -webkit-border-radius: 4px;
738
- border-radius: 4px;
739
-
740
- -webkit-box-sizing: border-box;
741
- -moz-box-sizing: border-box;
742
- box-sizing: border-box;
743
- }
744
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn {
745
- position: relative;
746
- }
747
- /* Follow button */
748
- [id^=sb_youtube_].sb_youtube .sby_follow_btn{
749
- display: -moz-inline-stack;
750
- display: inline-block;
751
- vertical-align: top;
752
- zoom: 1;
753
- *display: inline;
754
- text-align: center;
755
- }
756
- [id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_top{
757
- display: block;
758
- margin-bottom: 5px;
759
- }
760
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a{
761
- background: #408bd1;
762
- color: #fff;
763
- }
764
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a,
765
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a,
766
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{
767
- transition: all 0.1s ease-in;
768
- }
769
- /* Hover state for default colors */
770
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:hover{
771
- outline: none;
772
- box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.25);
773
- }
774
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a:hover,
775
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a:focus{
776
- outline: none;
777
- box-shadow: inset 0 0 10px 20px #359dff;
778
- }
779
- /* If a custom color is applied then just use opacity for the hover effect */
780
- [id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:hover,
781
- [id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:focus,
782
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn.sby_custom:hover{
783
- box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.15);
784
- }
785
- /* Active state */
786
- [id^=sb_youtube_].sb_youtube .sby_follow_btn a:active,
787
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:active{
788
- box-shadow: inset 0 0 10px 20px rgba(0,0,0,0.3);
789
- }
790
-
791
- [id^=sb_youtube_].sb_youtube .sby_follow_btn .fa,
792
- [id^=sb_youtube_].sb_youtube .sby_follow_btn svg{
793
- margin-bottom: -1px;
794
- margin-right: 7px;
795
- font-size: 15px;
796
- }
797
- [id^=sb_youtube_].sb_youtube .sby_follow_btn svg{
798
- vertical-align: -.125em;
799
- }
800
- [id^=sb_youtube_].sb_youtube .sby_footer .sby_follow_btn{
801
- margin-left: 5px;
802
- }
803
-
804
- /* Media queries */
805
- @media all and (max-width: 640px){
806
- /* Make 3-6 cols into 2 col */
807
- [id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,
808
- [id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,
809
- [id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,
810
- [id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item{
811
- width: 50%;
812
- }
813
- /* Make 7-10 cols into 4 col */
814
- [id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item,
815
- [id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item,
816
- [id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item,
817
- [id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item,
818
- [id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,
819
- [id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,
820
- [id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item,
821
- [id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item{
822
- width: 25%;
823
- }
824
- [id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{ width: 50%; }
825
- [id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{ width: 33.33%; }
826
- [id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{ width: 25%; }
827
- [id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{ width: 20%; }
828
- [id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{ width: 16.66%; }
829
- [id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{ width: 14.28%; }
830
- [id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{ width: 12.5%; }
831
- [id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{ width: 11.11%; }
832
- [id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{ width: 10%; }
833
- /* On mobile make the min-width 100% */
834
- [id^=sb_youtube_].sb_youtube.sby_width_resp{
835
- width: 100% !important;
836
- }
837
- }
838
- @media all and (max-width: 480px){
839
- /* Make all cols into 1 col */
840
- [id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,
841
- [id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,
842
- [id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,
843
- [id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item,
844
- [id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,
845
- [id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,
846
- [id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item,
847
- [id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item,
848
- [id^=sb_youtube_].sb_youtube.sby_mob_col_1 .sby_items_wrap .sby_item{
849
- width: 100%;
850
- }
851
- [id^=sb_youtube_].sb_youtube.sby_mob_col_2 .sby_items_wrap .sby_item{ width: 50%; }
852
- [id^=sb_youtube_].sb_youtube.sby_mob_col_3 .sby_items_wrap .sby_item{ width: 33.33%; }
853
- [id^=sb_youtube_].sb_youtube.sby_mob_col_4 .sby_items_wrap .sby_item{ width: 25%; }
854
- [id^=sb_youtube_].sb_youtube.sby_mob_col_5 .sby_items_wrap .sby_item{ width: 20%; }
855
- [id^=sb_youtube_].sb_youtube.sby_mob_col_6 .sby_items_wrap .sby_item{ width: 16.66%; }
856
- [id^=sb_youtube_].sb_youtube.sby_mob_col_7 .sby_items_wrap .sby_item{ width: 14.28%; }
857
- }
858
-
859
- /* --- Lightbox --- */
860
-
861
- .sby_lightboxOverlay {
862
- position: absolute;
863
- top: 0;
864
- left: 0;
865
- z-index: 99999;
866
- background-color: black;
867
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
868
- opacity: 0.9;
869
- display: none;
870
- }
871
- .sby_lightbox {
872
- position: absolute;
873
- left: 0;
874
- width: 100%;
875
- z-index: 100000;
876
- line-height: 0;
877
- font-weight: normal;
878
- }
879
- .sby_lightbox .sby_lb-image {
880
- display: block;
881
- height: auto;
882
- max-width: inherit;
883
- -webkit-border-radius: 3px;
884
- -moz-border-radius: 3px;
885
- -ms-border-radius: 3px;
886
- -o-border-radius: 3px;
887
- border-radius: 3px;
888
- }
889
- .sby_lightbox a:hover,
890
- .sby_lightbox a:focus,
891
- .sby_lightbox a:active{
892
- outline: none;
893
- }
894
- .sby_lightbox a img {
895
- border: none;
896
- }
897
- .sby_lb-outerContainer {
898
- position: relative;
899
- background-color: #000;
900
- *zoom: 1;
901
- width: 250px;
902
- height: 250px;
903
- margin: 0 auto 5px auto;
904
- -webkit-border-radius: 3px;
905
- -moz-border-radius: 3px;
906
- -ms-border-radius: 3px;
907
- -o-border-radius: 3px;
908
- border-radius: 3px;
909
- }
910
- .sby_lb-outerContainer:after {
911
- content: "";
912
- display: table;
913
- clear: both;
914
- }
915
- .sby_lb-container {
916
- position: relative;
917
- padding: 4px;
918
- top: 0;
919
- left: 0;
920
- width: 100%;
921
- height: 100%;
922
- bottom: 0;
923
- right: 0;
924
-
925
- -webkit-border-radius: 3px;
926
- -moz-border-radius: 3px;
927
- -ms-border-radius: 3px;
928
- -o-border-radius: 3px;
929
- border-radius: 3px;
930
- }
931
- .sby_lb-loader {
932
- position: absolute;
933
- top: 43%;
934
- left: 0;
935
- height: 25%;
936
- width: 100%;
937
- text-align: center;
938
- line-height: 0;
939
- }
940
- .sby_lb-cancel {
941
- display: block;
942
- width: 32px;
943
- height: 32px;
944
- margin: 0 auto;
945
- background-color: #666;
946
- background-color: rgba(255,255,255,0.5);
947
-
948
- border-radius: 100%;
949
- -webkit-animation: ctf-sk-scaleout 1.0s infinite ease-in-out;
950
- animation: ctf-sk-scaleout 1.0s infinite ease-in-out;
951
- }
952
-
953
-
954
- .sby_lb-nav {
955
- /*position: absolute;*/
956
- top: 0;
957
- left: 0;
958
- /*height: 100%;*/
959
- width: 100%;
960
- z-index: 10;
961
- /*pointer-events: none;*/
962
- }
963
- .sby_lb-container > .nav {
964
- left: 0;
965
- }
966
- .sby_lb-nav a {
967
- position: absolute;
968
- z-index: 100;
969
- top: 0;
970
- height: 90%;
971
- outline: none;
972
- background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
973
- }
974
-
975
-
976
- /* Arrows */
977
- .sby_lb-prev, .sby_lb-next {
978
- height: 100%;
979
- cursor: pointer;
980
- display: block;
981
- }
982
- .sby_lb-nav a.sby_lb-prev {
983
- /*width: 30%;*/
984
- width: 50px;
985
- left: -70px;
986
- padding-left: 10px;
987
- padding-right: 10px;
988
- float: left;
989
-
990
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0.5);
991
- opacity: 0.5;
992
- -webkit-transition: opacity 0.2s;
993
- -moz-transition: opacity 0.2;
994
- -o-transition: opacity 0.2s;
995
- transition: opacity 0.2s;
996
-
997
- }
998
-
999
- .sby_lb-nav a.sby_lb-prev:hover {
1000
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1001
- opacity: 1;
1002
- }
1003
-
1004
- .sby_lb-nav a.sby_lb-next {
1005
- /*width: 30%;*/
1006
- width: 50px;
1007
- right: -70px;
1008
- padding-left: 10px;
1009
- padding-right: 10px;
1010
- float: right;
1011
-
1012
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0.5);
1013
- opacity: 0.5;
1014
- -webkit-transition: opacity 0.2s;
1015
- -moz-transition: opacity 0.2s;
1016
- -o-transition: opacity 0.2s;
1017
- transition: opacity 0.2s;
1018
-
1019
- }
1020
-
1021
- .sby_lb-nav a.sby_lb-next:hover {
1022
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1023
- opacity: 1;
1024
- }
1025
-
1026
- .sby_lb-nav span{
1027
- display: block;
1028
- top: 55%;
1029
- position: absolute;
1030
- left: 20px;
1031
- width: 34px;
1032
- height: 45px;
1033
- margin: -25px 0 0 0;
1034
- background: url(../img/sby-sprite.png) no-repeat;
1035
- }
1036
- .sby_lb-nav a.sby_lb-prev span{
1037
- background-position: -53px 0;
1038
- }
1039
- .sby_lb-nav a.sby_lb-next span{
1040
- left: auto;
1041
- right: 20px;
1042
- background-position: -18px 0;
1043
- }
1044
-
1045
-
1046
- .sby_lb-dataContainer {
1047
- margin: 0 auto;
1048
- padding-top: 5px;
1049
- *zoom: 1;
1050
- width: 100%;
1051
- font-family: "Open Sans", Helvetica, Arial, sans-serif;
1052
-
1053
- -moz-border-radius-bottomleft: 4px;
1054
- -webkit-border-bottom-left-radius: 4px;
1055
- border-bottom-left-radius: 4px;
1056
- -moz-border-radius-bottomright: 4px;
1057
- -webkit-border-bottom-right-radius: 4px;
1058
- border-bottom-right-radius: 4px;
1059
- }
1060
- .sby_lb-dataContainer:after {
1061
- content: "";
1062
- display: table;
1063
- clear: both;
1064
- }
1065
- .sby_lb-data {
1066
- padding: 0 4px;
1067
- color: #ccc;
1068
- }
1069
- .sby_lb-data .sby_lb-details {
1070
- width: 85%;
1071
- float: left;
1072
- text-align: left;
1073
- line-height: 1.1;
1074
- }
1075
- .sby_lb-data .sby_lb-caption {
1076
- float: left;
1077
- font-size: 13px;
1078
- font-weight: normal;
1079
- line-height: 1.3;
1080
- padding-bottom: 3px;
1081
- color: #ccc;
1082
-
1083
- word-wrap: break-word;
1084
- -webkit-hyphens: auto;
1085
- -moz-hyphens: auto;
1086
- hyphens: auto;
1087
- }
1088
- .sby_lb-data .sby_lb-caption a,
1089
- .sby_lb-data .sby_lb-caption .ctf-screename-sep{
1090
- color: #ccc;
1091
- font-weight: bold;
1092
- text-decoration: none;
1093
- }
1094
- .sby_lb-data .sby_lb-caption a:hover{
1095
- color: #fff;
1096
- text-decoration: underline;
1097
- }
1098
- .sby_lb-data .sby_lb-caption .sby_lightbox_username{
1099
- float: left;
1100
- width: 100%;
1101
- color: #ccc;
1102
- padding-bottom: 0;
1103
- display: block;
1104
- margin: 0 0 5px 0;
1105
- }
1106
- .sby_lb-data .sby_lb-caption .sby_lightbox_username{
1107
- color: #ccc;
1108
- }
1109
- .sby_lb-data .sby_lb-caption .sby_lightbox_username:hover p{
1110
- color: #fff;
1111
- text-decoration: underline;
1112
- }
1113
- .sby_lightbox .sby_lightbox_username img {
1114
- float: left;
1115
- border: none;
1116
- width: 48px;
1117
- height: 48px;
1118
- margin-right: 10px;
1119
- background: #666;
1120
-
1121
- -moz-border-radius: 5px;
1122
- -webkit-border-radius: 5px;
1123
- border-radius: 5px;
1124
- }
1125
- .sby_lightbox_username p{
1126
- float: left;
1127
- margin: 0;
1128
- padding: 0;
1129
- color: #ccc;
1130
- line-height: 32px;
1131
- font-weight: bold;
1132
- font-size: 13px;
1133
- text-align: left;
1134
- }
1135
-
1136
- .sby_lb-data .ctf-caption-text{
1137
- width: 100%;
1138
- margin-left: 58px;
1139
- padding-top: 3px;
1140
- }
1141
- .sby_lb-data .sby_lb-caption .ctf-tweet-date,
1142
- .sby_lb-data .sby_lb-caption .ctf-author-screenname{
1143
- font-weight: normal;
1144
- }
1145
- .sby_lb-data .sby_lb-info{
1146
- width: 100%;
1147
- float: left;
1148
- clear: both;
1149
- }
1150
- .sby_lb-data .sby_lb-number {
1151
- display: block;
1152
- float: left;
1153
- clear: both;
1154
- padding: 5px 0 15px 0;
1155
- font-size: 12px;
1156
- color: #999999;
1157
- }
1158
- .sby_lb-data .sby_lb-close {
1159
- display: block;
1160
- float: right;
1161
- width: 30px;
1162
- height: 30px;
1163
- background: url(../img/close.png) top right no-repeat;
1164
- text-align: right;
1165
- outline: none;
1166
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
1167
- opacity: 0.7;
1168
- -webkit-transition: opacity 0.2s;
1169
- -moz-transition: opacity 0.2s;
1170
- -o-transition: opacity 0.2s;
1171
- transition: opacity 0.2s;
1172
- }
1173
- .sby_lb-data .sby_lb-close:hover {
1174
- cursor: pointer;
1175
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1176
- opacity: 1;
1177
- }
1178
-
1179
- /* Lightbox video - must go after lighbox CSS */
1180
- /* Leave a gap at the bottom of the nav for video controls */
1181
- .sby_lb-nav {
1182
- height: auto;
1183
- }
1184
- /* Remove 4px padding from lightbox container so video lines up */
1185
- .sby_lb-container{
1186
- padding: 0;
1187
- }
1188
- .sby_lb-container iframe {
1189
- position: absolute;
1190
- top: 0;
1191
- left:0;
1192
- width: 100%;
1193
- height: 100%;
1194
- z-index: 1;
1195
- }
1196
- /* Lightbox action links */
1197
- #sby_lightbox .sby_lightbox_action{
1198
- float: left;
1199
- /*clear: both;*/
1200
- position: relative;
1201
- padding: 0 0 0 10px;
1202
- margin: 5px 0 0 10px;
1203
- border-left: 1px solid #666;
1204
- font-size: 12px;
1205
- }
1206
- #sby_lightbox .sby_lightbox_action a{
1207
- display: block;
1208
- float: left;
1209
- color: #999;
1210
- text-decoration: none;
1211
- }
1212
- #sby_lightbox .sby_lightbox_action a:hover,
1213
- #sby_lightbox .sby_lightbox_action a:focus{
1214
- color: #fff;
1215
- }
1216
- #sby_lightbox .sby_lightbox_action .fa,
1217
- #sby_lightbox .sby_lightbox_action svg {
1218
- margin-right: 5px;
1219
- }
1220
- #sby_lightbox .sby_lightbox_action.sby_youtube .fa {
1221
- font-size: 13px;
1222
- }
1223
- #sby_lightbox .sby_tooltip_social a svg {
1224
- font-size: 19px;
1225
- padding: 3px 4px;
1226
- margin: auto;
1227
- }
1228
- /* Lightbox tooltip */
1229
- #sby_lightbox .sby_lightbox_tooltip{
1230
- display: none;
1231
- position: absolute;
1232
- width: 100px;
1233
- bottom: 22px;
1234
- left: 0;
1235
- padding: 5px 10px;
1236
- margin: 0;
1237
- background: rgba(255,255,255,0.9);
1238
- color: #222;
1239
- font-size: 12px;
1240
- line-height: 1.3;
1241
-
1242
- -moz-border-radius: 4px;
1243
- -webkit-border-radius: 4px;
1244
- border-radius: 4px;
1245
-
1246
- box-shadow: 0 0 10px rgba(0,0,0,0.4);
1247
- -moz-box-shadow: 0 0 10px rgba(0,0,0,0.4);
1248
- -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.4);
1249
-
1250
- -webkit-box-sizing: border-box;
1251
- -moz-box-sizing: border-box;
1252
- box-sizing: border-box;
1253
- }
1254
- #sby_lightbox .sby_lightbox_tooltip .fa-play{
1255
- position: absolute;
1256
- font-size: 8px;
1257
- bottom: -6px;
1258
- left: 36px;
1259
- color: rgba(255,255,255,0.9);
1260
- }
1261
- #sby_lightbox .sby_tooltip_social a .fa{
1262
- font-size: 16px;
1263
- margin: 0;
1264
- padding: 5px;
1265
- }
1266
- #sby_lightbox .sby_tooltip_social a#sby_facebook_icon .fa,
1267
- #sby_lightbox .sby_tooltip_social a#sby_twitter_icon .fa,
1268
- #sby_lightbox .sby_tooltip_social a#sby_pinterest_icon .fa{
1269
- padding-top: 4px;
1270
- font-size: 18px;
1271
- }
1272
- #sby_lightbox .sby_gdpr_notice {
1273
- z-index: 6;
1274
- display: block;
1275
- position: absolute;
1276
- top: 50%;
1277
- left: 50%;
1278
- margin-left: -44px;
1279
- margin-top: -44px;
1280
- padding: 20px;
1281
- }
1282
- #sby_lightbox .sby_gdpr_notice svg:not(:root).svg-inline--fa {
1283
- position: relative;
1284
- display: block !important;
1285
- height: 48px;
1286
- width: 48px;
1287
- opacity: .8;
1288
- }
1289
- #sby_lightbox .sby_gdpr_notice:hover svg:not(:root).svg-inline--fa {
1290
- opacity: 1;
1291
- }
1292
- /* Hide photos tooltip */
1293
- #sby_lightbox #sby_mod_box{
1294
- width: 280px;
1295
- padding: 5px 10px 7px 10px;
1296
- }
1297
- /* Social icons tooltip */
1298
- #sby_lightbox .sby_tooltip_social{
1299
- width: 172px;
1300
- padding: 5px 5px 4px 5px;
1301
- }
1302
- #sby_lightbox .sby_tooltip_social a{
1303
- color: #333;
1304
-
1305
- -moz-border-radius: 4px;
1306
- -webkit-border-radius: 4px;
1307
- border-radius: 4px;
1308
- }
1309
- #sby_lightbox .sby_lightbox_action #sby_facebook_icon:hover{ background: #3b5998; }
1310
- #sby_lightbox .sby_lightbox_action #sby_twitter_icon:hover{ background: #00aced; }
1311
- #sby_lightbox .sby_lightbox_action #sby_google_icon:hover{ background: #dd4b39; }
1312
- #sby_lightbox .sby_lightbox_action #sby_linkedin_icon:hover{ background: #007bb6; }
1313
- #sby_lightbox .sby_lightbox_action #sby_pinterest_icon:hover{ background: #cb2027; }
1314
- #sby_lightbox .sby_lightbox_action #sby_email_icon:hover{ background: #333; }
1315
-
1316
- .sby_lb-outerContainer, .sby_lb-dataContainer{
1317
- min-width: 450px;
1318
- }
1319
- @media all and (max-width: 450px){
1320
- .sby_lb-outerContainer, .sby_lb-dataContainer {
1321
- min-width: 0; /* Remove min-width on lightbox on mobile */
1322
- }
1323
- }
1324
- .sby_lightbox .sby_lb-image {
1325
- display: block;
1326
- height: auto;
1327
- max-width: inherit;
1328
- margin: 0 auto;
1329
- -webkit-border-radius: 0;
1330
- -moz-border-radius: 0;
1331
- -ms-border-radius: 0;
1332
- -o-border-radius: 0;
1333
- border-radius: 0;
1334
- }
1335
-
1336
- /* Mod only error msgs */
1337
- #sby_mod_error{
1338
- display: none;
1339
- border: 1px solid #ddd;
1340
- background: #eee;
1341
- color: #333;
1342
- margin: 10px 0 0;
1343
- padding: 10px 15px;
1344
- font-size: 13px;
1345
- text-align: center;
1346
- clear: both;
1347
- margin-bottom: 10px;
1348
-
1349
- -moz-border-radius: 4px;
1350
- -webkit-border-radius: 4px;
1351
- border-radius: 4px;
1352
- }
1353
- #sby_mod_error p{
1354
- padding: 5px 0 !important;
1355
- margin: 0 !important;
1356
- line-height: 1.3 !important;
1357
- }
1358
- #sby_mod_error ol,
1359
- #sby_mod_error ul{
1360
- padding: 5px 0 5px 20px !important;
1361
- margin: 0 !important;
1362
- }
1363
- #sby_mod_error li{
1364
- padding: 1px 0 !important;
1365
- margin: 0 !important;
1366
- }
1367
- #sby_mod_error span{
1368
- font-size: 12px;
1369
- }
1370
-
1371
- /* SVGs */
1372
- [id^=sb_youtube_].sb_youtube svg:not(:root).svg-inline--fa,
1373
- [id^=sb_youtube_].sb_youtube_lightbox svg:not(:root).svg-inline--fa{
1374
- box-sizing: unset;
1375
- overflow: visible;
1376
- width: 1em;
1377
- }
1378
- [id^=sb_youtube_].sb_youtube .svg-inline--fa.fa-w-16,
1379
- [id^=sb_youtube_].sb_youtube .svg-inline--fa.fa-w-16{
1380
- width: 16px;
1381
- }
1382
- [id^=sb_youtube_].sb_youtube .svg-inline--fa,
1383
- [id^=sb_youtube_].sb_youtube_lightbox .svg-inline--fa{
1384
- display: inline-block;
1385
- font-size: inherit;
1386
- height: 1em;
1387
- overflow: visible;
1388
- vertical-align: -.125em;
1389
- }
1390
-
1391
- [id^=sb_youtube_].sb_youtube.sby_player_loaded .sby_player_outer_wrap .sby_video_thumbnail,
1392
- [id^=sb_youtube_].sb_youtube.sby_player_loaded.sby_layout_list .sby_video_thumbnail{
1393
- z-index: -1 !important;
 
 
 
 
1394
  }
1
+ /**************/
2
+ /*** LAYOUT ***/
3
+ /**************/
4
+
5
+ /* Feed container */
6
+ [id^=sb_youtube_].sb_youtube {
7
+ width: 100%;
8
+ margin: 0 auto;
9
+ padding: 0;
10
+ -webkit-box-sizing: border-box;
11
+ -moz-box-sizing: border-box;
12
+ box-sizing: border-box;
13
+ }
14
+ [id^=sb_youtube_].sb_youtube * {
15
+ -webkit-box-sizing: border-box;
16
+ -moz-box-sizing: border-box;
17
+ box-sizing: border-box
18
+ }
19
+ [id^=sb_youtube_].sb_youtube:after{
20
+ content: "";
21
+ display: table;
22
+ clear: both;
23
+ }
24
+ [id^=sb_youtube_].sb_youtube iframe,
25
+ #sby_lightbox iframe{
26
+ pointer-events: all !important;
27
+ }
28
+
29
+ /*********************/
30
+ /*** STYLE OPTIONS ***/
31
+ /*********************/
32
+ [id^=sb_youtube_].sb_youtube.sby_fixed_height{
33
+ overflow: hidden;
34
+ overflow-y: auto;
35
+ -webkit-box-sizing: border-box;
36
+ -moz-box-sizing: border-box;
37
+ box-sizing: border-box;
38
+ }
39
+ [id^=sb_youtube_].sb_youtube .sby_items_wrap{
40
+ width: 100%;
41
+ float: left;
42
+ line-height: 0;
43
+
44
+ -webkit-box-sizing: border-box;
45
+ -moz-box-sizing: border-box;
46
+ box-sizing: border-box;
47
+ }
48
+
49
+ /* Items */
50
+ [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item,
51
+ [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_video_thumbnail_wrap,
52
+ [id^=sb_youtube_].sb_youtube .sby_player_wrap{
53
+ display: -moz-inline-stack;
54
+ display: inline-block;
55
+ vertical-align: top;
56
+ zoom: 1;
57
+ *display: inline;
58
+
59
+ max-height: 1000px;
60
+ padding: inherit !important;
61
+ text-decoration: none;
62
+ opacity: 1;
63
+ overflow: hidden;
64
+
65
+ -webkit-box-sizing: border-box;
66
+ -moz-box-sizing: border-box;
67
+ box-sizing: border-box;
68
+
69
+ -webkit-transition: all 0.5s ease;
70
+ -moz-transition: all 0.5s ease;
71
+ -o-transition: all 0.5s ease;
72
+ -ms-transition: all 0.5s ease;
73
+ transition: all 0.5s ease;
74
+ }
75
+ [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_no_margin {
76
+ margin: 0 !important;
77
+ }
78
+ [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item {
79
+ float: left;
80
+ }
81
+ /* Transition items in */
82
+ [id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_transition{
83
+ opacity: 0;
84
+ max-height: 0;
85
+ }
86
+
87
+ /* Cols */
88
+ [id^=sb_youtube_].sb_youtube.sby_col_0 .sby_items_wrap .sby_item{ width: 100%; }
89
+ [id^=sb_youtube_].sb_youtube.sby_col_1 .sby_items_wrap .sby_item{ width: 100%; }
90
+ [id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{ width: 50%; }
91
+ [id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{ width: 33.33%; }
92
+ [id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{ width: 25%; }
93
+ [id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{ width: 20%; }
94
+ [id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{ width: 16.66%; }
95
+ [id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{ width: 14.28%; }
96
+ [id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{ width: 12.5%; }
97
+ [id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{ width: 11.11%; }
98
+ [id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{ width: 10%; }
99
+
100
+ /* Disable mobile layout */
101
+ /*
102
+ [id^=sb_youtube_].sb_youtube.sby_col_1.sby_disable_mobile .sby_items_wrap .sby_item{ width: 100%; }
103
+ [id^=sb_youtube_].sb_youtube.sby_col_2.sby_disable_mobile .sby_items_wrap .sby_item{ width: 50%; }
104
+ [id^=sb_youtube_].sb_youtube.sby_col_3.sby_disable_mobile .sby_items_wrap .sby_item{ width: 33.33%; }
105
+ [id^=sb_youtube_].sb_youtube.sby_col_4.sby_disable_mobile .sby_items_wrap .sby_item{ width: 25%; }
106
+ [id^=sb_youtube_].sb_youtube.sby_col_5.sby_disable_mobile .sby_items_wrap .sby_item{ width: 20%; }
107
+ [id^=sb_youtube_].sb_youtube.sby_col_6.sby_disable_mobile .sby_items_wrap .sby_item{ width: 16.66%; }
108
+ [id^=sb_youtube_].sb_youtube.sby_col_7.sby_disable_mobile .sby_items_wrap .sby_item{ width: 14.28%; }
109
+ [id^=sb_youtube_].sb_youtube.sby_col_8.sby_disable_mobile .sby_items_wrap .sby_item{ width: 12.5%; }
110
+ [id^=sb_youtube_].sb_youtube.sby_col_9.sby_disable_mobile .sby_items_wrap .sby_item{ width: 11.11%; }
111
+ [id^=sb_youtube_].sb_youtube.sby_col_10.sby_disable_mobile .sby_items_wrap .sby_item{ width: 10%; }
112
+ */
113
+ /* Photos */
114
+ .sby-screenreader{text-indent: -9999px !important;display: block !important;width: 0 !important;height: 0 !important;line-height: 0 !important;}
115
+ [id^=sb_youtube_].sb_youtube .sby_video_thumbnail_wrap,
116
+ [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap {
117
+ width: 100%;
118
+ position: relative;
119
+ float: left;
120
+ }
121
+ [id^=sb_youtube_].sb_youtube .sby_video_thumbnail{
122
+ display: block;
123
+ position: relative;
124
+ text-decoration: none;
125
+ line-height: 0;
126
+ z-index: 5;
127
+ }
128
+ [id^=sb_youtube_].sb_youtube .sby_video_thumbnail img{
129
+ width: 100%;
130
+ height: auto;
131
+ border-radius: 0;
132
+ }
133
+ [id^=sb_youtube_].sb_youtube .sby_link{
134
+ display: none;
135
+ position: absolute;
136
+ z-index: 1;
137
+ top: 0;
138
+ right: 0;
139
+ bottom: 0;
140
+ left: 0;
141
+
142
+ width: 100%;
143
+ padding: 0;
144
+ background: #333;
145
+ background: rgba(0,0,0,0.6);
146
+ text-align: center;
147
+ color: #fff;
148
+ font-size: 12px;
149
+ line-height: 1.1;
150
+ overflow: hidden;
151
+ }
152
+ [id^=sb_youtube_].sb_youtube .sby_link.sby_default p,
153
+ [id^=sb_youtube_].sb_youtube .sby_link.sby_default span,
154
+ [id^=sb_youtube_].sb_youtube .sby_link.sby_default a{
155
+ text-shadow: 0px 0px 10px #000;
156
+ }
157
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_username a,
158
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link,
159
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_hover_bottom,
160
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn,
161
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link,
162
+ [id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play{
163
+ filter: alpha(opacity=90);
164
+ opacity: 0.9;
165
+ }
166
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_username a:hover,
167
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link:hover,
168
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn:hover,
169
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link:hover,
170
+ [id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play:hover{
171
+ filter: alpha(opacity=100);
172
+ opacity: 1;
173
+ }
174
+ [id^=sb_youtube_].sb_youtube .sby_link_area{
175
+ position: absolute;
176
+ top: 0;
177
+ right: 0;
178
+ bottom: 0;
179
+ left: 0;
180
+ z-index: 1;
181
+ }
182
+
183
+ [id^=sb_youtube_].sb_youtube .sby_link a{
184
+ padding: 0;
185
+ text-decoration: none;
186
+ color: #ddd;
187
+ color: rgba(255,255,255,0.7);
188
+ line-height: 1.1;
189
+ background: none;
190
+
191
+ display: -moz-inline-stack;
192
+ display: inline-block;
193
+ vertical-align: top;
194
+ zoom: 1;
195
+ *display: inline;
196
+ }
197
+ [id^=sb_youtube_].sb_youtube .sby_link a:hover,
198
+ [id^=sb_youtube_].sb_youtube .sby_link a:active{
199
+ color: #fff;
200
+ }
201
+
202
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link{
203
+ display: block;
204
+ /*display: none;*/
205
+ position: absolute;
206
+ z-index: 2;
207
+ top: 50%;
208
+ left: 50%;
209
+
210
+ margin-top: -24px;
211
+ margin-left: -21px;
212
+ padding: 0;
213
+ font-size: 49px;
214
+ font-style: normal !important;
215
+ }
216
+ [id^=sb_youtube_].sb_youtube .sby_type_video .sby_lightbox_link,
217
+ [id^=sb_youtube_].sb_youtube .sby_carousel_vid_first .sby_lightbox_link{
218
+ display: none;
219
+ }
220
+
221
+ [id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link{
222
+ /*float: right;*/
223
+ font-size: 30px;
224
+ position: absolute;
225
+ z-index: 100;
226
+ bottom: 0;
227
+ right: 2px;
228
+ padding: 8px;
229
+ }
230
+ [id^=sb_youtube_].sb_youtube .sby_link a:hover,
231
+ [id^=sb_youtube_].sb_youtube .sby_link a:focus{
232
+ text-decoration: underline;
233
+ }
234
+
235
+ /* Player */
236
+ [id^=sb_youtube_].sb_youtube .sby_player_wrap {
237
+ z-index: 1;
238
+ width: 100% !important;
239
+ height: 100% !important;
240
+ position: absolute;
241
+ top: 0;
242
+ left: 0;
243
+ }
244
+ [id^=sb_youtube_].sb_youtube .sby_player_wrap iframe {
245
+ width: 100% !important;
246
+ height: 100% !important;
247
+ }
248
+
249
+ /* Use CSS for lightbox fade instead of JS */
250
+ [id^=sb_youtube_].sb_youtube .sby_thumbnail_hover {
251
+ opacity: 0;
252
+ display: block;
253
+ position: absolute;
254
+ top: 0;
255
+ right: 0;
256
+ bottom: 0;
257
+ left: 0;
258
+ z-index: 10;
259
+ color: #fff;
260
+ background: #333;
261
+ background: rgba(0,0,0,.6);
262
+ transition: opacity .6s ease-in-out;
263
+ -moz-transition: opacity .6s ease-in-out;
264
+ -webkit-transition: opacity .6s ease-in-out;
265
+ }
266
+ [id^=sb_youtube_].sb_youtube.sby_layout_list .sby_thumbnail_hover {
267
+ display: none;
268
+ }
269
+ .sby_video_title {
270
+ display: inline-block;
271
+ height: 100%;
272
+ padding: 10px;
273
+ overflow: hidden;
274
+ font-size: 13px;
275
+ line-height: 1.2;
276
+ }
277
+ [id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_thumbnail_hover {
278
+ opacity: 1;
279
+ display: block;
280
+ transition: opacity .2s ease-in-out;
281
+ -moz-transition: opacity .2s ease-in-out;
282
+ -webkit-transition: opacity .2s ease-in-out;
283
+ }
284
+ [id^=sb_youtube_].sb_youtube .sby_current .sby_thumbnail_hover {
285
+ opacity: 1;
286
+ }
287
+ [id^=sb_youtube_].sb_youtube.sby_layout_list .sby_video_thumbnail:hover .sby_thumbnail_hover {
288
+ opacity: 0;
289
+ display: none;
290
+ transition: none;
291
+ -moz-transition: none;
292
+ -webkit-transition: none;
293
+ }
294
+
295
+ a.sby_video_thumbnail:after {
296
+ box-shadow: inset 0 0 1px 0 rgba(0,0,0,0.7);
297
+ bottom: 0;
298
+ content: '';
299
+ left: 0;
300
+ position: absolute;
301
+ z-index: 1;
302
+ right: 0;
303
+ top: 0;
304
+ width: 100%;
305
+ }
306
+
307
+ /* Play Button */
308
+ [id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_play_btn {
309
+ opacity: .5;
310
+ }
311
+ [id^=sb_youtube_].sb_youtube .sby_play_btn {
312
+ position: absolute;
313
+ z-index: 1;
314
+ left: 50%;
315
+ bottom: 50%;
316
+ top: 50%;
317
+ right: 50%;
318
+ margin-top: -25px;
319
+ margin-left: -28px;
320
+ color: #fff;
321
+ width: 57px;
322
+ height: 50px;
323
+ opacity: 1;
324
+ transition: opacity .2s ease-in-out;
325
+ -moz-transition: opacity .2s ease-in-out;
326
+ -webkit-transition: opacity .2s ease-in-out;
327
+ }
328
+ [id^=sb_youtube_].sb_youtube .sby_play_btn_bg {
329
+ display: block;
330
+ position: absolute;
331
+ z-index: -1;
332
+ top: 17px;
333
+ left: 22px;
334
+ width: 0;
335
+ height: 0;
336
+ border: 0 solid transparent;
337
+ border-bottom-width: 9px;
338
+ border-top-width: 9px;
339
+ border-left: 16px solid #fff;
340
+ }
341
+ [id^=sb_youtube_].sb_youtube .sby_play_btn svg:not(:root).svg-inline--fa{
342
+ width: 57px;
343
+ height: auto;
344
+ opacity: 0.75;
345
+ }
346
+
347
+ [id^=sb_youtube_].sb_youtube .sby_play_btn svg,
348
+ [id^=sb_youtube_].sb_youtube .sby_play_btn i{
349
+ color: #000;
350
+ }
351
+ /* Medium */
352
+ [id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn {
353
+ margin-top: -20px;
354
+ margin-left: -22px;
355
+ width: 45px;
356
+ height: 40px;
357
+ }
358
+ [id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn_bg {
359
+ top: 13px;
360
+ left: 18px;
361
+ border-bottom-width: 7px;
362
+ border-top-width: 7px;
363
+ border-left: 12px solid #fff;
364
+ }
365
+ [id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn svg:not(:root).svg-inline--fa{
366
+ width: 45px;
367
+ }
368
+
369
+ /* Small */
370
+ [id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn{
371
+ margin-top: -16px;
372
+ margin-left: -18px;
373
+ width: 36px;
374
+ height: 32px;
375
+ }
376
+ [id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn_bg {
377
+ top: 10px;
378
+ left: 14px;
379
+ border-bottom-width: 6px;
380
+ border-top-width: 6px;
381
+ border-left: 10px solid #fff;
382
+ }
383
+ [id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn svg:not(:root).svg-inline--fa{
384
+ width: 36px;
385
+ }
386
+
387
+ [id^=sb_youtube_].sby_layout_gallery .sby_player_outer_wrap .sby_play_btn {
388
+ z-index: 10;
389
+ }
390
+
391
+ /* Loader */
392
+ [id^=sb_youtube_].sb_youtube .sby_loader{
393
+ width: 20px;
394
+ height: 20px;
395
+
396
+ position: relative;
397
+ top: 50%;
398
+ left: 50%;
399
+ margin: -10px 0 0 -10px;
400
+ background-color: #000;
401
+ background-color: rgba(0,0,0,0.5);
402
+
403
+ border-radius: 100%;
404
+ -webkit-animation: sby-sk-scaleout 1.0s infinite ease-in-out;
405
+ animation: sby-sk-scaleout 1.0s infinite ease-in-out;
406
+ }
407
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header br,
408
+ [id^=sb_youtube_].sb_youtube .sby_items_wrap br,
409
+ [id^=sb_youtube_].sb_youtube .sby_footer br{
410
+ display: none;
411
+ }
412
+ .sby_footer p {
413
+ display: inline;
414
+ padding: 0;
415
+ margin: 0;
416
+ }
417
+ /* Loader in button */
418
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_loader,
419
+ [id^=sb_youtube_].sb_youtube .sby_item .sby_loader,
420
+ [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_loader{
421
+ position: absolute;
422
+ margin-top: -11px;
423
+ background-color: #fff;
424
+ }
425
+ [id^=sb_youtube_].sb_youtube .sby_item.sby_player_loading,
426
+ [id^=sb_youtube_].sb_youtube .sby_player_outer_wrap.sby_player_loading {
427
+ opacity: .8;
428
+ }
429
+ @-webkit-keyframes sby-sk-scaleout {
430
+ 0% { -webkit-transform: scale(0) }
431
+ 100% {
432
+ -webkit-transform: scale(1.0);
433
+ opacity: 0;
434
+ }
435
+ }
436
+ @keyframes sby-sk-scaleout {
437
+ 0% {
438
+ -webkit-transform: scale(0);
439
+ -ms-transform: scale(0);
440
+ transform: scale(0);
441
+ } 100% {
442
+ -webkit-transform: scale(1.0);
443
+ -ms-transform: scale(1.0);
444
+ transform: scale(1.0);
445
+ opacity: 0;
446
+ }
447
+ }
448
+
449
+ [id^=sb_youtube_].sb_youtube .fa-spin,
450
+ #sby_lightbox .fa-spin{
451
+ -webkit-animation: fa-spin 2s infinite linear;
452
+ animation: fa-spin 2s infinite linear
453
+ }
454
+
455
+ [id^=sb_youtube_].sb_youtube .fa-pulse,
456
+ #sby_lightbox .fa-pulse{
457
+ -webkit-animation: fa-spin 1s infinite steps(8);
458
+ animation: fa-spin 1s infinite steps(8)
459
+ }
460
+
461
+ @-webkit-keyframes fa-spin {
462
+ 0% {
463
+ -webkit-transform: rotate(0deg);
464
+ transform: rotate(0deg)
465
+ }
466
+ 100% {
467
+ -webkit-transform: rotate(359deg);
468
+ transform: rotate(359deg)
469
+ }
470
+ }
471
+
472
+ @keyframes fa-spin {
473
+ 0% {
474
+ -webkit-transform: rotate(0deg);
475
+ transform: rotate(0deg)
476
+ }
477
+ 100% {
478
+ -webkit-transform: rotate(359deg);
479
+ transform: rotate(359deg)
480
+ }
481
+ }
482
+
483
+ /* HEADER */
484
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header{
485
+ float: left;
486
+ clear: both;
487
+ margin: 0 0 15px 0;
488
+ padding: 0;
489
+ line-height: 1.2;
490
+ width: 100%;
491
+ }
492
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header a{
493
+ float: left;
494
+ display: block;
495
+ /*width: 100%;*/
496
+ min-width: 100%\9;
497
+ text-decoration: none;
498
+ transition: color 0.5s ease;
499
+ }
500
+ /** Medium Header */
501
+ /* Only use medium & large headers on devices above 480px */
502
+ @media all and (min-width: 480px){
503
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img {
504
+ width: 80px;
505
+ height: 80px;
506
+ border-radius: 40px;
507
+ }
508
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img img {
509
+ width: 80px;
510
+ height: 80px;
511
+ border-radius: 40px;
512
+ }
513
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3 {
514
+ font-size: 20px;
515
+ }
516
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info,
517
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio{
518
+ font-size: 14px;
519
+ }
520
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3,
521
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info,
522
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio{
523
+ margin-left: 95px !important;
524
+ line-height: 1.4
525
+ }
526
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{
527
+ margin-right: -85px !important;
528
+ }
529
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info{
530
+ margin-top: 4px !important;
531
+ }
532
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text.sby_no_bio h3{
533
+ padding-top: 20px !important;
534
+ }
535
+ /** Large Header */
536
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img {
537
+ width: 120px;
538
+ height: 120px;
539
+ border-radius: 60px;
540
+ }
541
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img img {
542
+ width: 120px;
543
+ height: 120px;
544
+ border-radius: 60px;
545
+ }
546
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3 {
547
+ font-size: 28px;
548
+ }
549
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info,
550
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio{
551
+ font-size: 16px;
552
+ }
553
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3,
554
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info,
555
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio{
556
+ margin-left: 140px !important;
557
+ line-height: 1.5;
558
+ }
559
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{
560
+ margin-right: -120px !important;
561
+ }
562
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info{
563
+ margin-top: 12px !important;
564
+ }
565
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text.sby_no_bio h3{
566
+ padding-top: 32px !important;
567
+ }
568
+ }
569
+
570
+ /* Header profile pic */
571
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img{
572
+ float: left;
573
+ position: relative;
574
+ width: 50px;
575
+ margin: 0 0 0 -100% !important;
576
+ overflow: hidden;
577
+
578
+ -moz-border-radius: 40px;
579
+ -webkit-border-radius: 40px;
580
+ border-radius: 40px;
581
+ }
582
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img img{
583
+ float: left;
584
+ margin: 0 !important;
585
+ padding: 0 !important;
586
+ border: none !important;
587
+
588
+ -moz-border-radius: 40px;
589
+ -webkit-border-radius: 40px;
590
+ border-radius: 40px;
591
+ }
592
+ /* Profile pic hover */
593
+ /* Profile pic hover */
594
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{
595
+ opacity: 0;
596
+ position: absolute;
597
+ width: 100%;
598
+ top: 0;
599
+ bottom: 0;
600
+ left: 0;
601
+ text-align: center;
602
+ color: #fff;
603
+ background: rgba(0,0,0,0.75);
604
+ }
605
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img {
606
+ height: 50px;
607
+ }
608
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img_hover{
609
+ opacity: 1;
610
+ }
611
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover .sby_new_logo{
612
+ position: absolute;
613
+ top: 50%;
614
+ left: 50%;
615
+ margin-top: -12px;
616
+ margin-left: -12px;
617
+ width: 24px;
618
+ height: 24px;
619
+ font-size: 24px;
620
+ }
621
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover i {
622
+ overflow: hidden;
623
+ background: url('../img/small-logo.png') no-repeat 0 0;
624
+ }
625
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{
626
+ z-index: 2;
627
+ transition: opacity 0.4s ease-in-out;
628
+ }
629
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_fade_in{
630
+ opacity: 1;
631
+ transition: opacity 0.2s ease-in-out;
632
+ }
633
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{
634
+ position: absolute;
635
+ width: 100%;
636
+ top: 0;
637
+ bottom: 0;
638
+ left: 0;
639
+ text-align: center;
640
+ color: #fff;
641
+ background: rgba(0,0,0,0.75);
642
+
643
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
644
+ filter: alpha(opacity=0);
645
+ -moz-opacity: 0;
646
+ -khtml-opacity: 0;
647
+ opacity: 0;
648
+ border-radius: 40px;
649
+ transition: opacity 0.2s;
650
+ }
651
+ /* Fade the Youtube icon in when hovering on the header */
652
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header a:hover .sby_header_img_hover,
653
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header a:focus .sby_header_img_hover{
654
+ opacity: 1;
655
+ }
656
+ /* Header text */
657
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text{
658
+ float: left;
659
+ width: 100%;
660
+ padding-top: 5px;
661
+ }
662
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header a{
663
+ text-decoration: none;
664
+ }
665
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text .sby_bio,
666
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text h3{
667
+ float: left;
668
+ clear: both;
669
+ width: auto;
670
+ margin: 0 0 0 60px !important;
671
+ padding: 0 !important;
672
+ }
673
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header h3{
674
+ font-size: 16px;
675
+ line-height: 1.3;
676
+ }
677
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header p{
678
+ font-size: 13px;
679
+ line-height: 1.3;
680
+ margin: 0;
681
+ padding: 0;
682
+ }
683
+ [id^=sb_youtube_].sb_youtube p:empty { display: none; }
684
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text img.emoji{
685
+ margin-right: 3px !important;
686
+ }
687
+
688
+ /* No bio */
689
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio h3{
690
+ padding-top: 9px !important;
691
+ }
692
+ [id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio .sby_bio_info{
693
+ clear: both;
694
+ }
695
+
696
+ /* Buttons */
697
+ [id^=sb_youtube_].sb_youtube .sby_footer{
698
+ float: left;
699
+ clear: both;
700
+ width: 100%;
701
+ text-align: center;
702
+ }
703
+ [id^=sb_youtube_].sb_youtube .sby_footer .fa-spinner{
704
+ display: none;
705
+ position: absolute;
706
+ top: 50%;
707
+ left: 50%;
708
+ margin: -8px 0 0 -7px;
709
+ font-size: 15px;
710
+ }
711
+ [id^=sb_youtube_].sb_youtube .sby_footer{
712
+ opacity: 1;
713
+ transition: all 0.5s ease-in;
714
+ }
715
+ [id^=sb_youtube_].sb_youtube .sby_load_btn .sby_btn_text, [id^=sb_youtube_].sb_youtube .sby_load_btn .sby_loader{
716
+ opacity: 1;
717
+ transition: all 0.1s ease-in;
718
+ }
719
+ [id^=sb_youtube_].sb_youtube .sby_hidden{
720
+ opacity: 0 !important;
721
+ }
722
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn,
723
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a{
724
+ display: -moz-inline-stack;
725
+ display: inline-block;
726
+ vertical-align: top;
727
+ zoom: 1;
728
+ *display: inline;
729
+
730
+ padding: 7px 14px;
731
+ margin: 5px auto 0 auto;
732
+ background: #333;
733
+ color: #eee;
734
+ border: none;
735
+ color: #fff;
736
+ text-decoration: none;
737
+ font-size: 13px;
738
+ line-height: 1.5;
739
+
740
+ -moz-border-radius: 4px;
741
+ -webkit-border-radius: 4px;
742
+ border-radius: 4px;
743
+
744
+ -webkit-box-sizing: border-box;
745
+ -moz-box-sizing: border-box;
746
+ box-sizing: border-box;
747
+ }
748
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn {
749
+ position: relative;
750
+ }
751
+ /* Follow button */
752
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn{
753
+ display: -moz-inline-stack;
754
+ display: inline-block;
755
+ vertical-align: top;
756
+ zoom: 1;
757
+ *display: inline;
758
+ text-align: center;
759
+ }
760
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_top{
761
+ display: block;
762
+ margin-bottom: 5px;
763
+ }
764
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a{
765
+ background: #408bd1;
766
+ color: #fff;
767
+ }
768
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a,
769
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a,
770
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{
771
+ transition: all 0.1s ease-in;
772
+ }
773
+ /* Hover state for default colors */
774
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:hover{
775
+ outline: none;
776
+ box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.25);
777
+ }
778
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a:hover,
779
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a:focus{
780
+ outline: none;
781
+ box-shadow: inset 0 0 10px 20px #359dff;
782
+ }
783
+ /* If a custom color is applied then just use opacity for the hover effect */
784
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:hover,
785
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:focus,
786
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn.sby_custom:hover{
787
+ box-shadow: inset 0 0 20px 20px rgba(255,255,255,0.15);
788
+ }
789
+ /* Active state */
790
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn a:active,
791
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:active{
792
+ box-shadow: inset 0 0 10px 20px rgba(0,0,0,0.3);
793
+ }
794
+
795
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn .fa,
796
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn svg{
797
+ margin-bottom: -1px;
798
+ margin-right: 7px;
799
+ font-size: 15px;
800
+ }
801
+ [id^=sb_youtube_].sb_youtube .sby_follow_btn svg{
802
+ vertical-align: -.125em;
803
+ }
804
+ [id^=sb_youtube_].sb_youtube .sby_footer .sby_follow_btn{
805
+ margin-left: 5px;
806
+ }
807
+
808
+ /* Media queries */
809
+ @media all and (max-width: 640px){
810
+ /* Make 3-6 cols into 2 col */
811
+ [id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,
812
+ [id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,
813
+ [id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,
814
+ [id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item{
815
+ width: 50%;
816
+ }
817
+ /* Make 7-10 cols into 4 col */
818
+ [id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item,
819
+ [id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item,
820
+ [id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item,
821
+ [id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item,
822
+ [id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,
823
+ [id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,
824
+ [id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item,
825
+ [id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item{
826
+ width: 25%;
827
+ }
828
+ [id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{ width: 50%; }
829
+ [id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{ width: 33.33%; }
830
+ [id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{ width: 25%; }
831
+ [id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{ width: 20%; }
832
+ [id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{ width: 16.66%; }
833
+ [id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{ width: 14.28%; }
834
+ [id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{ width: 12.5%; }
835
+ [id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{ width: 11.11%; }
836
+ [id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{ width: 10%; }
837
+ /* On mobile make the min-width 100% */
838
+ [id^=sb_youtube_].sb_youtube.sby_width_resp{
839
+ width: 100% !important;
840
+ }
841
+ }
842
+ @media all and (max-width: 480px){
843
+ /* Make all cols into 1 col */
844
+ [id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,
845
+ [id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,
846
+ [id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,
847
+ [id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item,
848
+ [id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,
849
+ [id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,
850
+ [id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item,
851
+ [id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item,
852
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_1 .sby_items_wrap .sby_item{
853
+ width: 100%;
854
+ }
855
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_2 .sby_items_wrap .sby_item{ width: 50%; }
856
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_3 .sby_items_wrap .sby_item{ width: 33.33%; }
857
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_4 .sby_items_wrap .sby_item{ width: 25%; }
858
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_5 .sby_items_wrap .sby_item{ width: 20%; }
859
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_6 .sby_items_wrap .sby_item{ width: 16.66%; }
860
+ [id^=sb_youtube_].sb_youtube.sby_mob_col_7 .sby_items_wrap .sby_item{ width: 14.28%; }
861
+ }
862
+
863
+ /* --- Lightbox --- */
864
+
865
+ .sby_lightboxOverlay {
866
+ position: absolute;
867
+ top: 0;
868
+ left: 0;
869
+ z-index: 99999;
870
+ background-color: black;
871
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
872
+ opacity: 0.9;
873
+ display: none;
874
+ }
875
+ .sby_lightbox {
876
+ position: absolute;
877
+ left: 0;
878
+ width: 100%;
879
+ z-index: 100000;
880
+ line-height: 0;
881
+ font-weight: normal;
882
+ }
883
+ .sby_lightbox .sby_lb-image {
884
+ display: block;
885
+ height: auto;
886
+ max-width: inherit;
887
+ -webkit-border-radius: 3px;
888
+ -moz-border-radius: 3px;
889
+ -ms-border-radius: 3px;
890
+ -o-border-radius: 3px;
891
+ border-radius: 3px;
892
+ }
893
+ .sby_lightbox a:hover,
894
+ .sby_lightbox a:focus,
895
+ .sby_lightbox a:active{
896
+ outline: none;
897
+ }
898
+ .sby_lightbox a img {
899
+ border: none;
900
+ }
901
+ .sby_lb-outerContainer {
902
+ position: relative;
903
+ background-color: #000;
904
+ *zoom: 1;
905
+ width: 250px;
906
+ height: 250px;
907
+ margin: 0 auto 5px auto;
908
+ -webkit-border-radius: 3px;
909
+ -moz-border-radius: 3px;
910
+ -ms-border-radius: 3px;
911
+ -o-border-radius: 3px;
912
+ border-radius: 3px;
913
+ }
914
+ .sby_lb-outerContainer:after {
915
+ content: "";
916
+ display: table;
917
+ clear: both;
918
+ }
919
+ .sby_lb-container {
920
+ position: relative;
921
+ padding: 4px;
922
+ top: 0;
923
+ left: 0;
924
+ width: 100%;
925
+ height: 100%;
926
+ bottom: 0;
927
+ right: 0;
928
+
929
+ -webkit-border-radius: 3px;
930
+ -moz-border-radius: 3px;
931
+ -ms-border-radius: 3px;
932
+ -o-border-radius: 3px;
933
+ border-radius: 3px;
934
+ }
935
+ .sby_lb-loader {
936
+ position: absolute;
937
+ top: 43%;
938
+ left: 0;
939
+ height: 25%;
940
+ width: 100%;
941
+ text-align: center;
942
+ line-height: 0;
943
+ }
944
+ .sby_lb-cancel {
945
+ display: block;
946
+ width: 32px;
947
+ height: 32px;
948
+ margin: 0 auto;
949
+ background-color: #666;
950
+ background-color: rgba(255,255,255,0.5);
951
+
952
+ border-radius: 100%;
953
+ -webkit-animation: ctf-sk-scaleout 1.0s infinite ease-in-out;
954
+ animation: ctf-sk-scaleout 1.0s infinite ease-in-out;
955
+ }
956
+
957
+
958
+ .sby_lb-nav {
959
+ /*position: absolute;*/
960
+ top: 0;
961
+ left: 0;
962
+ /*height: 100%;*/
963
+ width: 100%;
964
+ z-index: 10;
965
+ /*pointer-events: none;*/
966
+ }
967
+ .sby_lb-container > .nav {
968
+ left: 0;
969
+ }
970
+ .sby_lb-nav a {
971
+ position: absolute;
972
+ z-index: 100;
973
+ top: 0;
974
+ height: 90%;
975
+ outline: none;
976
+ background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
977
+ }
978
+
979
+
980
+ /* Arrows */
981
+ .sby_lb-prev, .sby_lb-next {
982
+ height: 100%;
983
+ cursor: pointer;
984
+ display: block;
985
+ }
986
+ .sby_lb-nav a.sby_lb-prev {
987
+ /*width: 30%;*/
988
+ width: 50px;
989
+ left: -70px;
990
+ padding-left: 10px;
991
+ padding-right: 10px;
992
+ float: left;
993
+
994
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0.5);
995
+ opacity: 0.5;
996
+ -webkit-transition: opacity 0.2s;
997
+ -moz-transition: opacity 0.2;
998
+ -o-transition: opacity 0.2s;
999
+ transition: opacity 0.2s;
1000
+
1001
+ }
1002
+
1003
+ .sby_lb-nav a.sby_lb-prev:hover {
1004
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1005
+ opacity: 1;
1006
+ }
1007
+
1008
+ .sby_lb-nav a.sby_lb-next {
1009
+ /*width: 30%;*/
1010
+ width: 50px;
1011
+ right: -70px;
1012
+ padding-left: 10px;
1013
+ padding-right: 10px;
1014
+ float: right;
1015
+
1016
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0.5);
1017
+ opacity: 0.5;
1018
+ -webkit-transition: opacity 0.2s;
1019
+ -moz-transition: opacity 0.2s;
1020
+ -o-transition: opacity 0.2s;
1021
+ transition: opacity 0.2s;
1022
+
1023
+ }
1024
+
1025
+ .sby_lb-nav a.sby_lb-next:hover {
1026
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1027
+ opacity: 1;
1028
+ }
1029
+
1030
+ .sby_lb-nav span{
1031
+ display: block;
1032
+ top: 55%;
1033
+ position: absolute;
1034
+ left: 20px;
1035
+ width: 34px;
1036
+ height: 45px;
1037
+ margin: -25px 0 0 0;
1038
+ background: url(../img/sby-sprite.png) no-repeat;
1039
+ }
1040
+ .sby_lb-nav a.sby_lb-prev span{
1041
+ background-position: -53px 0;
1042
+ }
1043
+ .sby_lb-nav a.sby_lb-next span{
1044
+ left: auto;
1045
+ right: 20px;
1046
+ background-position: -18px 0;
1047
+ }
1048
+
1049
+
1050
+ .sby_lb-dataContainer {
1051
+ margin: 0 auto;
1052
+ padding-top: 5px;
1053
+ *zoom: 1;
1054
+ width: 100%;
1055
+ font-family: "Open Sans", Helvetica, Arial, sans-serif;
1056
+
1057
+ -moz-border-radius-bottomleft: 4px;
1058
+ -webkit-border-bottom-left-radius: 4px;
1059
+ border-bottom-left-radius: 4px;
1060
+ -moz-border-radius-bottomright: 4px;
1061
+ -webkit-border-bottom-right-radius: 4px;
1062
+ border-bottom-right-radius: 4px;
1063
+ }
1064
+ .sby_lb-dataContainer:after {
1065
+ content: "";
1066
+ display: table;
1067
+ clear: both;
1068
+ }
1069
+ .sby_lb-data {
1070
+ padding: 0 4px;
1071
+ color: #ccc;
1072
+ }
1073
+ .sby_lb-data .sby_lb-details {
1074
+ width: 85%;
1075
+ float: left;
1076
+ text-align: left;
1077
+ line-height: 1.1;
1078
+ }
1079
+ .sby_lb-data .sby_lb-caption {
1080
+ float: left;
1081
+ font-size: 13px;
1082
+ font-weight: normal;
1083
+ line-height: 1.3;
1084
+ padding-bottom: 3px;
1085
+ color: #ccc;
1086
+
1087
+ word-wrap: break-word;
1088
+ -webkit-hyphens: auto;
1089
+ -moz-hyphens: auto;
1090
+ hyphens: auto;
1091
+ }
1092
+ .sby_lb-data .sby_lb-caption a,
1093
+ .sby_lb-data .sby_lb-caption .ctf-screename-sep{
1094
+ color: #ccc;
1095
+ font-weight: bold;
1096
+ text-decoration: none;
1097
+ }
1098
+ .sby_lb-data .sby_lb-caption a:hover{
1099
+ color: #fff;
1100
+ text-decoration: underline;
1101
+ }
1102
+ .sby_lb-data .sby_lb-caption .sby_lightbox_username{
1103
+ float: left;
1104
+ width: 100%;
1105
+ color: #ccc;
1106
+ padding-bottom: 0;
1107
+ display: block;
1108
+ margin: 0 0 5px 0;
1109
+ }
1110
+ .sby_lb-data .sby_lb-caption .sby_lightbox_username{
1111
+ color: #ccc;
1112
+ }
1113
+ .sby_lb-data .sby_lb-caption .sby_lightbox_username:hover p{
1114
+ color: #fff;
1115
+ text-decoration: underline;
1116
+ }
1117
+ .sby_lightbox .sby_lightbox_username img {
1118
+ float: left;
1119
+ border: none;
1120
+ width: 48px;
1121
+ height: 48px;
1122
+ margin-right: 10px;
1123
+ background: #666;
1124
+
1125
+ -moz-border-radius: 5px;
1126
+ -webkit-border-radius: 5px;
1127
+ border-radius: 5px;
1128
+ }
1129
+ .sby_lightbox_username p{
1130
+ float: left;
1131
+ margin: 0;
1132
+ padding: 0;
1133
+ color: #ccc;
1134
+ line-height: 32px;
1135
+ font-weight: bold;
1136
+ font-size: 13px;
1137
+ text-align: left;
1138
+ }
1139
+
1140
+ .sby_lb-data .ctf-caption-text{
1141
+ width: 100%;
1142
+ margin-left: 58px;
1143
+ padding-top: 3px;
1144
+ }
1145
+ .sby_lb-data .sby_lb-caption .ctf-tweet-date,
1146
+ .sby_lb-data .sby_lb-caption .ctf-author-screenname{
1147
+ font-weight: normal;
1148
+ }
1149
+ .sby_lb-data .sby_lb-info{
1150
+ width: 100%;
1151
+ float: left;
1152
+ clear: both;
1153
+ }
1154
+ .sby_lb-data .sby_lb-number {
1155
+ display: block;
1156
+ float: left;
1157
+ clear: both;
1158
+ padding: 5px 0 15px 0;
1159
+ font-size: 12px;
1160
+ color: #999999;
1161
+ }
1162
+ .sby_lb-data .sby_lb-close {
1163
+ display: block;
1164
+ float: right;
1165
+ width: 30px;
1166
+ height: 30px;
1167
+ background: url(../img/close.png) top right no-repeat;
1168
+ text-align: right;
1169
+ outline: none;
1170
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
1171
+ opacity: 0.7;
1172
+ -webkit-transition: opacity 0.2s;
1173
+ -moz-transition: opacity 0.2s;
1174
+ -o-transition: opacity 0.2s;
1175
+ transition: opacity 0.2s;
1176
+ }
1177
+ .sby_lb-data .sby_lb-close:hover {
1178
+ cursor: pointer;
1179
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1180
+ opacity: 1;
1181
+ }
1182
+
1183
+ /* Lightbox video - must go after lighbox CSS */
1184
+ /* Leave a gap at the bottom of the nav for video controls */
1185
+ .sby_lb-nav {
1186
+ height: auto;
1187
+ }
1188
+ /* Remove 4px padding from lightbox container so video lines up */
1189
+ .sby_lb-container{
1190
+ padding: 0;
1191
+ }
1192
+ .sby_lb-container iframe {
1193
+ position: absolute;
1194
+ top: 0;
1195
+ left:0;
1196
+ width: 100%;
1197
+ height: 100%;
1198
+ z-index: 1;
1199
+ }
1200
+ /* Lightbox action links */
1201
+ #sby_lightbox .sby_lightbox_action{
1202
+ float: left;
1203
+ /*clear: both;*/
1204
+ position: relative;
1205
+ padding: 0 0 0 10px;
1206
+ margin: 5px 0 0 10px;
1207
+ border-left: 1px solid #666;
1208
+ font-size: 12px;
1209
+ }
1210
+ #sby_lightbox .sby_lightbox_action a{
1211
+ display: block;
1212
+ float: left;
1213
+ color: #999;
1214
+ text-decoration: none;
1215
+ }
1216
+ #sby_lightbox .sby_lightbox_action a:hover,
1217
+ #sby_lightbox .sby_lightbox_action a:focus{
1218
+ color: #fff;
1219
+ }
1220
+ #sby_lightbox .sby_lightbox_action .fa,
1221
+ #sby_lightbox .sby_lightbox_action svg {
1222
+ margin-right: 5px;
1223
+ }
1224
+ #sby_lightbox .sby_lightbox_action.sby_youtube .fa {
1225
+ font-size: 13px;
1226
+ }
1227
+ #sby_lightbox .sby_tooltip_social a svg {
1228
+ font-size: 19px;
1229
+ padding: 3px 4px;
1230
+ margin: auto;
1231
+ }
1232
+ /* Lightbox tooltip */
1233
+ #sby_lightbox .sby_lightbox_tooltip{
1234
+ display: none;
1235
+ position: absolute;
1236
+ width: 100px;
1237
+ bottom: 22px;
1238
+ left: 0;
1239
+ padding: 5px 10px;
1240
+ margin: 0;
1241
+ background: rgba(255,255,255,0.9);
1242
+ color: #222;
1243
+ font-size: 12px;
1244
+ line-height: 1.3;
1245
+
1246
+ -moz-border-radius: 4px;
1247
+ -webkit-border-radius: 4px;
1248
+ border-radius: 4px;
1249
+
1250
+ box-shadow: 0 0 10px rgba(0,0,0,0.4);
1251
+ -moz-box-shadow: 0 0 10px rgba(0,0,0,0.4);
1252
+ -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.4);
1253
+
1254
+ -webkit-box-sizing: border-box;
1255
+ -moz-box-sizing: border-box;
1256
+ box-sizing: border-box;
1257
+ }
1258
+ #sby_lightbox .sby_lightbox_tooltip .fa-play{
1259
+ position: absolute;
1260
+ font-size: 8px;
1261
+ bottom: -6px;
1262
+ left: 36px;
1263
+ color: rgba(255,255,255,0.9);
1264
+ }
1265
+ #sby_lightbox .sby_tooltip_social a .fa{
1266
+ font-size: 16px;
1267
+ margin: 0;
1268
+ padding: 5px;
1269
+ }
1270
+ #sby_lightbox .sby_tooltip_social a#sby_facebook_icon .fa,
1271
+ #sby_lightbox .sby_tooltip_social a#sby_twitter_icon .fa,
1272
+ #sby_lightbox .sby_tooltip_social a#sby_pinterest_icon .fa{
1273
+ padding-top: 4px;
1274
+ font-size: 18px;
1275
+ }
1276
+ #sby_lightbox .sby_gdpr_notice {
1277
+ z-index: 6;
1278
+ display: block;
1279
+ position: absolute;
1280
+ top: 50%;
1281
+ left: 50%;
1282
+ margin-left: -44px;
1283
+ margin-top: -44px;
1284
+ padding: 20px;
1285
+ }
1286
+ #sby_lightbox .sby_gdpr_notice svg:not(:root).svg-inline--fa {
1287
+ position: relative;
1288
+ display: block !important;
1289
+ height: 48px;
1290
+ width: 48px;
1291
+ opacity: .8;
1292
+ }
1293
+ #sby_lightbox .sby_gdpr_notice:hover svg:not(:root).svg-inline--fa {
1294
+ opacity: 1;
1295
+ }
1296
+ /* Hide photos tooltip */
1297
+ #sby_lightbox #sby_mod_box{
1298
+ width: 280px;
1299
+ padding: 5px 10px 7px 10px;
1300
+ }
1301
+ /* Social icons tooltip */
1302
+ #sby_lightbox .sby_tooltip_social{
1303
+ width: 172px;
1304
+ padding: 5px 5px 4px 5px;
1305
+ }
1306
+ #sby_lightbox .sby_tooltip_social a{
1307
+ color: #333;
1308
+
1309
+ -moz-border-radius: 4px;
1310
+ -webkit-border-radius: 4px;
1311
+ border-radius: 4px;
1312
+ }
1313
+ #sby_lightbox .sby_lightbox_action #sby_facebook_icon:hover{ background: #3b5998; }
1314
+ #sby_lightbox .sby_lightbox_action #sby_twitter_icon:hover{ background: #00aced; }
1315
+ #sby_lightbox .sby_lightbox_action #sby_google_icon:hover{ background: #dd4b39; }
1316
+ #sby_lightbox .sby_lightbox_action #sby_linkedin_icon:hover{ background: #007bb6; }
1317
+ #sby_lightbox .sby_lightbox_action #sby_pinterest_icon:hover{ background: #cb2027; }
1318
+ #sby_lightbox .sby_lightbox_action #sby_email_icon:hover{ background: #333; }
1319
+
1320
+ .sby_lb-outerContainer, .sby_lb-dataContainer{
1321
+ min-width: 450px;
1322
+ }
1323
+ @media all and (max-width: 450px){
1324
+ .sby_lb-outerContainer, .sby_lb-dataContainer {
1325
+ min-width: 0; /* Remove min-width on lightbox on mobile */
1326
+ }
1327
+ }
1328
+ .sby_lightbox .sby_lb-image {
1329
+ display: block;
1330
+ height: auto;
1331
+ max-width: inherit;
1332
+ margin: 0 auto;
1333
+ -webkit-border-radius: 0;
1334
+ -moz-border-radius: 0;
1335
+ -ms-border-radius: 0;
1336
+ -o-border-radius: 0;
1337
+ border-radius: 0;
1338
+ }
1339
+
1340
+ /* Mod only error msgs */
1341
+ #sby_mod_error{
1342
+ display: none;
1343
+ border: 1px solid #ddd;
1344
+ background: #eee;
1345
+ color: #333;
1346
+ margin: 10px 0 0;
1347
+ padding: 10px 15px;
1348
+ font-size: 13px;
1349
+ text-align: center;
1350
+ clear: both;
1351
+ margin-bottom: 10px;
1352
+
1353
+ -moz-border-radius: 4px;
1354
+ -webkit-border-radius: 4px;
1355
+ border-radius: 4px;
1356
+ }
1357
+ #sby_mod_error p{
1358
+ padding: 5px 0 !important;
1359
+ margin: 0 !important;
1360
+ line-height: 1.3 !important;
1361
+ }
1362
+ #sby_mod_error ol,
1363
+ #sby_mod_error ul{
1364
+ padding: 5px 0 5px 20px !important;
1365
+ margin: 0 !important;
1366
+ }
1367
+ #sby_mod_error li{
1368
+ padding: 1px 0 !important;
1369
+ margin: 0 !important;
1370
+ }
1371
+ #sby_mod_error span{
1372
+ font-size: 12px;
1373
+ }
1374
+
1375
+ /* SVGs */
1376
+ [id^=sb_youtube_].sb_youtube svg:not(:root).svg-inline--fa,
1377
+ [id^=sb_youtube_].sb_youtube_lightbox svg:not(:root).svg-inline--fa{
1378
+ box-sizing: unset;
1379
+ overflow: visible;
1380
+ width: 1em;
1381
+ }
1382
+ [id^=sb_youtube_].sb_youtube .svg-inline--fa.fa-w-16,
1383
+ [id^=sb_youtube_].sb_youtube .svg-inline--fa.fa-w-16{
1384
+ width: 16px;
1385
+ }
1386
+ [id^=sb_youtube_].sb_youtube .svg-inline--fa,
1387
+ [id^=sb_youtube_].sb_youtube_lightbox .svg-inline--fa{
1388
+ display: inline-block;
1389
+ font-size: inherit;
1390
+ height: 1em;
1391
+ overflow: visible;
1392
+ vertical-align: -.125em;
1393
+ }
1394
+
1395
+ [id^=sb_youtube_].sb_youtube.sby_player_loaded .sby_player_outer_wrap .sby_video_thumbnail,
1396
+ [id^=sb_youtube_].sb_youtube.sby_player_loaded.sby_layout_list .sby_video_thumbnail{
1397
+ z-index: -1 !important;
1398
  }
css/sb-youtube.min.css CHANGED
@@ -1 +1 @@
1
- [id^=sb_youtube_].sb_youtube{width:100%;margin:0 auto;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube:after{content:"";display:table;clear:both}#sby_lightbox iframe,[id^=sb_youtube_].sb_youtube iframe{pointer-events:all!important}[id^=sb_youtube_].sb_youtube.sby_fixed_height{overflow:hidden;overflow-y:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube .sby_items_wrap{width:100%;float:left;line-height:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_video_thumbnail_wrap,[id^=sb_youtube_].sb_youtube .sby_player_wrap{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;max-height:1000px;padding:inherit!important;text-decoration:none;opacity:1;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;-ms-transition:all .5s ease;transition:all .5s ease}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_no_margin{margin:0!important}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item{float:left}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_transition{opacity:0;max-height:0}[id^=sb_youtube_].sb_youtube.sby_col_0 .sby_items_wrap .sby_item{width:100%}[id^=sb_youtube_].sb_youtube.sby_col_1 .sby_items_wrap .sby_item{width:100%}[id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{width:33.33%}[id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{width:20%}[id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{width:16.66%}[id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{width:14.28%}[id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{width:12.5%}[id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{width:11.11%}[id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{width:10%}.sby-screenreader{text-indent:-9999px!important;display:block!important;width:0!important;height:0!important;line-height:0!important}[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap,[id^=sb_youtube_].sb_youtube .sby_video_thumbnail_wrap{width:100%;position:relative;float:left}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail{display:block;position:relative;text-decoration:none;line-height:0;z-index:5}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail img{width:100%;height:auto;border-radius:0}[id^=sb_youtube_].sb_youtube .sby_link{display:none;position:absolute;z-index:1;top:0;right:0;bottom:0;left:0;width:100%;padding:0;background:#333;background:rgba(0,0,0,.6);text-align:center;color:#fff;font-size:12px;line-height:1.1;overflow:hidden}[id^=sb_youtube_].sb_youtube .sby_link.sby_default a,[id^=sb_youtube_].sb_youtube .sby_link.sby_default p,[id^=sb_youtube_].sb_youtube .sby_link.sby_default span{text-shadow:0 0 10px #000}[id^=sb_youtube_].sb_youtube .sby_link .sby_hover_bottom,[id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link,[id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn,[id^=sb_youtube_].sb_youtube .sby_link .sby_username a,[id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link,[id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play{opacity:.9}[id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link:hover,[id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn:hover,[id^=sb_youtube_].sb_youtube .sby_link .sby_username a:hover,[id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link:hover,[id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play:hover{opacity:1}[id^=sb_youtube_].sb_youtube .sby_link_area{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}[id^=sb_youtube_].sb_youtube .sby_link a{padding:0;text-decoration:none;color:#ddd;color:rgba(255,255,255,.7);line-height:1.1;background:0 0;display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1}[id^=sb_youtube_].sb_youtube .sby_link a:active,[id^=sb_youtube_].sb_youtube .sby_link a:hover{color:#fff}[id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link{display:block;position:absolute;z-index:2;top:50%;left:50%;margin-top:-24px;margin-left:-21px;padding:0;font-size:49px;font-style:normal!important}[id^=sb_youtube_].sb_youtube .sby_carousel_vid_first .sby_lightbox_link,[id^=sb_youtube_].sb_youtube .sby_type_video .sby_lightbox_link{display:none}[id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link{font-size:30px;position:absolute;z-index:100;bottom:0;right:2px;padding:8px}[id^=sb_youtube_].sb_youtube .sby_link a:focus,[id^=sb_youtube_].sb_youtube .sby_link a:hover{text-decoration:underline}[id^=sb_youtube_].sb_youtube .sby_player_wrap{z-index:1;width:100%!important;height:100%!important;position:absolute;top:0;left:0}[id^=sb_youtube_].sb_youtube .sby_player_wrap iframe{width:100%!important;height:100%!important}[id^=sb_youtube_].sb_youtube .sby_thumbnail_hover{opacity:0;display:block;position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;color:#fff;background:#333;background:rgba(0,0,0,.6);transition:opacity .6s ease-in-out;-moz-transition:opacity .6s ease-in-out;-webkit-transition:opacity .6s ease-in-out}[id^=sb_youtube_].sb_youtube.sby_layout_list .sby_thumbnail_hover{display:none}.sby_video_title{display:inline-block;height:100%;padding:10px;overflow:hidden;font-size:13px;line-height:1.2}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_thumbnail_hover{opacity:1;display:block;transition:opacity .2s ease-in-out;-moz-transition:opacity .2s ease-in-out;-webkit-transition:opacity .2s ease-in-out}[id^=sb_youtube_].sb_youtube .sby_current .sby_thumbnail_hover{opacity:1}[id^=sb_youtube_].sb_youtube.sby_layout_list .sby_video_thumbnail:hover .sby_thumbnail_hover{opacity:0;display:none;transition:none;-moz-transition:none;-webkit-transition:none}a.sby_video_thumbnail:after{box-shadow:inset 0 0 1px 0 rgba(0,0,0,.7);bottom:0;content:'';left:0;position:absolute;z-index:1;right:0;top:0;width:100%}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_play_btn{opacity:.5}[id^=sb_youtube_].sb_youtube .sby_play_btn{position:absolute;z-index:1;left:50%;bottom:50%;top:50%;right:50%;margin-top:-25px;margin-left:-28px;color:#fff;width:57px;height:50px;opacity:1;transition:opacity .2s ease-in-out;-moz-transition:opacity .2s ease-in-out;-webkit-transition:opacity .2s ease-in-out}[id^=sb_youtube_].sb_youtube .sby_play_btn_bg{display:block;position:absolute;z-index:-1;top:17px;left:22px;width:0;height:0;border:0 solid transparent;border-bottom-width:9px;border-top-width:9px;border-left:16px solid #fff}[id^=sb_youtube_].sb_youtube .sby_play_btn svg:not(:root).svg-inline--fa{width:57px;height:auto;opacity:.75}[id^=sb_youtube_].sb_youtube .sby_play_btn i,[id^=sb_youtube_].sb_youtube .sby_play_btn svg{color:#000}[id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn{margin-top:-20px;margin-left:-22px;width:45px;height:40px}[id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn_bg{top:13px;left:18px;border-bottom-width:7px;border-top-width:7px;border-left:12px solid #fff}[id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn svg:not(:root).svg-inline--fa{width:45px}[id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn{margin-top:-16px;margin-left:-18px;width:36px;height:32px}[id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn_bg{top:10px;left:14px;border-bottom-width:6px;border-top-width:6px;border-left:10px solid #fff}[id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn svg:not(:root).svg-inline--fa{width:36px}[id^=sb_youtube_].sb_youtube .sby_loader{width:20px;height:20px;position:relative;top:50%;left:50%;margin:-10px 0 0 -10px;background-color:#000;background-color:rgba(0,0,0,.5);border-radius:100%;-webkit-animation:sby-sk-scaleout 1s infinite ease-in-out;animation:sby-sk-scaleout 1s infinite ease-in-out}[id^=sb_youtube_].sb_youtube .sb_youtube_header br,[id^=sb_youtube_].sb_youtube .sby_footer br,[id^=sb_youtube_].sb_youtube .sby_items_wrap br{display:none}.sby_footer p{display:inline;padding:0;margin:0}[id^=sb_youtube_].sb_youtube .sby_footer .sby_loader,[id^=sb_youtube_].sb_youtube .sby_item .sby_loader,[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_loader{position:absolute;margin-top:-11px;background-color:#fff}[id^=sb_youtube_].sb_youtube .sby_item.sby_player_loading,[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap.sby_player_loading{opacity:.8}@-webkit-keyframes sby-sk-scaleout{0%{-webkit-transform:scale(0)}100%{-webkit-transform:scale(1);opacity:0}}@keyframes sby-sk-scaleout{0%{-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);opacity:0}}#sby_lightbox .fa-spin,[id^=sb_youtube_].sb_youtube .fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}#sby_lightbox .fa-pulse,[id^=sb_youtube_].sb_youtube .fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}[id^=sb_youtube_].sb_youtube .sb_youtube_header{float:left;clear:both;margin:0 0 15px 0;padding:0;line-height:1.2;width:100%}[id^=sb_youtube_].sb_youtube .sb_youtube_header a{float:left;display:block;text-decoration:none;transition:color .5s ease}@media all and (min-width:480px){[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img{width:80px;height:80px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img img{width:80px;height:80px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{font-size:20px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info{font-size:14px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{margin-left:95px!important;line-height:1.4}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{margin-right:-85px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info{margin-top:4px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text.sby_no_bio h3{padding-top:20px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img{width:120px;height:120px;border-radius:60px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img img{width:120px;height:120px;border-radius:60px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{font-size:28px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info{font-size:16px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{margin-left:140px!important;line-height:1.5}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{margin-right:-120px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info{margin-top:12px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text.sby_no_bio h3{padding-top:32px!important}}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img{float:left;position:relative;width:50px;margin:0 0 0 -100%!important;overflow:hidden;-moz-border-radius:40px;-webkit-border-radius:40px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img img{float:left;margin:0!important;padding:0!important;border:none!important;-moz-border-radius:40px;-webkit-border-radius:40px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{opacity:0;position:absolute;width:100%;top:0;bottom:0;left:0;text-align:center;color:#fff;background:rgba(0,0,0,.75)}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img{height:50px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img_hover{opacity:1}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover .sby_new_logo{position:absolute;top:50%;left:50%;margin-top:-12px;margin-left:-12px;width:24px;height:24px;font-size:24px}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover i{overflow:hidden;background:url(../img/small-logo.png) no-repeat 0 0}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{z-index:2;transition:opacity .4s ease-in-out}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_fade_in{opacity:1;transition:opacity .2s ease-in-out}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{position:absolute;width:100%;top:0;bottom:0;left:0;text-align:center;color:#fff;background:rgba(0,0,0,.75);-moz-opacity:0;-khtml-opacity:0;opacity:0;border-radius:40px;transition:opacity .2s}[id^=sb_youtube_].sb_youtube .sb_youtube_header a:focus .sby_header_img_hover,[id^=sb_youtube_].sb_youtube .sb_youtube_header a:hover .sby_header_img_hover{opacity:1}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text{float:left;width:100%;padding-top:5px}[id^=sb_youtube_].sb_youtube .sb_youtube_header a{text-decoration:none}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text h3{float:left;clear:both;width:auto;margin:0 0 0 60px!important;padding:0!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header h3{font-size:16px;line-height:1.3}[id^=sb_youtube_].sb_youtube .sb_youtube_header p{font-size:13px;line-height:1.3;margin:0;padding:0}[id^=sb_youtube_].sb_youtube p:empty{display:none}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text img.emoji{margin-right:3px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio h3{padding-top:9px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio .sby_bio_info{clear:both}[id^=sb_youtube_].sb_youtube .sby_footer{float:left;clear:both;width:100%;text-align:center}[id^=sb_youtube_].sb_youtube .sby_footer .fa-spinner{display:none;position:absolute;top:50%;left:50%;margin:-8px 0 0 -7px;font-size:15px}[id^=sb_youtube_].sb_youtube .sby_footer{opacity:1;transition:all .5s ease-in}[id^=sb_youtube_].sb_youtube .sby_load_btn .sby_btn_text,[id^=sb_youtube_].sb_youtube .sby_load_btn .sby_loader{opacity:1;transition:all .1s ease-in}[id^=sb_youtube_].sb_youtube .sby_hidden{opacity:0!important}[id^=sb_youtube_].sb_youtube .sby_follow_btn a,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;padding:7px 14px;margin:5px auto 0 auto;background:#333;color:#eee;border:none;color:#fff;text-decoration:none;font-size:13px;line-height:1.5;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{position:relative}[id^=sb_youtube_].sb_youtube .sby_follow_btn{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;text-align:center}[id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_top{display:block;margin-bottom:5px}[id^=sb_youtube_].sb_youtube .sby_follow_btn a{background:#408bd1;color:#fff}[id^=sb_youtube_].sb_youtube .sby_follow_btn a,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{transition:all .1s ease-in}[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:hover{outline:0;box-shadow:inset 0 0 20px 20px rgba(255,255,255,.25)}[id^=sb_youtube_].sb_youtube .sby_follow_btn a:focus,[id^=sb_youtube_].sb_youtube .sby_follow_btn a:hover{outline:0;box-shadow:inset 0 0 10px 20px #359dff}[id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:focus,[id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:hover,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn.sby_custom:hover{box-shadow:inset 0 0 20px 20px rgba(255,255,255,.15)}[id^=sb_youtube_].sb_youtube .sby_follow_btn a:active,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:active{box-shadow:inset 0 0 10px 20px rgba(0,0,0,.3)}[id^=sb_youtube_].sb_youtube .sby_follow_btn .fa,[id^=sb_youtube_].sb_youtube .sby_follow_btn svg{margin-bottom:-1px;margin-right:7px;font-size:15px}[id^=sb_youtube_].sb_youtube .sby_follow_btn svg{vertical-align:-.125em}[id^=sb_youtube_].sb_youtube .sby_footer .sby_follow_btn{margin-left:5px}@media all and (max-width:640px){[id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{width:33.33%}[id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{width:20%}[id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{width:16.66%}[id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{width:14.28%}[id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{width:12.5%}[id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{width:11.11%}[id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{width:10%}[id^=sb_youtube_].sb_youtube.sby_width_resp{width:100%!important}}@media all and (max-width:480px){[id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_mob_col_1 .sby_items_wrap .sby_item{width:100%}[id^=sb_youtube_].sb_youtube.sby_mob_col_2 .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_mob_col_3 .sby_items_wrap .sby_item{width:33.33%}[id^=sb_youtube_].sb_youtube.sby_mob_col_4 .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_mob_col_5 .sby_items_wrap .sby_item{width:20%}[id^=sb_youtube_].sb_youtube.sby_mob_col_6 .sby_items_wrap .sby_item{width:16.66%}[id^=sb_youtube_].sb_youtube.sby_mob_col_7 .sby_items_wrap .sby_item{width:14.28%}}.sby_lightboxOverlay{position:absolute;top:0;left:0;z-index:99999;background-color:#000;opacity:.9;display:none}.sby_lightbox{position:absolute;left:0;width:100%;z-index:100000;line-height:0;font-weight:400}.sby_lightbox .sby_lb-image{display:block;height:auto;max-width:inherit;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.sby_lightbox a:active,.sby_lightbox a:focus,.sby_lightbox a:hover{outline:0}.sby_lightbox a img{border:none}.sby_lb-outerContainer{position:relative;background-color:#000;width:250px;height:250px;margin:0 auto 5px auto;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.sby_lb-outerContainer:after{content:"";display:table;clear:both}.sby_lb-container{position:relative;padding:4px;top:0;left:0;width:100%;height:100%;bottom:0;right:0;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.sby_lb-loader{position:absolute;top:43%;left:0;height:25%;width:100%;text-align:center;line-height:0}.sby_lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background-color:#666;background-color:rgba(255,255,255,.5);border-radius:100%;-webkit-animation:ctf-sk-scaleout 1s infinite ease-in-out;animation:ctf-sk-scaleout 1s infinite ease-in-out}.sby_lb-nav{top:0;left:0;width:100%;z-index:10}.sby_lb-container>.nav{left:0}.sby_lb-nav a{position:absolute;z-index:100;top:0;height:90%;outline:0;background-image:url(data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}.sby_lb-next,.sby_lb-prev{height:100%;cursor:pointer;display:block}.sby_lb-nav a.sby_lb-prev{width:50px;left:-70px;padding-left:10px;padding-right:10px;float:left;opacity:.5;-webkit-transition:opacity .2s;-moz-transition:opacity .2;-o-transition:opacity .2s;transition:opacity .2s}.sby_lb-nav a.sby_lb-prev:hover{opacity:1}.sby_lb-nav a.sby_lb-next{width:50px;right:-70px;padding-left:10px;padding-right:10px;float:right;opacity:.5;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.sby_lb-nav a.sby_lb-next:hover{opacity:1}.sby_lb-nav span{display:block;top:55%;position:absolute;left:20px;width:34px;height:45px;margin:-25px 0 0 0;background:url(../img/sby-sprite.png) no-repeat}.sby_lb-nav a.sby_lb-prev span{background-position:-53px 0}.sby_lb-nav a.sby_lb-next span{left:auto;right:20px;background-position:-18px 0}.sby_lb-dataContainer{margin:0 auto;padding-top:5px;width:100%;font-family:"Open Sans",Helvetica,Arial,sans-serif;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.sby_lb-dataContainer:after{content:"";display:table;clear:both}.sby_lb-data{padding:0 4px;color:#ccc}.sby_lb-data .sby_lb-details{width:85%;float:left;text-align:left;line-height:1.1}.sby_lb-data .sby_lb-caption{float:left;font-size:13px;font-weight:400;line-height:1.3;padding-bottom:3px;color:#ccc;word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto}.sby_lb-data .sby_lb-caption .ctf-screename-sep,.sby_lb-data .sby_lb-caption a{color:#ccc;font-weight:700;text-decoration:none}.sby_lb-data .sby_lb-caption a:hover{color:#fff;text-decoration:underline}.sby_lb-data .sby_lb-caption .sby_lightbox_username{float:left;width:100%;color:#ccc;padding-bottom:0;display:block;margin:0 0 5px 0}.sby_lb-data .sby_lb-caption .sby_lightbox_username{color:#ccc}.sby_lb-data .sby_lb-caption .sby_lightbox_username:hover p{color:#fff;text-decoration:underline}.sby_lightbox .sby_lightbox_username img{float:left;border:none;width:48px;height:48px;margin-right:10px;background:#666;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sby_lightbox_username p{float:left;margin:0;padding:0;color:#ccc;line-height:32px;font-weight:700;font-size:13px;text-align:left}.sby_lb-data .ctf-caption-text{width:100%;margin-left:58px;padding-top:3px}.sby_lb-data .sby_lb-caption .ctf-author-screenname,.sby_lb-data .sby_lb-caption .ctf-tweet-date{font-weight:400}.sby_lb-data .sby_lb-info{width:100%;float:left;clear:both}.sby_lb-data .sby_lb-number{display:block;float:left;clear:both;padding:5px 0 15px 0;font-size:12px;color:#999}.sby_lb-data .sby_lb-close{display:block;float:right;width:30px;height:30px;background:url(../img/close.png) top right no-repeat;text-align:right;outline:0;opacity:.7;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.sby_lb-data .sby_lb-close:hover{cursor:pointer;opacity:1}.sby_lb-nav{height:auto}.sby_lb-container{padding:0}.sby_lb-container iframe{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}#sby_lightbox .sby_lightbox_action{float:left;position:relative;padding:0 0 0 10px;margin:5px 0 0 10px;border-left:1px solid #666;font-size:12px}#sby_lightbox .sby_lightbox_action a{display:block;float:left;color:#999;text-decoration:none}#sby_lightbox .sby_lightbox_action a:focus,#sby_lightbox .sby_lightbox_action a:hover{color:#fff}#sby_lightbox .sby_lightbox_action .fa,#sby_lightbox .sby_lightbox_action svg{margin-right:5px}#sby_lightbox .sby_lightbox_action.sby_youtube .fa{font-size:13px}#sby_lightbox .sby_tooltip_social a svg{font-size:19px;padding:3px 4px;margin:auto}#sby_lightbox .sby_lightbox_tooltip{display:none;position:absolute;width:100px;bottom:22px;left:0;padding:5px 10px;margin:0;background:rgba(255,255,255,.9);color:#222;font-size:12px;line-height:1.3;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;box-shadow:0 0 10px rgba(0,0,0,.4);-moz-box-shadow:0 0 10px rgba(0,0,0,.4);-webkit-box-shadow:0 0 10px rgba(0,0,0,.4);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#sby_lightbox .sby_lightbox_tooltip .fa-play{position:absolute;font-size:8px;bottom:-6px;left:36px;color:rgba(255,255,255,.9)}#sby_lightbox .sby_tooltip_social a .fa{font-size:16px;margin:0;padding:5px}#sby_lightbox .sby_tooltip_social a#sby_facebook_icon .fa,#sby_lightbox .sby_tooltip_social a#sby_pinterest_icon .fa,#sby_lightbox .sby_tooltip_social a#sby_twitter_icon .fa{padding-top:4px;font-size:18px}#sby_lightbox .sby_gdpr_notice{z-index:6;display:block;position:absolute;top:50%;left:50%;margin-left:-44px;margin-top:-44px;padding:20px}#sby_lightbox .sby_gdpr_notice svg:not(:root).svg-inline--fa{position:relative;display:block!important;height:48px;width:48px;opacity:.8}#sby_lightbox .sby_gdpr_notice:hover svg:not(:root).svg-inline--fa{opacity:1}#sby_lightbox #sby_mod_box{width:280px;padding:5px 10px 7px 10px}#sby_lightbox .sby_tooltip_social{width:172px;padding:5px 5px 4px 5px}#sby_lightbox .sby_tooltip_social a{color:#333;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}#sby_lightbox .sby_lightbox_action #sby_facebook_icon:hover{background:#3b5998}#sby_lightbox .sby_lightbox_action #sby_twitter_icon:hover{background:#00aced}#sby_lightbox .sby_lightbox_action #sby_google_icon:hover{background:#dd4b39}#sby_lightbox .sby_lightbox_action #sby_linkedin_icon:hover{background:#007bb6}#sby_lightbox .sby_lightbox_action #sby_pinterest_icon:hover{background:#cb2027}#sby_lightbox .sby_lightbox_action #sby_email_icon:hover{background:#333}.sby_lb-dataContainer,.sby_lb-outerContainer{min-width:450px}@media all and (max-width:450px){.sby_lb-dataContainer,.sby_lb-outerContainer{min-width:0}}.sby_lightbox .sby_lb-image{display:block;height:auto;max-width:inherit;margin:0 auto;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}#sby_mod_error{display:none;border:1px solid #ddd;background:#eee;color:#333;margin:10px 0 0;padding:10px 15px;font-size:13px;text-align:center;clear:both;margin-bottom:10px;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}#sby_mod_error p{padding:5px 0!important;margin:0!important;line-height:1.3!important}#sby_mod_error ol,#sby_mod_error ul{padding:5px 0 5px 20px!important;margin:0!important}#sby_mod_error li{padding:1px 0!important;margin:0!important}#sby_mod_error span{font-size:12px}[id^=sb_youtube_].sb_youtube svg:not(:root).svg-inline--fa,[id^=sb_youtube_].sb_youtube_lightbox svg:not(:root).svg-inline--fa{box-sizing:unset;overflow:visible;width:1em}[id^=sb_youtube_].sb_youtube .svg-inline--fa.fa-w-16{width:16px}[id^=sb_youtube_].sb_youtube .svg-inline--fa,[id^=sb_youtube_].sb_youtube_lightbox .svg-inline--fa{display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em}[id^=sb_youtube_].sb_youtube.sby_player_loaded .sby_player_outer_wrap .sby_video_thumbnail,[id^=sb_youtube_].sb_youtube.sby_player_loaded.sby_layout_list .sby_video_thumbnail{z-index:-1!important}
1
+ [id^=sb_youtube_].sb_youtube{width:100%;margin:0 auto;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube:after{content:"";display:table;clear:both}#sby_lightbox iframe,[id^=sb_youtube_].sb_youtube iframe{pointer-events:all!important}[id^=sb_youtube_].sb_youtube.sby_fixed_height{overflow:hidden;overflow-y:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube .sby_items_wrap{width:100%;float:left;line-height:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_video_thumbnail_wrap,[id^=sb_youtube_].sb_youtube .sby_player_wrap{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;max-height:1000px;padding:inherit!important;text-decoration:none;opacity:1;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;-ms-transition:all .5s ease;transition:all .5s ease}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_no_margin{margin:0!important}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item{float:left}[id^=sb_youtube_].sb_youtube .sby_items_wrap .sby_item.sby_transition{opacity:0;max-height:0}[id^=sb_youtube_].sb_youtube.sby_col_0 .sby_items_wrap .sby_item{width:100%}[id^=sb_youtube_].sb_youtube.sby_col_1 .sby_items_wrap .sby_item{width:100%}[id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{width:33.33%}[id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{width:20%}[id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{width:16.66%}[id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{width:14.28%}[id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{width:12.5%}[id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{width:11.11%}[id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{width:10%}.sby-screenreader{text-indent:-9999px!important;display:block!important;width:0!important;height:0!important;line-height:0!important}[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap,[id^=sb_youtube_].sb_youtube .sby_video_thumbnail_wrap{width:100%;position:relative;float:left}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail{display:block;position:relative;text-decoration:none;line-height:0;z-index:5}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail img{width:100%;height:auto;border-radius:0}[id^=sb_youtube_].sb_youtube .sby_link{display:none;position:absolute;z-index:1;top:0;right:0;bottom:0;left:0;width:100%;padding:0;background:#333;background:rgba(0,0,0,.6);text-align:center;color:#fff;font-size:12px;line-height:1.1;overflow:hidden}[id^=sb_youtube_].sb_youtube .sby_link.sby_default a,[id^=sb_youtube_].sb_youtube .sby_link.sby_default p,[id^=sb_youtube_].sb_youtube .sby_link.sby_default span{text-shadow:0 0 10px #000}[id^=sb_youtube_].sb_youtube .sby_link .sby_hover_bottom,[id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link,[id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn,[id^=sb_youtube_].sb_youtube .sby_link .sby_username a,[id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link,[id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play{opacity:.9}[id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link:hover,[id^=sb_youtube_].sb_youtube .sby_link .sby_playbtn:hover,[id^=sb_youtube_].sb_youtube .sby_link .sby_username a:hover,[id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link:hover,[id^=sb_youtube_].sb_youtube .sby_link .svg-inline--fa.fa-play:hover{opacity:1}[id^=sb_youtube_].sb_youtube .sby_link_area{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}[id^=sb_youtube_].sb_youtube .sby_link a{padding:0;text-decoration:none;color:#ddd;color:rgba(255,255,255,.7);line-height:1.1;background:0 0;display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1}[id^=sb_youtube_].sb_youtube .sby_link a:active,[id^=sb_youtube_].sb_youtube .sby_link a:hover{color:#fff}[id^=sb_youtube_].sb_youtube .sby_link .sby_lightbox_link{display:block;position:absolute;z-index:2;top:50%;left:50%;margin-top:-24px;margin-left:-21px;padding:0;font-size:49px;font-style:normal!important}[id^=sb_youtube_].sb_youtube .sby_carousel_vid_first .sby_lightbox_link,[id^=sb_youtube_].sb_youtube .sby_type_video .sby_lightbox_link{display:none}[id^=sb_youtube_].sb_youtube .sby_link .sby_youtube_link{font-size:30px;position:absolute;z-index:100;bottom:0;right:2px;padding:8px}[id^=sb_youtube_].sb_youtube .sby_link a:focus,[id^=sb_youtube_].sb_youtube .sby_link a:hover{text-decoration:underline}[id^=sb_youtube_].sb_youtube .sby_player_wrap{z-index:1;width:100%!important;height:100%!important;position:absolute;top:0;left:0}[id^=sb_youtube_].sb_youtube .sby_player_wrap iframe{width:100%!important;height:100%!important}[id^=sb_youtube_].sb_youtube .sby_thumbnail_hover{opacity:0;display:block;position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;color:#fff;background:#333;background:rgba(0,0,0,.6);transition:opacity .6s ease-in-out;-moz-transition:opacity .6s ease-in-out;-webkit-transition:opacity .6s ease-in-out}[id^=sb_youtube_].sb_youtube.sby_layout_list .sby_thumbnail_hover{display:none}.sby_video_title{display:inline-block;height:100%;padding:10px;overflow:hidden;font-size:13px;line-height:1.2}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_thumbnail_hover{opacity:1;display:block;transition:opacity .2s ease-in-out;-moz-transition:opacity .2s ease-in-out;-webkit-transition:opacity .2s ease-in-out}[id^=sb_youtube_].sb_youtube .sby_current .sby_thumbnail_hover{opacity:1}[id^=sb_youtube_].sb_youtube.sby_layout_list .sby_video_thumbnail:hover .sby_thumbnail_hover{opacity:0;display:none;transition:none;-moz-transition:none;-webkit-transition:none}a.sby_video_thumbnail:after{box-shadow:inset 0 0 1px 0 rgba(0,0,0,.7);bottom:0;content:'';left:0;position:absolute;z-index:1;right:0;top:0;width:100%}[id^=sb_youtube_].sb_youtube .sby_video_thumbnail:hover .sby_play_btn{opacity:.5}[id^=sb_youtube_].sb_youtube .sby_play_btn{position:absolute;z-index:1;left:50%;bottom:50%;top:50%;right:50%;margin-top:-25px;margin-left:-28px;color:#fff;width:57px;height:50px;opacity:1;transition:opacity .2s ease-in-out;-moz-transition:opacity .2s ease-in-out;-webkit-transition:opacity .2s ease-in-out}[id^=sb_youtube_].sb_youtube .sby_play_btn_bg{display:block;position:absolute;z-index:-1;top:17px;left:22px;width:0;height:0;border:0 solid transparent;border-bottom-width:9px;border-top-width:9px;border-left:16px solid #fff}[id^=sb_youtube_].sb_youtube .sby_play_btn svg:not(:root).svg-inline--fa{width:57px;height:auto;opacity:.75}[id^=sb_youtube_].sb_youtube .sby_play_btn i,[id^=sb_youtube_].sb_youtube .sby_play_btn svg{color:#000}[id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn{margin-top:-20px;margin-left:-22px;width:45px;height:40px}[id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn_bg{top:13px;left:18px;border-bottom-width:7px;border-top-width:7px;border-left:12px solid #fff}[id^=sb_youtube_].sb_youtube.sby_medium .sby_play_btn svg:not(:root).svg-inline--fa{width:45px}[id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn{margin-top:-16px;margin-left:-18px;width:36px;height:32px}[id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn_bg{top:10px;left:14px;border-bottom-width:6px;border-top-width:6px;border-left:10px solid #fff}[id^=sb_youtube_].sb_youtube.sby_small .sby_play_btn svg:not(:root).svg-inline--fa{width:36px}[id^=sb_youtube_].sby_layout_gallery .sby_player_outer_wrap .sby_play_btn{z-index:10}[id^=sb_youtube_].sb_youtube .sby_loader{width:20px;height:20px;position:relative;top:50%;left:50%;margin:-10px 0 0 -10px;background-color:#000;background-color:rgba(0,0,0,.5);border-radius:100%;-webkit-animation:sby-sk-scaleout 1s infinite ease-in-out;animation:sby-sk-scaleout 1s infinite ease-in-out}[id^=sb_youtube_].sb_youtube .sb_youtube_header br,[id^=sb_youtube_].sb_youtube .sby_footer br,[id^=sb_youtube_].sb_youtube .sby_items_wrap br{display:none}.sby_footer p{display:inline;padding:0;margin:0}[id^=sb_youtube_].sb_youtube .sby_footer .sby_loader,[id^=sb_youtube_].sb_youtube .sby_item .sby_loader,[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap .sby_loader{position:absolute;margin-top:-11px;background-color:#fff}[id^=sb_youtube_].sb_youtube .sby_item.sby_player_loading,[id^=sb_youtube_].sb_youtube .sby_player_outer_wrap.sby_player_loading{opacity:.8}@-webkit-keyframes sby-sk-scaleout{0%{-webkit-transform:scale(0)}100%{-webkit-transform:scale(1);opacity:0}}@keyframes sby-sk-scaleout{0%{-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);opacity:0}}#sby_lightbox .fa-spin,[id^=sb_youtube_].sb_youtube .fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}#sby_lightbox .fa-pulse,[id^=sb_youtube_].sb_youtube .fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}[id^=sb_youtube_].sb_youtube .sb_youtube_header{float:left;clear:both;margin:0 0 15px 0;padding:0;line-height:1.2;width:100%}[id^=sb_youtube_].sb_youtube .sb_youtube_header a{float:left;display:block;text-decoration:none;transition:color .5s ease}@media all and (min-width:480px){[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img{width:80px;height:80px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_img img{width:80px;height:80px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{font-size:20px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info{font-size:14px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{margin-left:95px!important;line-height:1.4}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text h3{margin-right:-85px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text .sby_bio_info{margin-top:4px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_medium .sby_header_text.sby_no_bio h3{padding-top:20px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img{width:120px;height:120px;border-radius:60px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_img img{width:120px;height:120px;border-radius:60px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{font-size:28px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info{font-size:16px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info,[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{margin-left:140px!important;line-height:1.5}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text h3{margin-right:-120px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text .sby_bio_info{margin-top:12px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_large .sby_header_text.sby_no_bio h3{padding-top:32px!important}}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img{float:left;position:relative;width:50px;margin:0 0 0 -100%!important;overflow:hidden;-moz-border-radius:40px;-webkit-border-radius:40px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img img{float:left;margin:0!important;padding:0!important;border:none!important;-moz-border-radius:40px;-webkit-border-radius:40px;border-radius:40px}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{opacity:0;position:absolute;width:100%;top:0;bottom:0;left:0;text-align:center;color:#fff;background:rgba(0,0,0,.75)}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img{height:50px}[id^=sb_youtube_].sb_youtube .sb_youtube_header.sby_no_consent .sby_header_img_hover{opacity:1}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover .sby_new_logo{position:absolute;top:50%;left:50%;margin-top:-12px;margin-left:-12px;width:24px;height:24px;font-size:24px}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover i{overflow:hidden;background:url(../img/small-logo.png) no-repeat 0 0}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{z-index:2;transition:opacity .4s ease-in-out}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_fade_in{opacity:1;transition:opacity .2s ease-in-out}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_img_hover{position:absolute;width:100%;top:0;bottom:0;left:0;text-align:center;color:#fff;background:rgba(0,0,0,.75);-moz-opacity:0;-khtml-opacity:0;opacity:0;border-radius:40px;transition:opacity .2s}[id^=sb_youtube_].sb_youtube .sb_youtube_header a:focus .sby_header_img_hover,[id^=sb_youtube_].sb_youtube .sb_youtube_header a:hover .sby_header_img_hover{opacity:1}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text{float:left;width:100%;padding-top:5px}[id^=sb_youtube_].sb_youtube .sb_youtube_header a{text-decoration:none}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text .sby_bio,[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text h3{float:left;clear:both;width:auto;margin:0 0 0 60px!important;padding:0!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header h3{font-size:16px;line-height:1.3}[id^=sb_youtube_].sb_youtube .sb_youtube_header p{font-size:13px;line-height:1.3;margin:0;padding:0}[id^=sb_youtube_].sb_youtube p:empty{display:none}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text img.emoji{margin-right:3px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio h3{padding-top:9px!important}[id^=sb_youtube_].sb_youtube .sb_youtube_header .sby_header_text.sby_no_bio .sby_bio_info{clear:both}[id^=sb_youtube_].sb_youtube .sby_footer{float:left;clear:both;width:100%;text-align:center}[id^=sb_youtube_].sb_youtube .sby_footer .fa-spinner{display:none;position:absolute;top:50%;left:50%;margin:-8px 0 0 -7px;font-size:15px}[id^=sb_youtube_].sb_youtube .sby_footer{opacity:1;transition:all .5s ease-in}[id^=sb_youtube_].sb_youtube .sby_load_btn .sby_btn_text,[id^=sb_youtube_].sb_youtube .sby_load_btn .sby_loader{opacity:1;transition:all .1s ease-in}[id^=sb_youtube_].sb_youtube .sby_hidden{opacity:0!important}[id^=sb_youtube_].sb_youtube .sby_follow_btn a,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;padding:7px 14px;margin:5px auto 0 auto;background:#333;color:#eee;border:none;color:#fff;text-decoration:none;font-size:13px;line-height:1.5;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{position:relative}[id^=sb_youtube_].sb_youtube .sby_follow_btn{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;text-align:center}[id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_top{display:block;margin-bottom:5px}[id^=sb_youtube_].sb_youtube .sby_follow_btn a{background:#408bd1;color:#fff}[id^=sb_youtube_].sb_youtube .sby_follow_btn a,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn{transition:all .1s ease-in}[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:hover{outline:0;box-shadow:inset 0 0 20px 20px rgba(255,255,255,.25)}[id^=sb_youtube_].sb_youtube .sby_follow_btn a:focus,[id^=sb_youtube_].sb_youtube .sby_follow_btn a:hover{outline:0;box-shadow:inset 0 0 10px 20px #359dff}[id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:focus,[id^=sb_youtube_].sb_youtube .sby_follow_btn.sby_custom a:hover,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn.sby_custom:hover{box-shadow:inset 0 0 20px 20px rgba(255,255,255,.15)}[id^=sb_youtube_].sb_youtube .sby_follow_btn a:active,[id^=sb_youtube_].sb_youtube .sby_footer .sby_load_btn:active{box-shadow:inset 0 0 10px 20px rgba(0,0,0,.3)}[id^=sb_youtube_].sb_youtube .sby_follow_btn .fa,[id^=sb_youtube_].sb_youtube .sby_follow_btn svg{margin-bottom:-1px;margin-right:7px;font-size:15px}[id^=sb_youtube_].sb_youtube .sby_follow_btn svg{vertical-align:-.125em}[id^=sb_youtube_].sb_youtube .sby_footer .sby_follow_btn{margin-left:5px}@media all and (max-width:640px){[id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_col_2 .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_col_3 .sby_items_wrap .sby_item{width:33.33%}[id^=sb_youtube_].sb_youtube.sby_col_4 .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_col_5 .sby_items_wrap .sby_item{width:20%}[id^=sb_youtube_].sb_youtube.sby_col_6 .sby_items_wrap .sby_item{width:16.66%}[id^=sb_youtube_].sb_youtube.sby_col_7 .sby_items_wrap .sby_item{width:14.28%}[id^=sb_youtube_].sb_youtube.sby_col_8 .sby_items_wrap .sby_item{width:12.5%}[id^=sb_youtube_].sb_youtube.sby_col_9 .sby_items_wrap .sby_item{width:11.11%}[id^=sb_youtube_].sb_youtube.sby_col_10 .sby_items_wrap .sby_item{width:10%}[id^=sb_youtube_].sb_youtube.sby_width_resp{width:100%!important}}@media all and (max-width:480px){[id^=sb_youtube_].sb_youtube.sby_col_10.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_3.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_4.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_5.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_6.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_7.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_8.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_col_9.sby_mob_col_auto .sby_items_wrap .sby_item,[id^=sb_youtube_].sb_youtube.sby_mob_col_1 .sby_items_wrap .sby_item{width:100%}[id^=sb_youtube_].sb_youtube.sby_mob_col_2 .sby_items_wrap .sby_item{width:50%}[id^=sb_youtube_].sb_youtube.sby_mob_col_3 .sby_items_wrap .sby_item{width:33.33%}[id^=sb_youtube_].sb_youtube.sby_mob_col_4 .sby_items_wrap .sby_item{width:25%}[id^=sb_youtube_].sb_youtube.sby_mob_col_5 .sby_items_wrap .sby_item{width:20%}[id^=sb_youtube_].sb_youtube.sby_mob_col_6 .sby_items_wrap .sby_item{width:16.66%}[id^=sb_youtube_].sb_youtube.sby_mob_col_7 .sby_items_wrap .sby_item{width:14.28%}}.sby_lightboxOverlay{position:absolute;top:0;left:0;z-index:99999;background-color:#000;opacity:.9;display:none}.sby_lightbox{position:absolute;left:0;width:100%;z-index:100000;line-height:0;font-weight:400}.sby_lightbox .sby_lb-image{display:block;height:auto;max-width:inherit;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.sby_lightbox a:active,.sby_lightbox a:focus,.sby_lightbox a:hover{outline:0}.sby_lightbox a img{border:none}.sby_lb-outerContainer{position:relative;background-color:#000;width:250px;height:250px;margin:0 auto 5px auto;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.sby_lb-outerContainer:after{content:"";display:table;clear:both}.sby_lb-container{position:relative;padding:4px;top:0;left:0;width:100%;height:100%;bottom:0;right:0;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}.sby_lb-loader{position:absolute;top:43%;left:0;height:25%;width:100%;text-align:center;line-height:0}.sby_lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background-color:#666;background-color:rgba(255,255,255,.5);border-radius:100%;-webkit-animation:ctf-sk-scaleout 1s infinite ease-in-out;animation:ctf-sk-scaleout 1s infinite ease-in-out}.sby_lb-nav{top:0;left:0;width:100%;z-index:10}.sby_lb-container>.nav{left:0}.sby_lb-nav a{position:absolute;z-index:100;top:0;height:90%;outline:0;background-image:url(data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}.sby_lb-next,.sby_lb-prev{height:100%;cursor:pointer;display:block}.sby_lb-nav a.sby_lb-prev{width:50px;left:-70px;padding-left:10px;padding-right:10px;float:left;opacity:.5;-webkit-transition:opacity .2s;-moz-transition:opacity .2;-o-transition:opacity .2s;transition:opacity .2s}.sby_lb-nav a.sby_lb-prev:hover{opacity:1}.sby_lb-nav a.sby_lb-next{width:50px;right:-70px;padding-left:10px;padding-right:10px;float:right;opacity:.5;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.sby_lb-nav a.sby_lb-next:hover{opacity:1}.sby_lb-nav span{display:block;top:55%;position:absolute;left:20px;width:34px;height:45px;margin:-25px 0 0 0;background:url(../img/sby-sprite.png) no-repeat}.sby_lb-nav a.sby_lb-prev span{background-position:-53px 0}.sby_lb-nav a.sby_lb-next span{left:auto;right:20px;background-position:-18px 0}.sby_lb-dataContainer{margin:0 auto;padding-top:5px;width:100%;font-family:"Open Sans",Helvetica,Arial,sans-serif;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.sby_lb-dataContainer:after{content:"";display:table;clear:both}.sby_lb-data{padding:0 4px;color:#ccc}.sby_lb-data .sby_lb-details{width:85%;float:left;text-align:left;line-height:1.1}.sby_lb-data .sby_lb-caption{float:left;font-size:13px;font-weight:400;line-height:1.3;padding-bottom:3px;color:#ccc;word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto}.sby_lb-data .sby_lb-caption .ctf-screename-sep,.sby_lb-data .sby_lb-caption a{color:#ccc;font-weight:700;text-decoration:none}.sby_lb-data .sby_lb-caption a:hover{color:#fff;text-decoration:underline}.sby_lb-data .sby_lb-caption .sby_lightbox_username{float:left;width:100%;color:#ccc;padding-bottom:0;display:block;margin:0 0 5px 0}.sby_lb-data .sby_lb-caption .sby_lightbox_username{color:#ccc}.sby_lb-data .sby_lb-caption .sby_lightbox_username:hover p{color:#fff;text-decoration:underline}.sby_lightbox .sby_lightbox_username img{float:left;border:none;width:48px;height:48px;margin-right:10px;background:#666;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sby_lightbox_username p{float:left;margin:0;padding:0;color:#ccc;line-height:32px;font-weight:700;font-size:13px;text-align:left}.sby_lb-data .ctf-caption-text{width:100%;margin-left:58px;padding-top:3px}.sby_lb-data .sby_lb-caption .ctf-author-screenname,.sby_lb-data .sby_lb-caption .ctf-tweet-date{font-weight:400}.sby_lb-data .sby_lb-info{width:100%;float:left;clear:both}.sby_lb-data .sby_lb-number{display:block;float:left;clear:both;padding:5px 0 15px 0;font-size:12px;color:#999}.sby_lb-data .sby_lb-close{display:block;float:right;width:30px;height:30px;background:url(../img/close.png) top right no-repeat;text-align:right;outline:0;opacity:.7;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.sby_lb-data .sby_lb-close:hover{cursor:pointer;opacity:1}.sby_lb-nav{height:auto}.sby_lb-container{padding:0}.sby_lb-container iframe{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}#sby_lightbox .sby_lightbox_action{float:left;position:relative;padding:0 0 0 10px;margin:5px 0 0 10px;border-left:1px solid #666;font-size:12px}#sby_lightbox .sby_lightbox_action a{display:block;float:left;color:#999;text-decoration:none}#sby_lightbox .sby_lightbox_action a:focus,#sby_lightbox .sby_lightbox_action a:hover{color:#fff}#sby_lightbox .sby_lightbox_action .fa,#sby_lightbox .sby_lightbox_action svg{margin-right:5px}#sby_lightbox .sby_lightbox_action.sby_youtube .fa{font-size:13px}#sby_lightbox .sby_tooltip_social a svg{font-size:19px;padding:3px 4px;margin:auto}#sby_lightbox .sby_lightbox_tooltip{display:none;position:absolute;width:100px;bottom:22px;left:0;padding:5px 10px;margin:0;background:rgba(255,255,255,.9);color:#222;font-size:12px;line-height:1.3;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;box-shadow:0 0 10px rgba(0,0,0,.4);-moz-box-shadow:0 0 10px rgba(0,0,0,.4);-webkit-box-shadow:0 0 10px rgba(0,0,0,.4);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#sby_lightbox .sby_lightbox_tooltip .fa-play{position:absolute;font-size:8px;bottom:-6px;left:36px;color:rgba(255,255,255,.9)}#sby_lightbox .sby_tooltip_social a .fa{font-size:16px;margin:0;padding:5px}#sby_lightbox .sby_tooltip_social a#sby_facebook_icon .fa,#sby_lightbox .sby_tooltip_social a#sby_pinterest_icon .fa,#sby_lightbox .sby_tooltip_social a#sby_twitter_icon .fa{padding-top:4px;font-size:18px}#sby_lightbox .sby_gdpr_notice{z-index:6;display:block;position:absolute;top:50%;left:50%;margin-left:-44px;margin-top:-44px;padding:20px}#sby_lightbox .sby_gdpr_notice svg:not(:root).svg-inline--fa{position:relative;display:block!important;height:48px;width:48px;opacity:.8}#sby_lightbox .sby_gdpr_notice:hover svg:not(:root).svg-inline--fa{opacity:1}#sby_lightbox #sby_mod_box{width:280px;padding:5px 10px 7px 10px}#sby_lightbox .sby_tooltip_social{width:172px;padding:5px 5px 4px 5px}#sby_lightbox .sby_tooltip_social a{color:#333;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}#sby_lightbox .sby_lightbox_action #sby_facebook_icon:hover{background:#3b5998}#sby_lightbox .sby_lightbox_action #sby_twitter_icon:hover{background:#00aced}#sby_lightbox .sby_lightbox_action #sby_google_icon:hover{background:#dd4b39}#sby_lightbox .sby_lightbox_action #sby_linkedin_icon:hover{background:#007bb6}#sby_lightbox .sby_lightbox_action #sby_pinterest_icon:hover{background:#cb2027}#sby_lightbox .sby_lightbox_action #sby_email_icon:hover{background:#333}.sby_lb-dataContainer,.sby_lb-outerContainer{min-width:450px}@media all and (max-width:450px){.sby_lb-dataContainer,.sby_lb-outerContainer{min-width:0}}.sby_lightbox .sby_lb-image{display:block;height:auto;max-width:inherit;margin:0 auto;-webkit-border-radius:0;-moz-border-radius:0;-ms-border-radius:0;-o-border-radius:0;border-radius:0}#sby_mod_error{display:none;border:1px solid #ddd;background:#eee;color:#333;margin:10px 0 0;padding:10px 15px;font-size:13px;text-align:center;clear:both;margin-bottom:10px;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}#sby_mod_error p{padding:5px 0!important;margin:0!important;line-height:1.3!important}#sby_mod_error ol,#sby_mod_error ul{padding:5px 0 5px 20px!important;margin:0!important}#sby_mod_error li{padding:1px 0!important;margin:0!important}#sby_mod_error span{font-size:12px}[id^=sb_youtube_].sb_youtube svg:not(:root).svg-inline--fa,[id^=sb_youtube_].sb_youtube_lightbox svg:not(:root).svg-inline--fa{box-sizing:unset;overflow:visible;width:1em}[id^=sb_youtube_].sb_youtube .svg-inline--fa.fa-w-16{width:16px}[id^=sb_youtube_].sb_youtube .svg-inline--fa,[id^=sb_youtube_].sb_youtube_lightbox .svg-inline--fa{display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em}[id^=sb_youtube_].sb_youtube.sby_player_loaded .sby_player_outer_wrap .sby_video_thumbnail,[id^=sb_youtube_].sb_youtube.sby_player_loaded.sby_layout_list .sby_video_thumbnail{z-index:-1!important}
css/sby-blocks.css CHANGED
@@ -1,3 +1,3 @@
1
- .sb_youtube {
2
- pointer-events: none !important;
3
  }
1
+ .sb_youtube {
2
+ pointer-events: none !important;
3
  }
css/sby-notices.css CHANGED
@@ -1,119 +1,119 @@
1
- /* Review notice */
2
- .sby_notice{
3
- position: relative;
4
- overflow: hidden;
5
- clear: both;
6
- max-width: 885px;
7
- margin-top: 10px;
8
- padding: 10px 10px 7px 10px;
9
-
10
- background: #E6F0E8;
11
- border: 1px solid #6AB074;
12
- color: #214F28;
13
- }
14
- .sby_notice .sby_thumb{
15
- position: relative;
16
- display: inline-block;
17
- width: 74px;
18
- margin: 0 0 0 -100% !important;
19
-
20
- -moz-border-radius: 4px;
21
- -webkit-border-radius: 4px;
22
- border-radius: 4px;
23
- }
24
- .sby_notice .sby_thumb .img-overlay {
25
- position: absolute;
26
- bottom: 4px;
27
- padding: 6px 7px 6px 5px;
28
- font-size: 13px;
29
- font-weight: bold;
30
- background: #fff;
31
- background: rgba(255,255,255,0.85);
32
- line-height: 1;
33
- color: #333;
34
- box-shadow: 1px -1px 3px 0 rgba(0,0,0,0.15);
35
- }
36
- .sby_notice .sby_thumb img {
37
- max-width: 100%;
38
- }
39
- .sby_notice .sby-notice-text{
40
- float: left;
41
- clear: none;
42
- width: 100%;
43
- padding: 0;
44
- }
45
- .sby_notice .sby-links{
46
- margin-top: 4px !important;
47
- }
48
- .sby_notice p{
49
- float: left;
50
- clear: both;
51
- width: auto;
52
- margin: 0 0 0 90px !important;
53
- padding: 2px 40px 2px 0;
54
- line-height: 1.4;
55
- }
56
- .sby_notice a{
57
- display: inline-block;
58
- padding: 0 8px;
59
- color: #178529;
60
- }
61
- .sby_notice a:hover,
62
- .sby_notice a:focus{
63
- color: #0c7abf;
64
- }
65
- .sby_notice .links{
66
- margin: 0 0 0 90px !important;
67
- padding: 4px 0 0 0;
68
- margin-top: 1px !important;
69
- }
70
- .sby_review_notice .links{
71
- margin-left: 82px !important;
72
- margin-top: 0 !important;
73
- }
74
- .sby_notice .sby_notice_close,
75
- .sby_notice .sby_bfcm_sale_notice_close,
76
- .sby_notice .sby_new_user_sale_notice_close {
77
- position: absolute;
78
- top: 0;
79
- right: 0;
80
- padding: 10px;
81
- line-height: 1;
82
- }
83
- .sby_notice .sby_notice_close:hover,
84
- .sby_notice .sby_notice_close:focus{
85
- color: #a34100;
86
- }
87
- .sby_notice strong span {
88
- font-weight: 900;
89
- }
90
- /* Notice CTA btn */
91
- .sby_notice .sby_offer_btn,
92
- .sby_notice .sby_main_cta{
93
- padding: 4px 12px 6px 12px;
94
- background: green;
95
- color: #fff;
96
- border-radius: 4px;
97
- display: inline-block;
98
- text-decoration: none;
99
- margin-left: 0;
100
- margin-right: 4px;
101
- }
102
- .sby_notice .sby_offer_btn:hover,
103
- .sby_notice .sby_offer_btn:focus,
104
- .sby_notice .sby_main_cta:hover,
105
- .sby_notice .sby_main_cta:focus{
106
- background: #049404;
107
- color: #fff;
108
- }
109
- .sby_notice .sby_other_notice{
110
- padding-top: 10px;
111
- font-style: italic;
112
- font-size: 12px;
113
- }
114
- .sby_notice .sby_other_notice a{
115
- padding: 0;
116
- }
117
- .sby_notice .links > .sby_main_cta:first-child {
118
- margin-left: 8px;
119
  }
1
+ /* Review notice */
2
+ .sby_notice{
3
+ position: relative;
4
+ overflow: hidden;
5
+ clear: both;
6
+ max-width: 885px;
7
+ margin-top: 10px;
8
+ padding: 10px 10px 7px 10px;
9
+
10
+ background: #E6F0E8;
11
+ border: 1px solid #6AB074;
12
+ color: #214F28;
13
+ }
14
+ .sby_notice .sby_thumb{
15
+ position: relative;
16
+ display: inline-block;
17
+ width: 74px;
18
+ margin: 0 0 0 -100% !important;
19
+
20
+ -moz-border-radius: 4px;
21
+ -webkit-border-radius: 4px;
22
+ border-radius: 4px;
23
+ }
24
+ .sby_notice .sby_thumb .img-overlay {
25
+ position: absolute;
26
+ bottom: 4px;
27
+ padding: 6px 7px 6px 5px;
28
+ font-size: 13px;
29
+ font-weight: bold;
30
+ background: #fff;
31
+ background: rgba(255,255,255,0.85);
32
+ line-height: 1;
33
+ color: #333;
34
+ box-shadow: 1px -1px 3px 0 rgba(0,0,0,0.15);
35
+ }
36
+ .sby_notice .sby_thumb img {
37
+ max-width: 100%;
38
+ }
39
+ .sby_notice .sby-notice-text{
40
+ float: left;
41
+ clear: none;
42
+ width: 100%;
43
+ padding: 0;
44
+ }
45
+ .sby_notice .sby-links{
46
+ margin-top: 4px !important;
47
+ }
48
+ .sby_notice p{
49
+ float: left;
50
+ clear: both;
51
+ width: auto;
52
+ margin: 0 0 0 90px !important;
53
+ padding: 2px 40px 2px 0;
54
+ line-height: 1.4;
55
+ }
56
+ .sby_notice a{
57
+ display: inline-block;
58
+ padding: 0 8px;
59
+ color: #178529;
60
+ }
61
+ .sby_notice a:hover,
62
+ .sby_notice a:focus{
63
+ color: #0c7abf;
64
+ }
65
+ .sby_notice .links{
66
+ margin: 0 0 0 90px !important;
67
+ padding: 4px 0 0 0;
68
+ margin-top: 1px !important;
69
+ }
70
+ .sby_review_notice .links{
71
+ margin-left: 82px !important;
72
+ margin-top: 0 !important;
73
+ }
74
+ .sby_notice .sby_notice_close,
75
+ .sby_notice .sby_bfcm_sale_notice_close,
76
+ .sby_notice .sby_new_user_sale_notice_close {
77
+ position: absolute;
78
+ top: 0;
79
+ right: 0;
80
+ padding: 10px;
81
+ line-height: 1;
82
+ }
83
+ .sby_notice .sby_notice_close:hover,
84
+ .sby_notice .sby_notice_close:focus{
85
+ color: #a34100;
86
+ }
87
+ .sby_notice strong span {
88
+ font-weight: 900;
89
+ }
90
+ /* Notice CTA btn */
91
+ .sby_notice .sby_offer_btn,
92
+ .sby_notice .sby_main_cta{
93
+ padding: 4px 12px 6px 12px;
94
+ background: green;
95
+ color: #fff;
96
+ border-radius: 4px;
97
+ display: inline-block;
98
+ text-decoration: none;
99
+ margin-left: 0;
100
+ margin-right: 4px;
101
+ }
102
+ .sby_notice .sby_offer_btn:hover,
103
+ .sby_notice .sby_offer_btn:focus,
104
+ .sby_notice .sby_main_cta:hover,
105
+ .sby_notice .sby_main_cta:focus{
106
+ background: #049404;
107
+ color: #fff;
108
+ }
109
+ .sby_notice .sby_other_notice{
110
+ padding-top: 10px;
111
+ font-style: italic;
112
+ font-size: 12px;
113
+ }
114
+ .sby_notice .sby_other_notice a{
115
+ padding: 0;
116
+ }
117
+ .sby_notice .links > .sby_main_cta:first-child {
118
+ margin-left: 8px;
119
  }
img/sby-icon-offer.png DELETED
Binary file
inc/admin/admin-functions.php CHANGED
@@ -1,785 +1,785 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- function sby_admin_init() {
7
- global $sby_settings;
8
-
9
- $base_path = trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates';
10
- $slug = SBY_SLUG;
11
- $plugin_name = SBY_PLUGIN_NAME;
12
- $capability = current_user_can( 'manage_options' ) ? 'manage_options' : 'manage_youtube_feed_options';
13
- $icon = 'dashicons-video-alt3';
14
- $position = 99;
15
- $tabs = array(
16
- array(
17
- 'title' => __( 'Configure', SBY_TEXT_DOMAIN ),
18
- 'slug' => 'configure',
19
- 'capability' => $capability,
20
- 'next_step_instructions' => __( 'Customize your feed', SBY_TEXT_DOMAIN )
21
- ),
22
- array(
23
- 'title' => __( 'Customize', SBY_TEXT_DOMAIN ),
24
- 'slug' => 'customize',
25
- 'capability' => $capability,
26
- 'next_step_instructions' => __( 'Display your feed', SBY_TEXT_DOMAIN )
27
- ),
28
- array(
29
- 'title' => __( 'Display', SBY_TEXT_DOMAIN ),
30
- 'slug' => 'display',
31
- 'capability' => $capability
32
- ),
33
- array(
34
- 'title' => __( 'Support', SBY_TEXT_DOMAIN ),
35
- 'slug' => 'support',
36
- 'capability' => $capability,
37
- 'numbered_tab' => false
38
- ),
39
- array(
40
- 'title' => __( 'All Feeds', SBY_TEXT_DOMAIN ),
41
- 'slug' => 'allfeeds',
42
- 'capability' => $capability,
43
- 'numbered_tab' => false,
44
- 'has_nav_tab' => false
45
- )
46
- );
47
-
48
- $active_tab = $tabs[0]['slug'];
49
- if ( isset( $_GET['tab'] ) ) {
50
- $active_tab = sanitize_text_field( $_GET['tab'] ); $tabs[0]['slug'];
51
- } elseif ( isset( $_GET['page'] ) ) {
52
- foreach ( $tabs as $tab ) {
53
- if ( $_GET['page'] === $slug . '_' . $tab['slug'] ) {
54
- $active_tab = $tab['slug'];
55
- }
56
- }
57
- }
58
- $vars = new SBY_Vars();
59
- $admin = new SBY_Admin( $vars, $base_path, $slug, $plugin_name, $capability, $icon, $position, $tabs, $sby_settings, $active_tab, 'sby_settings' );
60
- $admin->access_token_listener();
61
-
62
- $first_connected = sby_get_first_connected_account();
63
- $first_channel_id = isset( $first_connected['channel_id'] ) ? $first_connected['channel_id'] : '';
64
-
65
- $types = array(
66
- array(
67
- 'slug' => 'channel',
68
- 'label' => __( 'Channel', SBY_TEXT_DOMAIN ),
69
- 'input_type' => 'text',
70
- 'default' => $first_channel_id,
71
- 'note' => __( 'Eg: Channel ID or User Name', SBY_TEXT_DOMAIN ),
72
- 'example' => 'smashballoon',
73
- 'description' => __( 'Display videos from a YouTube channel (channel)', SBY_TEXT_DOMAIN ),
74
- 'tooltip' => '<p>' . __( 'Enter any channel ID or user name to display all of an accounts latest videos starting with the most recently published.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
75
- <li><b>' . __( 'Channel ID or User Name', SBY_TEXT_DOMAIN ).'</b><br>
76
- ' . __( 'You can find the ID or User Name of your YouTube Channel from the URL. In each URL format, the text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
77
- ' . __( 'URL Format 1:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/channel/<span class="sbspf-highlight">UC1a2b3c4D5F6g7i8j9k</span></code>
78
- <br>
79
- ' . __( 'URL Format 2:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/user/<span class="sbspf-highlight">your_user_name</span></code>
80
- </li>
81
- </ul></p>'
82
- ),
83
- array(
84
- 'slug' => 'playlist',
85
- 'label' => __( 'Playlist', SBY_TEXT_DOMAIN ),
86
- 'input_type' => 'text',
87
- 'default' => '',
88
- 'pro' => true,
89
- 'note' => __( 'Eg: Playlist ID', SBY_TEXT_DOMAIN ),
90
- 'example' => 'PLLLm1a2b3c4D6g7i8j9k_1a',
91
- 'description' => __( 'Display videos from a specific playlist (playlist)', SBY_TEXT_DOMAIN ),
92
- 'tooltip' => '<p>' . __( 'Enter any playlist ID to display videos from a playlist starting with the most recently published.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
93
- <li><b>' . __( 'Playlist ID', SBY_TEXT_DOMAIN ).'</b><br>
94
- ' . __( 'You can find the ID of your YouTube playlist from the URL. The text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
95
- <code>https://www.youtube.com/playlist?list=<span class="sbspf-highlight">PLLLm1a2b3c4D6g7i8j9k_1a2b3c4D57i8j9k</span></code>
96
- </li>
97
- </ul></p>'
98
- ),
99
- array(
100
- 'slug' => 'favorites',
101
- 'label' => __( 'Favorites', SBY_TEXT_DOMAIN ),
102
- 'input_type' => 'text',
103
- 'default' => '',
104
- 'pro' => true,
105
- 'note' => __( 'Eg: Channel ID or User Name', SBY_TEXT_DOMAIN ),
106
- 'example' => 'smashballoon',
107
- 'description' => __( 'Display the "favorites" playlist for a channel (favorites)', SBY_TEXT_DOMAIN ),
108
- 'tooltip' => '<p>' . __( 'Displays all videos marked as "favorites" by a YouTube account starting with the most recently published.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
109
- <li><b>' . __( 'Channel ID or User Name', SBY_TEXT_DOMAIN ).'</b><br>
110
- ' . __( 'You can find the ID or User Name of your YouTube Channel from the URL. In each URL format, the text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
111
- ' . __( 'URL Format 1:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/channel/<span class="sbspf-highlight">UC1a2b3c4D5F6g7i8j9k</span></code>
112
- <br>
113
- ' . __( 'URL Format 2:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/user/<span class="sbspf-highlight">your_user_name</span></code>
114
- </li>
115
- </ul></p>'
116
- ),
117
- array(
118
- 'slug' => 'search',
119
- 'label' => __( 'Search', SBY_TEXT_DOMAIN ),
120
- 'input_type' => 'text',
121
- 'default' => '',
122
- 'pro' => true,
123
- 'note' => __( 'Eg: Search Term', SBY_TEXT_DOMAIN ),
124
- 'example' => 'cats',
125
- 'description' => __( 'Display a feed of matching search results (search)', SBY_TEXT_DOMAIN ),
126
- 'tooltip' => '<p>' . __( 'Enter any search term or phrase. Separate multiple terms with commas. You can add your own additional query vars using the <a href="https://smashballoon.com/youtube-feed/custom-search-guide/" target="_blank" rel="noopener">guide on our website</a> and the input field above.', SBY_TEXT_DOMAIN ) . '</p>',
127
- ),
128
- array(
129
- 'slug' => 'live',
130
- 'label' => __( 'Live Streams', SBY_TEXT_DOMAIN ),
131
- 'input_type' => 'text',
132
- 'default' => '',
133
- 'pro' => true,
134
- 'note' => __( 'Eg: Channel ID', SBY_TEXT_DOMAIN ),
135
- 'example' => 'UC1a2b3c4D5F6g7i8j9k',
136
- 'description' => __( 'Display upcoming and currently playing live streams (live)', SBY_TEXT_DOMAIN ),
137
- 'tooltip' => '<p>' . __( 'Displays upcoming and currently playing live streaming videos sorted by soonest scheduled broadcast.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
138
- <li><b>' . __( 'Channel ID', SBY_TEXT_DOMAIN ).'</b><br>
139
- ' . __( 'You can find the ID of your YouTube Channel from the URL. The text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
140
- <code>https://www.youtube.com/channel/<span class="sbspf-highlight">UC1a2b3c4D5F6g7i8j9k</span></code>
141
- </li>
142
- </ul></p>'
143
- )
144
- );
145
- $admin->set_feed_types( $types );
146
-
147
- $text_domain = SBY_TEXT_DOMAIN;
148
- /* Layout */
149
- $layouts = array(
150
- array(
151
- 'slug' => 'grid',
152
- 'label' => __( 'Grid', $text_domain ),
153
- 'image' => 'img/grid.png',
154
- 'note' => __( 'Video thumbnails are displayed in columns and play in a lightbox when clicked.', $text_domain ),
155
- 'options' => array(
156
- array(
157
- 'name' => 'cols',
158
- 'callback' => 'select',
159
- 'label' => __( 'Columns', $text_domain ),
160
- 'min' => 1,
161
- 'max' => 7,
162
- 'default' => 3,
163
- 'shortcode' => array(
164
- 'example' => '3',
165
- 'description' => __( 'Videos in carousel when 480px screen width or less.', $text_domain ),
166
- )
167
- ),
168
- array(
169
- 'name' => 'colsmobile',
170
- 'callback' => 'select',
171
- 'label' => __( 'Mobile Columns', $text_domain ),
172
- 'min' => 1,
173
- 'max' => 2,
174
- 'default' => 2,
175
- 'shortcode' => array(
176
- 'example' => '2',
177
- 'description' => __( 'Columns when 480px screen width or less.', $text_domain ),
178
- )
179
- ),
180
- )
181
- ),
182
- array(
183
- 'slug' => 'gallery',
184
- 'label' => __( 'Gallery', $text_domain ),
185
- 'image' => 'img/gallery.png',
186
- 'note' => __( 'One large video that plays when clicked with thumbnails underneath to play more.', $text_domain ),
187
- 'options' => array(
188
- array(
189
- 'name' => 'cols',
190
- 'callback' => 'select',
191
- 'label' => __( 'Columns', $text_domain ),
192
- 'min' => 1,
193
- 'max' => 7,
194
- 'default' => 3,
195
- 'shortcode' => array(
196
- 'example' => '3',
197
- 'description' => __( 'Videos in carousel when 480px screen width or less.', $text_domain ),
198
- )
199
- ),
200
- array(
201
- 'name' => 'colsmobile',
202
- 'callback' => 'select',
203
- 'label' => __( 'Mobile Columns', $text_domain ),
204
- 'min' => 1,
205
- 'max' => 2,
206
- 'default' => 2,
207
- 'shortcode' => array(
208
- 'example' => '2',
209
- 'description' => __( 'Columns when 480px screen width or less.', $text_domain ),
210
- )
211
- ),
212
- )
213
- ),
214
- array(
215
- 'slug' => 'list',
216
- 'label' => __( 'List', $text_domain ),
217
- 'image' => 'img/list.png',
218
- 'note' => __( 'A single columns of videos that play when clicked.', $text_domain ),
219
- ),
220
- array(
221
- 'slug' => 'carousel',
222
- 'label' => __( 'Carousel', $text_domain ),
223
- 'image' => 'img/carousel.png',
224
- 'note' => __( 'Posts are displayed in a slideshow carousel.', $text_domain ),
225
- 'pro' => true,
226
- 'options' => array(
227
- array(
228
- 'name' => 'cols',
229
- 'callback' => 'select',
230
- 'label' => __( 'Columns', $text_domain ),
231
- 'min' => 1,
232
- 'max' => 7,
233
- 'default' => 3,
234
- 'shortcode' => array(
235
- 'example' => '3',
236
- 'description' => __( 'Videos in carousel when 480px screen width or less.', $text_domain ),
237
- )
238
- ),
239
- array(
240
- 'name' => 'colsmobile',
241
- 'callback' => 'select',
242
- 'label' => __( 'Mobile Columns', $text_domain ),
243
- 'min' => 1,
244
- 'max' => 2,
245
- 'default' => 2,
246
- 'shortcode' => array(
247
- 'example' => '2',
248
- 'description' => __( 'Columns when 480px screen width or less.', $text_domain ),
249
- ) ),
250
- array(
251
- 'name' => 'rows',
252
- 'callback' => 'select',
253
- 'label' => __( 'Number of Rows', $text_domain ),
254
- 'min' => 1,
255
- 'max' => 2,
256
- 'default' => 1,
257
- 'shortcode' => array(
258
- 'example' => '2',
259
- 'description' => __( 'Choose 2 rows to show two posts in a single slide.', $text_domain ),
260
- )
261
- ),
262
- array(
263
- 'name' => 'loop',
264
- 'callback' => 'select',
265
- 'label' => __( 'Loop Type', $text_domain ),
266
- 'options' => array(
267
- array(
268
- 'label' => __( 'Rewind', $text_domain ),
269
- 'value' => 'rewind'
270
- ),
271
- array(
272
- 'label' => __( 'Infinity', $text_domain ),
273
- 'value' => 'infinity'
274
- )
275
- ),
276
- 'default' => 'rewind',
277
- 'shortcode' => array(
278
- 'example' => 'infinity',
279
- 'description' => __( 'What happens when the last slide is reached.', $text_domain ),
280
- )
281
- ),
282
- array(
283
- 'name' => 'arrows',
284
- 'callback' => 'checkbox',
285
- 'label' => __( 'Show Navigation Arrows', $text_domain ),
286
- 'default' => true,
287
- 'shortcode' => array(
288
- 'example' => 'false',
289
- 'description' => __( 'Show arrows on the sides to navigate posts.', $text_domain ),
290
- )
291
- ),
292
- array(
293
- 'name' => 'pag',
294
- 'callback' => 'checkbox',
295
- 'label' => __( 'Show Pagination', $text_domain ),
296
- 'default' => true,
297
- 'shortcode' => array(
298
- 'example' => 'false',
299
- 'description' => __( 'Show dots below carousel for an ordinal indication of which slide is being shown.', $text_domain ),
300
- )
301
- ),
302
- array(
303
- 'name' => 'autoplay',
304
- 'callback' => 'checkbox',
305
- 'label' => __( 'Enable Autoplay', $text_domain ),
306
- 'default' => false,
307
- 'shortcode' => array(
308
- 'example' => 'true',
309
- 'description' => __( 'Whether or not to change slides automatically on an interval.', $text_domain ),
310
- )
311
- ),
312
- array(
313
- 'name' => 'time',
314
- 'callback' => 'text',
315
- 'label' => __( 'Interval Time', $text_domain ),
316
- 'default' => 5000,
317
- 'shortcode' => array(
318
- 'example' => '3000',
319
- 'description' => __( 'Duration in milliseconds before the slide changes.', $text_domain ),
320
- )
321
- ),
322
- )
323
- ),
324
-
325
- );
326
- $admin->set_feed_layouts( $layouts );
327
-
328
- $display_your_feed_table_headings = array(
329
- array(
330
- 'slug' => 'configure',
331
- 'label' => __( 'Configure Options', SBY_TEXT_DOMAIN ),
332
- ),
333
- array(
334
- 'slug' => 'customize',
335
- 'label' => __( 'Customize Options', SBY_TEXT_DOMAIN ),
336
- ),
337
- array(
338
- 'slug' => 'layout',
339
- 'label' => __( 'Layout Options', SBY_TEXT_DOMAIN ),
340
- ),
341
- array(
342
- 'slug' => 'experience',
343
- 'label' => __( 'Video Experience Options', SBY_TEXT_DOMAIN ),
344
- ),
345
- array(
346
- 'slug' => 'header',
347
- 'label' => __( 'Header Options', SBY_TEXT_DOMAIN ),
348
- ),
349
- array(
350
- 'slug' => 'button',
351
- 'label' => __( '"Load More" Button Options', SBY_TEXT_DOMAIN ),
352
- ),
353
- array(
354
- 'slug' => 'subscribe',
355
- 'label' => __( '"Subscribe" Button Options', SBY_TEXT_DOMAIN ),
356
- )
357
- );
358
- $admin->set_display_table_sections( $display_your_feed_table_headings );
359
-
360
- $admin->init();
361
- }
362
-
363
- function sby_admin_style() {
364
- wp_enqueue_style( SBY_SLUG . '_admin_notices_css', SBY_PLUGIN_URL . 'css/sby-notices.css', array(), SBYVER );
365
- if ( ! sby_is_admin_page() ) {
366
- return;
367
- }
368
- wp_enqueue_style( SBY_SLUG . '_admin_css', SBY_PLUGIN_URL . 'css/admin.css', array(), SBYVER );
369
- wp_enqueue_style( 'sb_font_awesome', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' );
370
- wp_enqueue_style( 'wp-color-picker' );
371
- }
372
- add_action( 'admin_enqueue_scripts', 'sby_admin_style' );
373
-
374
- function sby_admin_scripts() {
375
- if ( ! sby_is_admin_page() ) {
376
- return;
377
- }
378
- wp_enqueue_script( SBY_SLUG . '_admin_js', SBY_PLUGIN_URL . 'js/admin.js', array(), SBYVER );
379
- wp_localize_script( SBY_SLUG . '_admin_js', 'sbspf', array(
380
- 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
381
- 'nonce' => wp_create_nonce( 'sbspf_nonce' )
382
- )
383
- );
384
- wp_enqueue_script('wp-color-picker' );
385
- }
386
- add_action( 'admin_enqueue_scripts', 'sby_admin_scripts' );
387
-
388
- function sby_is_admin_page() {
389
- if ( ! isset( $_GET['page'] ) ) {
390
- return false;
391
- } elseif ( strpos( sanitize_text_field( $_GET['page'] ), SBY_SLUG ) !== false ) {
392
- return true;
393
- }
394
- return false;
395
- }
396
-
397
- function sby_admin_icon( $icon, $class = '' ) {
398
- $class = ! empty( $class ) ? ' ' . $class : '';
399
- if ( $icon === 'question-circle' ) {
400
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="question-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-question-circle fa-w-16'.$class.'"><path fill="currentColor" d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z" class=""></path></svg>';
401
- } elseif ( $icon === 'info-circle' ) {
402
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="info-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-info-circle fa-w-16'.$class.'"><path fill="currentColor" d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z" class=""></path></svg>';
403
- } elseif ( $icon === 'life-ring' ) {
404
- return '<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="life-ring" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-life-ring fa-w-16'.$class.'"><path fill="currentColor" d="M256 504c136.967 0 248-111.033 248-248S392.967 8 256 8 8 119.033 8 256s111.033 248 248 248zm-103.398-76.72l53.411-53.411c31.806 13.506 68.128 13.522 99.974 0l53.411 53.411c-63.217 38.319-143.579 38.319-206.796 0zM336 256c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zm91.28 103.398l-53.411-53.411c13.505-31.806 13.522-68.128 0-99.974l53.411-53.411c38.319 63.217 38.319 143.579 0 206.796zM359.397 84.72l-53.411 53.411c-31.806-13.505-68.128-13.522-99.973 0L152.602 84.72c63.217-38.319 143.579-38.319 206.795 0zM84.72 152.602l53.411 53.411c-13.506 31.806-13.522 68.128 0 99.974L84.72 359.398c-38.319-63.217-38.319-143.579 0-206.796z" class=""></path></svg>';
405
- } elseif ( $icon === 'envelope' ) {
406
- return '<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="envelope" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-envelope fa-w-16'.$class.'"><path fill="currentColor" d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm0 48v40.805c-22.422 18.259-58.168 46.651-134.587 106.49-16.841 13.247-50.201 45.072-73.413 44.701-23.208.375-56.579-31.459-73.413-44.701C106.18 199.465 70.425 171.067 48 152.805V112h416zM48 400V214.398c22.914 18.251 55.409 43.862 104.938 82.646 21.857 17.205 60.134 55.186 103.062 54.955 42.717.231 80.509-37.199 103.053-54.947 49.528-38.783 82.032-64.401 104.947-82.653V400H48z" class=""></path></svg>';
407
- } elseif ( $icon === 'chevron-right' ) {
408
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-circle-right" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-chevron-circle-right fa-w-16'.$class.'"><path fill="currentColor" d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z" class=""></path></svg>';
409
- } elseif ( $icon === 'rocket' ) {
410
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="rocket" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-rocket fa-w-16'.$class.'"><path fill="currentColor" d="M505.05 19.1a15.89 15.89 0 0 0-12.2-12.2C460.65 0 435.46 0 410.36 0c-103.2 0-165.1 55.2-211.29 128H94.87A48 48 0 0 0 52 154.49l-49.42 98.8A24 24 0 0 0 24.07 288h103.77l-22.47 22.47a32 32 0 0 0 0 45.25l50.9 50.91a32 32 0 0 0 45.26 0L224 384.16V488a24 24 0 0 0 34.7 21.49l98.7-49.39a47.91 47.91 0 0 0 26.5-42.9V312.79c72.59-46.3 128-108.4 128-211.09.1-25.2.1-50.4-6.85-82.6zM384 168a40 40 0 1 1 40-40 40 40 0 0 1-40 40z" class=""></path></svg>';
411
- } elseif ( $icon === 'minus-circle' ) {
412
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="minus-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-minus-circle fa-w-16'.$class.'"><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z" class=""></path></svg>';
413
- } elseif ( $icon === 'times' ) {
414
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512" class="svg-inline--fa fa-times fa-w-11'.$class.'"><path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" class=""></path></svg>';
415
- } elseif ( $icon === 'cog' ) {
416
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="cog" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-cog fa-w-16'.$class.'"><path fill="currentColor" d="M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z" class=""></path></svg>';
417
- } elseif ( $icon === 'ellipsis' ) {
418
- return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="ellipsis-h" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-ellipsis-h fa-w-16'.$class.'"><path fill="currentColor" d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z" class=""></path></svg>';
419
- } else {
420
- sby_icon( $icon );
421
- }
422
- }
423
-
424
- function sby_delete_connected_account() {
425
- if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['account_id']) ) return;
426
- $nonce = $_POST['sbspf_nonce'];
427
- if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
428
- die ( 'You did not do this the right way!' );
429
- }
430
-
431
- global $sby_settings;
432
-
433
- $account_id = sanitize_text_field( $_POST['account_id'] );
434
- $to_save = array();
435
-
436
- foreach ( $sby_settings['connected_accounts'] as $connected_account ) {
437
- if ( (string)$connected_account['channel_id'] !== (string)$account_id ) {
438
- $to_save[ $connected_account['channel_id'] ] = $connected_account;
439
- }
440
- }
441
-
442
- $sby_settings['connected_accounts'] = $to_save;
443
- update_option( 'sby_settings', $sby_settings );
444
-
445
- echo wp_json_encode( array( 'success' => true ) );
446
-
447
- die();
448
- }
449
- add_action( 'wp_ajax_sby_ca_after_remove_clicked', 'sby_delete_connected_account' );
450
-
451
- function sby_process_access_token() {
452
- if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['sby_access_token'] ) ) return;
453
- $nonce = $_POST['sbspf_nonce'];
454
- if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
455
- die ( 'You did not do this the right way!' );
456
- }
457
-
458
- $account = sby_attempt_connection();
459
-
460
- if ( $account ) {
461
- global $sby_settings;
462
-
463
- $options = $sby_settings;
464
- $username = $account['username'] ? $account['username'] : $account['channel_id'];
465
- if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['favorlocal'] ) && $options['favorlocal' ] === 'on' ) {
466
- $upload = wp_upload_dir();
467
- $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBY_UPLOADS_NAME );
468
- $profile_picture = '<img class="sbspf_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
469
- } else {
470
- $profile_picture = $account['profile_picture'] ? '<img class="sbspf_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
471
- }
472
-
473
- $text_domain = SBY_TEXT_DOMAIN;
474
- $slug = SBY_SLUG;
475
- ob_start();
476
- include trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates/single-connected-account.php';
477
- if ( sby_notice_not_dismissed() ) {
478
- include trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates/modal.php';
479
- echo '<span class="sby_account_just_added"></span>';
480
- }
481
-
482
- $html = ob_get_contents();
483
- ob_get_clean();
484
-
485
- $return = array(
486
- 'account_id' => $account['channel_id'],
487
- 'html' => $html
488
- );
489
- } else {
490
- $return = array(
491
- 'error' => __( 'Could not connect your account. Please check to make sure this is a valid access token for the Smash Balloon YouTube App.'),
492
- 'html' => ''
493
- );
494
- }
495
-
496
- echo wp_json_encode( $return );
497
-
498
- die();
499
- }
500
- add_action( 'wp_ajax_sby_process_access_token', 'sby_process_access_token' );
501
-
502
- function sby_delete_wp_posts() {
503
- if ( ! isset( $_POST['sbspf_nonce'] ) ) return;
504
- $nonce = $_POST['sbspf_nonce'];
505
- if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
506
- die ( 'You did not do this the right way!' );
507
- }
508
-
509
- sby_clear_wp_posts();
510
-
511
- echo '{}';
512
-
513
- die();
514
- }
515
- add_action( 'wp_ajax_sby_delete_wp_posts', 'sby_delete_wp_posts' );
516
-
517
- function sby_attempt_connection() {
518
- if ( ! current_user_can( 'manage_youtube_feed_options' ) ) {
519
- return false;
520
- }
521
- if ( isset( $_GET['sby_access_token'] ) ) {
522
- $access_token = sanitize_text_field( urldecode( $_GET['sby_access_token'] ) );
523
- $refresh_token = '';
524
- } else {
525
- $access_token = sanitize_text_field( $_POST['sby_access_token'] );
526
- $refresh_token = '';
527
- }
528
-
529
- $account_info = array(
530
- 'access_token' => $access_token,
531
- 'refresh_token' => $refresh_token
532
- );
533
- $sby_api_connect = new SBY_API_Connect( $account_info, 'tokeninfo' );
534
- $sby_api_connect->connect();
535
-
536
- $data = $sby_api_connect->get_data();
537
-
538
- if ( isset( $data['audience'] ) ) {
539
- $expires = $data['expires_in'] + time();
540
- $sby_api_connect = new SBY_API_Connect( $account_info, 'channels' );
541
- $sby_api_connect->connect();
542
- $data = $sby_api_connect->get_data();
543
-
544
- if ( isset( $data['items'] ) ) {
545
- $account_info['username'] = $data['items'][0]['snippet']['title'];
546
- $account_info['channel_id'] = $data['items'][0]['id'];
547
- $account_info['profile_picture'] = $data['items'][0]['snippet']['thumbnails']['default']['url'];
548
- $account_info['privacy'] = '';
549
- $account_info['expires'] = $expires;
550
- //privacyStatus
551
- SBY_Admin::connect_account( $account_info );
552
-
553
- return $account_info;
554
- } else {
555
- $account_info['username'] = '(No Channel)';
556
- $account_info['channel_id'] = '';
557
- $account_info['profile_picture'] = '';
558
- $account_info['privacy'] = '';
559
- $account_info['expires'] = $expires;
560
- //privacyStatus
561
- SBY_Admin::connect_account( $account_info );
562
-
563
- return $account_info;
564
- }
565
- }
566
- return false;
567
- }
568
-
569
- function sbspf_account_search() {
570
- if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['term']) ) return;
571
- $nonce = $_POST['sbspf_nonce'];
572
- if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
573
- die ( 'You did not do this the right way!' );
574
- }
575
-
576
- global $sby_settings;
577
-
578
- $term = sanitize_text_field( $_POST['term'] );
579
- $params = array(
580
- 'q' => $term,
581
- 'type' => 'channel'
582
- );
583
-
584
- $connected_account_for_term = array();
585
- foreach ( $sby_settings['connected_accounts'] as $connected_account ) {
586
- $connected_account_for_term = $connected_account;
587
- }
588
- if ( $connected_account_for_term['expires'] < time() + 5 ) {
589
- $new_token_data = SBY_API_Connect::refresh_token( sby_get_account_bottom(), $connected_account_for_term['refresh_token'], sby_get_account_top() );
590
-
591
- if ( isset( $new_token_data['access_token'] ) ) {
592
- $connected_account_for_term['access_token'] = $new_token_data['access_token'];
593
- $connected_accounts_for_feed[ $term ]['access_token'] = $new_token_data['access_token'];
594
- $connected_account_for_term['expires'] = $new_token_data['expires_in'] + time();
595
- $connected_accounts_for_feed[ $term ]['expires'] = $new_token_data['expires_in'] + time();
596
-
597
- sby_update_or_connect_account( $connected_account_for_term );
598
-
599
- }
600
- }
601
-
602
- $search = new SBY_API_Connect( $connected_account_for_term, 'search', $params );
603
-
604
- $search->connect();
605
-
606
-
607
- echo wp_json_encode( $search->get_data() );
608
-
609
- die();
610
- }
611
- add_action( 'wp_ajax_sbspf_account_search', 'sbspf_account_search' );
612
-
613
- function sby_reset_cron( $settings ) {
614
- $sbi_caching_type = isset( $settings['caching_type'] ) ? $settings['caching_type'] : '';
615
- $sbi_cache_cron_interval = isset( $settings['cache_cron_interval'] ) ? $settings['cache_cron_interval'] : '';
616
- $sbi_cache_cron_time = isset( $settings['cache_cron_time'] ) ? $settings['cache_cron_time'] : '';
617
- $sbi_cache_cron_am_pm = isset( $settings['cache_cron_am_pm'] ) ? $settings['cache_cron_am_pm'] : '';
618
-
619
- if ( $sbi_caching_type === 'background' ) {
620
- delete_option( 'sby_cron_report' );
621
- SBY_Cron_Updater::start_cron_job( $sbi_cache_cron_interval, $sbi_cache_cron_time, $sbi_cache_cron_am_pm );
622
- }
623
- }
624
- add_action( 'sby_settings_after_configure_save', 'sby_reset_cron', 10, 1 );
625
-
626
- function sby_maybe_start_cron_clear_cache( $settings ) {
627
- $sby_doing_cron_clear = isset( $settings['cronclear'] ) ? $settings['cronclear'] : false;
628
-
629
- if ( $sby_doing_cron_clear ) {
630
- wp_clear_scheduled_hook( 'sby_cron_job' );
631
-
632
- wp_schedule_event( time(), 'hourly', 'sby_cron_job' );
633
- }
634
- }
635
- add_action( 'sby_settings_after_customize_save', 'sby_maybe_start_cron_clear_cache', 10, 1 );
636
-
637
- function sby_clear_wp_posts() {
638
-
639
- global $wpdb;
640
-
641
- $youtube_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type = '".SBY_CPT."';" );
642
-
643
- $id_string = implode( ', ', $youtube_ids );
644
- if ( ! empty( $id_string ) ) {
645
- $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE post_id IN ($id_string);" );
646
- $wpdb->query( "DELETE FROM $wpdb->posts WHERE post_type = '".SBY_CPT."';" );
647
- }
648
- }
649
-
650
- /** Notices */
651
-
652
- function sby_dismiss_at_warning_notice() {
653
-
654
- update_user_meta( get_current_user_id(), 'sby_at_warning_notice', time() );
655
-
656
- die();
657
- }
658
- add_action( 'wp_ajax_sby_dismiss_at_warning_notice', 'sby_dismiss_at_warning_notice' );
659
-
660
- function sby_dismiss_connect_warning_notice() {
661
-
662
- update_user_meta( get_current_user_id(), 'sby_connect_warning_notice', time() );
663
-
664
- die();
665
- }
666
- add_action( 'wp_ajax_sby_dismiss_connect_warning_button', 'sby_dismiss_connect_warning_notice' );
667
-
668
- function sby_notice_not_dismissed( $key = 'sby_at_warning_notice' ) {
669
- $meta = get_user_meta( get_current_user_id(), $key, true );
670
- return (int)$meta + DAY_IN_SECONDS < time();
671
- }
672
-
673
- function sby_access_token_warning_modal() {
674
- if ( isset( $_GET['page'] ) && $_GET['page'] === SBY_SLUG && isset( $_GET['sby_access_token'] ) && sby_notice_not_dismissed() ) {
675
- $text_domain = SBY_TEXT_DOMAIN;
676
- include trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates/modal.php';
677
- echo '<span class="sby_account_just_added"></span>';
678
- }
679
-
680
- }
681
- add_action( 'admin_footer', 'sby_access_token_warning_modal', 1 );
682
-
683
- function sby_get_current_time() {
684
- $current_time = time();
685
-
686
- // where to do tests
687
- //$current_time = strtotime( 'November 25, 2020' ) + 1;
688
-
689
- return $current_time;
690
- }
691
-
692
- // generates the html for the admin notices
693
- function sby_notices_html() {
694
-
695
- //delete_transient( 'instagram_feed_rating_notice_waiting' );
696
-
697
- //set_transient( 'instagram_feed_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
698
- //update_option( 'sby_rating_notice', 'pending', false );
699
-
700
-
701
- }
702
- //add_action( 'admin_notices', 'sby_notices_html', 12 ); // priority 8 for Instagram, priority 10 for Facebook
703
-
704
-
705
- function sby_lite_dismiss() {
706
- if ( ! isset( $_POST['sbspf_nonce'] ) ) return;
707
- $nonce = $_POST['sbspf_nonce'];
708
- if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
709
- die ( 'You did not do this the right way!' );
710
- }
711
-
712
- set_transient( 'youtube_feed_dismiss_lite', 'dismiss', 1 * WEEK_IN_SECONDS );
713
-
714
- die();
715
- }
716
- add_action( 'wp_ajax_sby_lite_dismiss', 'sby_lite_dismiss' );
717
-
718
- function sby_get_future_date( $month, $year, $week, $day, $direction ) {
719
- if ( $direction > 0 ) {
720
- $startday = 1;
721
- } else {
722
- $startday = date( 't', mktime(0, 0, 0, $month, 1, $year ) );
723
- }
724
-
725
- $start = mktime( 0, 0, 0, $month, $startday, $year );
726
- $weekday = date( 'N', $start );
727
-
728
- $offset = 0;
729
- if ( $direction * $day >= $direction * $weekday ) {
730
- $offset = -$direction * 7;
731
- }
732
-
733
- $offset += $direction * ($week * 7) + ($day - $weekday);
734
- return mktime( 0, 0, 0, $month, $startday + $offset, $year );
735
- }
736
-
737
- function sby_admin_hide_unrelated_notices() {
738
-
739
- // Bail if we're not on a Sby screen or page.
740
- if ( ! sby_is_admin_page() ) {
741
- return;
742
- }
743
-
744
- // Extra banned classes and callbacks from third-party plugins.
745
- $blacklist = array(
746
- 'classes' => array(),
747
- 'callbacks' => array(
748
- 'sbydb_admin_notice', // 'Database for Sby' plugin.
749
- ),
750
- );
751
-
752
- global $wp_filter;
753
-
754
- foreach ( array( 'user_admin_notices', 'admin_notices', 'all_admin_notices' ) as $notices_type ) {
755
- if ( empty( $wp_filter[ $notices_type ]->callbacks ) || ! is_array( $wp_filter[ $notices_type ]->callbacks ) ) {
756
- continue;
757
- }
758
- foreach ( $wp_filter[ $notices_type ]->callbacks as $priority => $hooks ) {
759
- foreach ( $hooks as $name => $arr ) {
760
- if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
761
- unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
762
- continue;
763
- }
764
- $class = ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) ? strtolower( get_class( $arr['function'][0] ) ) : '';
765
- if (
766
- ! empty( $class ) &&
767
- strpos( $class, 'sby' ) !== false &&
768
- ! in_array( $class, $blacklist['classes'], true )
769
- ) {
770
- continue;
771
- }
772
- if (
773
- ! empty( $name ) && (
774
- strpos( $name, 'sby' ) === false ||
775
- in_array( $class, $blacklist['classes'], true ) ||
776
- in_array( $name, $blacklist['callbacks'], true )
777
- )
778
- ) {
779
- unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
780
- }
781
- }
782
- }
783
- }
784
- }
785
  add_action( 'admin_print_scripts', 'sby_admin_hide_unrelated_notices' );
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ function sby_admin_init() {
7
+ global $sby_settings;
8
+
9
+ $base_path = trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates';
10
+ $slug = SBY_SLUG;
11
+ $plugin_name = SBY_PLUGIN_NAME;
12
+ $capability = current_user_can( 'manage_options' ) ? 'manage_options' : 'manage_youtube_feed_options';
13
+ $icon = 'dashicons-video-alt3';
14
+ $position = 99;
15
+ $tabs = array(
16
+ array(
17
+ 'title' => __( 'Configure', SBY_TEXT_DOMAIN ),
18
+ 'slug' => 'configure',
19
+ 'capability' => $capability,
20
+ 'next_step_instructions' => __( 'Customize your feed', SBY_TEXT_DOMAIN )
21
+ ),
22
+ array(
23
+ 'title' => __( 'Customize', SBY_TEXT_DOMAIN ),
24
+ 'slug' => 'customize',
25
+ 'capability' => $capability,
26
+ 'next_step_instructions' => __( 'Display your feed', SBY_TEXT_DOMAIN )
27
+ ),
28
+ array(
29
+ 'title' => __( 'Display', SBY_TEXT_DOMAIN ),
30
+ 'slug' => 'display',
31
+ 'capability' => $capability
32
+ ),
33
+ array(
34
+ 'title' => __( 'Support', SBY_TEXT_DOMAIN ),
35
+ 'slug' => 'support',
36
+ 'capability' => $capability,
37
+ 'numbered_tab' => false
38
+ ),
39
+ array(
40
+ 'title' => __( 'All Feeds', SBY_TEXT_DOMAIN ),
41
+ 'slug' => 'allfeeds',
42
+ 'capability' => $capability,
43
+ 'numbered_tab' => false,
44
+ 'has_nav_tab' => false
45
+ )
46
+ );
47
+
48
+ $active_tab = $tabs[0]['slug'];
49
+ if ( isset( $_GET['tab'] ) ) {
50
+ $active_tab = sanitize_text_field( $_GET['tab'] ); $tabs[0]['slug'];
51
+ } elseif ( isset( $_GET['page'] ) ) {
52
+ foreach ( $tabs as $tab ) {
53
+ if ( $_GET['page'] === $slug . '_' . $tab['slug'] ) {
54
+ $active_tab = $tab['slug'];
55
+ }
56
+ }
57
+ }
58
+ $vars = new SBY_Vars();
59
+ $admin = new SBY_Admin( $vars, $base_path, $slug, $plugin_name, $capability, $icon, $position, $tabs, $sby_settings, $active_tab, 'sby_settings' );
60
+ $admin->access_token_listener();
61
+
62
+ $first_connected = sby_get_first_connected_account();
63
+ $first_channel_id = isset( $first_connected['channel_id'] ) ? $first_connected['channel_id'] : '';
64
+
65
+ $types = array(
66
+ array(
67
+ 'slug' => 'channel',
68
+ 'label' => __( 'Channel', SBY_TEXT_DOMAIN ),
69
+ 'input_type' => 'text',
70
+ 'default' => $first_channel_id,
71
+ 'note' => __( 'Eg: Channel ID or User Name', SBY_TEXT_DOMAIN ),
72
+ 'example' => 'smashballoon',
73
+ 'description' => __( 'Display videos from a YouTube channel (channel)', SBY_TEXT_DOMAIN ),
74
+ 'tooltip' => '<p>' . __( 'Enter any channel ID or user name to display all of an accounts latest videos starting with the most recently published.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
75
+ <li><b>' . __( 'Channel ID or User Name', SBY_TEXT_DOMAIN ).'</b><br>
76
+ ' . __( 'You can find the ID or User Name of your YouTube Channel from the URL. In each URL format, the text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
77
+ ' . __( 'URL Format 1:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/channel/<span class="sbspf-highlight">UC1a2b3c4D5F6g7i8j9k</span></code>
78
+ <br>
79
+ ' . __( 'URL Format 2:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/user/<span class="sbspf-highlight">your_user_name</span></code>
80
+ </li>
81
+ </ul></p>'
82
+ ),
83
+ array(
84
+ 'slug' => 'playlist',
85
+ 'label' => __( 'Playlist', SBY_TEXT_DOMAIN ),
86
+ 'input_type' => 'text',
87
+ 'default' => '',
88
+ 'pro' => true,
89
+ 'note' => __( 'Eg: Playlist ID', SBY_TEXT_DOMAIN ),
90
+ 'example' => 'PLLLm1a2b3c4D6g7i8j9k_1a',
91
+ 'description' => __( 'Display videos from a specific playlist (playlist)', SBY_TEXT_DOMAIN ),
92
+ 'tooltip' => '<p>' . __( 'Enter any playlist ID to display videos from a playlist starting with the most recently published.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
93
+ <li><b>' . __( 'Playlist ID', SBY_TEXT_DOMAIN ).'</b><br>
94
+ ' . __( 'You can find the ID of your YouTube playlist from the URL. The text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
95
+ <code>https://www.youtube.com/playlist?list=<span class="sbspf-highlight">PLLLm1a2b3c4D6g7i8j9k_1a2b3c4D57i8j9k</span></code>
96
+ </li>
97
+ </ul></p>'
98
+ ),
99
+ array(
100
+ 'slug' => 'favorites',
101
+ 'label' => __( 'Favorites', SBY_TEXT_DOMAIN ),
102
+ 'input_type' => 'text',
103
+ 'default' => '',
104
+ 'pro' => true,
105
+ 'note' => __( 'Eg: Channel ID or User Name', SBY_TEXT_DOMAIN ),
106
+ 'example' => 'smashballoon',
107
+ 'description' => __( 'Display the "favorites" playlist for a channel (favorites)', SBY_TEXT_DOMAIN ),
108
+ 'tooltip' => '<p>' . __( 'Displays all videos marked as "favorites" by a YouTube account starting with the most recently published.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
109
+ <li><b>' . __( 'Channel ID or User Name', SBY_TEXT_DOMAIN ).'</b><br>
110
+ ' . __( 'You can find the ID or User Name of your YouTube Channel from the URL. In each URL format, the text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
111
+ ' . __( 'URL Format 1:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/channel/<span class="sbspf-highlight">UC1a2b3c4D5F6g7i8j9k</span></code>
112
+ <br>
113
+ ' . __( 'URL Format 2:', SBY_TEXT_DOMAIN ).' <code>https://www.youtube.com/user/<span class="sbspf-highlight">your_user_name</span></code>
114
+ </li>
115
+ </ul></p>'
116
+ ),
117
+ array(
118
+ 'slug' => 'search',
119
+ 'label' => __( 'Search', SBY_TEXT_DOMAIN ),
120
+ 'input_type' => 'text',
121
+ 'default' => '',
122
+ 'pro' => true,
123
+ 'note' => __( 'Eg: Search Term', SBY_TEXT_DOMAIN ),
124
+ 'example' => 'cats',
125
+ 'description' => __( 'Display a feed of matching search results (search)', SBY_TEXT_DOMAIN ),
126
+ 'tooltip' => '<p>' . __( 'Enter any search term or phrase. Separate multiple terms with commas. You can add your own additional query vars using the <a href="https://smashballoon.com/youtube-feed/custom-search-guide/" target="_blank" rel="noopener">guide on our website</a> and the input field above.', SBY_TEXT_DOMAIN ) . '</p>',
127
+ ),
128
+ array(
129
+ 'slug' => 'live',
130
+ 'label' => __( 'Live Streams', SBY_TEXT_DOMAIN ),
131
+ 'input_type' => 'text',
132
+ 'default' => '',
133
+ 'pro' => true,
134
+ 'note' => __( 'Eg: Channel ID', SBY_TEXT_DOMAIN ),
135
+ 'example' => 'UC1a2b3c4D5F6g7i8j9k',
136
+ 'description' => __( 'Display upcoming and currently playing live streams (live)', SBY_TEXT_DOMAIN ),
137
+ 'tooltip' => '<p>' . __( 'Displays upcoming and currently playing live streaming videos sorted by soonest scheduled broadcast.', SBY_TEXT_DOMAIN ) . '</p><p><ul>
138
+ <li><b>' . __( 'Channel ID', SBY_TEXT_DOMAIN ).'</b><br>
139
+ ' . __( 'You can find the ID of your YouTube Channel from the URL. The text you need to use is highlighted below:', SBY_TEXT_DOMAIN ).'<br><br>
140
+ <code>https://www.youtube.com/channel/<span class="sbspf-highlight">UC1a2b3c4D5F6g7i8j9k</span></code>
141
+ </li>
142
+ </ul></p>'
143
+ )
144
+ );
145
+ $admin->set_feed_types( $types );
146
+
147
+ $text_domain = SBY_TEXT_DOMAIN;
148
+ /* Layout */
149
+ $layouts = array(
150
+ array(
151
+ 'slug' => 'grid',
152
+ 'label' => __( 'Grid', $text_domain ),
153
+ 'image' => 'img/grid.png',
154
+ 'note' => __( 'Video thumbnails are displayed in columns and play in a lightbox when clicked.', $text_domain ),
155
+ 'options' => array(
156
+ array(
157
+ 'name' => 'cols',
158
+ 'callback' => 'select',
159
+ 'label' => __( 'Columns', $text_domain ),
160
+ 'min' => 1,
161
+ 'max' => 7,
162
+ 'default' => 3,
163
+ 'shortcode' => array(
164
+ 'example' => '3',
165
+ 'description' => __( 'Videos in carousel when 480px screen width or less.', $text_domain ),
166
+ )
167
+ ),
168
+ array(
169
+ 'name' => 'colsmobile',
170
+ 'callback' => 'select',
171
+ 'label' => __( 'Mobile Columns', $text_domain ),
172
+ 'min' => 1,
173
+ 'max' => 2,
174
+ 'default' => 2,
175
+ 'shortcode' => array(
176
+ 'example' => '2',
177
+ 'description' => __( 'Columns when 480px screen width or less.', $text_domain ),
178
+ )
179
+ ),
180
+ )
181
+ ),
182
+ array(
183
+ 'slug' => 'gallery',
184
+ 'label' => __( 'Gallery', $text_domain ),
185
+ 'image' => 'img/gallery.png',
186
+ 'note' => __( 'One large video that plays when clicked with thumbnails underneath to play more.', $text_domain ),
187
+ 'options' => array(
188
+ array(
189
+ 'name' => 'cols',
190
+ 'callback' => 'select',
191
+ 'label' => __( 'Columns', $text_domain ),
192
+ 'min' => 1,
193
+ 'max' => 7,
194
+ 'default' => 3,
195
+ 'shortcode' => array(
196
+ 'example' => '3',
197
+ 'description' => __( 'Videos in carousel when 480px screen width or less.', $text_domain ),
198
+ )
199
+ ),
200
+ array(
201
+ 'name' => 'colsmobile',
202
+ 'callback' => 'select',
203
+ 'label' => __( 'Mobile Columns', $text_domain ),
204
+ 'min' => 1,
205
+ 'max' => 2,
206
+ 'default' => 2,
207
+ 'shortcode' => array(
208
+ 'example' => '2',
209
+ 'description' => __( 'Columns when 480px screen width or less.', $text_domain ),
210
+ )
211
+ ),
212
+ )
213
+ ),
214
+ array(
215
+ 'slug' => 'list',
216
+ 'label' => __( 'List', $text_domain ),
217
+ 'image' => 'img/list.png',
218
+ 'note' => __( 'A single columns of videos that play when clicked.', $text_domain ),
219
+ ),
220
+ array(
221
+ 'slug' => 'carousel',
222
+ 'label' => __( 'Carousel', $text_domain ),
223
+ 'image' => 'img/carousel.png',
224
+ 'note' => __( 'Posts are displayed in a slideshow carousel.', $text_domain ),
225
+ 'pro' => true,
226
+ 'options' => array(
227
+ array(
228
+ 'name' => 'cols',
229
+ 'callback' => 'select',
230
+ 'label' => __( 'Columns', $text_domain ),
231
+ 'min' => 1,
232
+ 'max' => 7,
233
+ 'default' => 3,
234
+ 'shortcode' => array(
235
+ 'example' => '3',
236
+ 'description' => __( 'Videos in carousel when 480px screen width or less.', $text_domain ),
237
+ )
238
+ ),
239
+ array(
240
+ 'name' => 'colsmobile',
241
+ 'callback' => 'select',
242
+ 'label' => __( 'Mobile Columns', $text_domain ),
243
+ 'min' => 1,
244
+ 'max' => 2,
245
+ 'default' => 2,
246
+ 'shortcode' => array(
247
+ 'example' => '2',
248
+ 'description' => __( 'Columns when 480px screen width or less.', $text_domain ),
249
+ ) ),
250
+ array(
251
+ 'name' => 'rows',
252
+ 'callback' => 'select',
253
+ 'label' => __( 'Number of Rows', $text_domain ),
254
+ 'min' => 1,
255
+ 'max' => 2,
256
+ 'default' => 1,
257
+ 'shortcode' => array(
258
+ 'example' => '2',
259
+ 'description' => __( 'Choose 2 rows to show two posts in a single slide.', $text_domain ),
260
+ )
261
+ ),
262
+ array(
263
+ 'name' => 'loop',
264
+ 'callback' => 'select',
265
+ 'label' => __( 'Loop Type', $text_domain ),
266
+ 'options' => array(
267
+ array(
268
+ 'label' => __( 'Rewind', $text_domain ),
269
+ 'value' => 'rewind'
270
+ ),
271
+ array(
272
+ 'label' => __( 'Infinity', $text_domain ),
273
+ 'value' => 'infinity'
274
+ )
275
+ ),
276
+ 'default' => 'rewind',
277
+ 'shortcode' => array(
278
+ 'example' => 'infinity',
279
+ 'description' => __( 'What happens when the last slide is reached.', $text_domain ),
280
+ )
281
+ ),
282
+ array(
283
+ 'name' => 'arrows',
284
+ 'callback' => 'checkbox',
285
+ 'label' => __( 'Show Navigation Arrows', $text_domain ),
286
+ 'default' => true,
287
+ 'shortcode' => array(
288
+ 'example' => 'false',
289
+ 'description' => __( 'Show arrows on the sides to navigate posts.', $text_domain ),
290
+ )
291
+ ),
292
+ array(
293
+ 'name' => 'pag',
294
+ 'callback' => 'checkbox',
295
+ 'label' => __( 'Show Pagination', $text_domain ),
296
+ 'default' => true,
297
+ 'shortcode' => array(
298
+ 'example' => 'false',
299
+ 'description' => __( 'Show dots below carousel for an ordinal indication of which slide is being shown.', $text_domain ),
300
+ )
301
+ ),
302
+ array(
303
+ 'name' => 'autoplay',
304
+ 'callback' => 'checkbox',
305
+ 'label' => __( 'Enable Autoplay', $text_domain ),
306
+ 'default' => false,
307
+ 'shortcode' => array(
308
+ 'example' => 'true',
309
+ 'description' => __( 'Whether or not to change slides automatically on an interval.', $text_domain ),
310
+ )
311
+ ),
312
+ array(
313
+ 'name' => 'time',
314
+ 'callback' => 'text',
315
+ 'label' => __( 'Interval Time', $text_domain ),
316
+ 'default' => 5000,
317
+ 'shortcode' => array(
318
+ 'example' => '3000',
319
+ 'description' => __( 'Duration in milliseconds before the slide changes.', $text_domain ),
320
+ )
321
+ ),
322
+ )
323
+ ),
324
+
325
+ );
326
+ $admin->set_feed_layouts( $layouts );
327
+
328
+ $display_your_feed_table_headings = array(
329
+ array(
330
+ 'slug' => 'configure',
331
+ 'label' => __( 'Configure Options', SBY_TEXT_DOMAIN ),
332
+ ),
333
+ array(
334
+ 'slug' => 'customize',
335
+ 'label' => __( 'Customize Options', SBY_TEXT_DOMAIN ),
336
+ ),
337
+ array(
338
+ 'slug' => 'layout',
339
+ 'label' => __( 'Layout Options', SBY_TEXT_DOMAIN ),
340
+ ),
341
+ array(
342
+ 'slug' => 'experience',
343
+ 'label' => __( 'Video Experience Options', SBY_TEXT_DOMAIN ),
344
+ ),
345
+ array(
346
+ 'slug' => 'header',
347
+ 'label' => __( 'Header Options', SBY_TEXT_DOMAIN ),
348
+ ),
349
+ array(
350
+ 'slug' => 'button',
351
+ 'label' => __( '"Load More" Button Options', SBY_TEXT_DOMAIN ),
352
+ ),
353
+ array(
354
+ 'slug' => 'subscribe',
355
+ 'label' => __( '"Subscribe" Button Options', SBY_TEXT_DOMAIN ),
356
+ )
357
+ );
358
+ $admin->set_display_table_sections( $display_your_feed_table_headings );
359
+
360
+ $admin->init();
361
+ }
362
+
363
+ function sby_admin_style() {
364
+ wp_enqueue_style( SBY_SLUG . '_admin_notices_css', SBY_PLUGIN_URL . 'css/sby-notices.css', array(), SBYVER );
365
+ if ( ! sby_is_admin_page() ) {
366
+ return;
367
+ }
368
+ wp_enqueue_style( SBY_SLUG . '_admin_css', SBY_PLUGIN_URL . 'css/admin.css', array(), SBYVER );
369
+ wp_enqueue_style( 'sb_font_awesome', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' );
370
+ wp_enqueue_style( 'wp-color-picker' );
371
+ }
372
+ add_action( 'admin_enqueue_scripts', 'sby_admin_style' );
373
+
374
+ function sby_admin_scripts() {
375
+ if ( ! sby_is_admin_page() ) {
376
+ return;
377
+ }
378
+ wp_enqueue_script( SBY_SLUG . '_admin_js', SBY_PLUGIN_URL . 'js/admin.js', array(), SBYVER );
379
+ wp_localize_script( SBY_SLUG . '_admin_js', 'sbspf', array(
380
+ 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
381
+ 'nonce' => wp_create_nonce( 'sbspf_nonce' )
382
+ )
383
+ );
384
+ wp_enqueue_script('wp-color-picker' );
385
+ }
386
+ add_action( 'admin_enqueue_scripts', 'sby_admin_scripts' );
387
+
388
+ function sby_is_admin_page() {
389
+ if ( ! isset( $_GET['page'] ) ) {
390
+ return false;
391
+ } elseif ( strpos( sanitize_text_field( $_GET['page'] ), SBY_SLUG ) !== false ) {
392
+ return true;
393
+ }
394
+ return false;
395
+ }
396
+
397
+ function sby_admin_icon( $icon, $class = '' ) {
398
+ $class = ! empty( $class ) ? ' ' . $class : '';
399
+ if ( $icon === 'question-circle' ) {
400
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="question-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-question-circle fa-w-16'.$class.'"><path fill="currentColor" d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z" class=""></path></svg>';
401
+ } elseif ( $icon === 'info-circle' ) {
402
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="info-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-info-circle fa-w-16'.$class.'"><path fill="currentColor" d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z" class=""></path></svg>';
403
+ } elseif ( $icon === 'life-ring' ) {
404
+ return '<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="life-ring" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-life-ring fa-w-16'.$class.'"><path fill="currentColor" d="M256 504c136.967 0 248-111.033 248-248S392.967 8 256 8 8 119.033 8 256s111.033 248 248 248zm-103.398-76.72l53.411-53.411c31.806 13.506 68.128 13.522 99.974 0l53.411 53.411c-63.217 38.319-143.579 38.319-206.796 0zM336 256c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zm91.28 103.398l-53.411-53.411c13.505-31.806 13.522-68.128 0-99.974l53.411-53.411c38.319 63.217 38.319 143.579 0 206.796zM359.397 84.72l-53.411 53.411c-31.806-13.505-68.128-13.522-99.973 0L152.602 84.72c63.217-38.319 143.579-38.319 206.795 0zM84.72 152.602l53.411 53.411c-13.506 31.806-13.522 68.128 0 99.974L84.72 359.398c-38.319-63.217-38.319-143.579 0-206.796z" class=""></path></svg>';
405
+ } elseif ( $icon === 'envelope' ) {
406
+ return '<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="envelope" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-envelope fa-w-16'.$class.'"><path fill="currentColor" d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm0 48v40.805c-22.422 18.259-58.168 46.651-134.587 106.49-16.841 13.247-50.201 45.072-73.413 44.701-23.208.375-56.579-31.459-73.413-44.701C106.18 199.465 70.425 171.067 48 152.805V112h416zM48 400V214.398c22.914 18.251 55.409 43.862 104.938 82.646 21.857 17.205 60.134 55.186 103.062 54.955 42.717.231 80.509-37.199 103.053-54.947 49.528-38.783 82.032-64.401 104.947-82.653V400H48z" class=""></path></svg>';
407
+ } elseif ( $icon === 'chevron-right' ) {
408
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-circle-right" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-chevron-circle-right fa-w-16'.$class.'"><path fill="currentColor" d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z" class=""></path></svg>';
409
+ } elseif ( $icon === 'rocket' ) {
410
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="rocket" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-rocket fa-w-16'.$class.'"><path fill="currentColor" d="M505.05 19.1a15.89 15.89 0 0 0-12.2-12.2C460.65 0 435.46 0 410.36 0c-103.2 0-165.1 55.2-211.29 128H94.87A48 48 0 0 0 52 154.49l-49.42 98.8A24 24 0 0 0 24.07 288h103.77l-22.47 22.47a32 32 0 0 0 0 45.25l50.9 50.91a32 32 0 0 0 45.26 0L224 384.16V488a24 24 0 0 0 34.7 21.49l98.7-49.39a47.91 47.91 0 0 0 26.5-42.9V312.79c72.59-46.3 128-108.4 128-211.09.1-25.2.1-50.4-6.85-82.6zM384 168a40 40 0 1 1 40-40 40 40 0 0 1-40 40z" class=""></path></svg>';
411
+ } elseif ( $icon === 'minus-circle' ) {
412
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="minus-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-minus-circle fa-w-16'.$class.'"><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z" class=""></path></svg>';
413
+ } elseif ( $icon === 'times' ) {
414
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512" class="svg-inline--fa fa-times fa-w-11'.$class.'"><path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" class=""></path></svg>';
415
+ } elseif ( $icon === 'cog' ) {
416
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="cog" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-cog fa-w-16'.$class.'"><path fill="currentColor" d="M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z" class=""></path></svg>';
417
+ } elseif ( $icon === 'ellipsis' ) {
418
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="ellipsis-h" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-ellipsis-h fa-w-16'.$class.'"><path fill="currentColor" d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z" class=""></path></svg>';
419
+ } else {
420
+ sby_icon( $icon );
421
+ }
422
+ }
423
+
424
+ function sby_delete_connected_account() {
425
+ if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['account_id']) ) return;
426
+ $nonce = $_POST['sbspf_nonce'];
427
+ if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
428
+ die ( 'You did not do this the right way!' );
429
+ }
430
+
431
+ global $sby_settings;
432
+
433
+ $account_id = sanitize_text_field( $_POST['account_id'] );
434
+ $to_save = array();
435
+
436
+ foreach ( $sby_settings['connected_accounts'] as $connected_account ) {
437
+ if ( (string)$connected_account['channel_id'] !== (string)$account_id ) {
438
+ $to_save[ $connected_account['channel_id'] ] = $connected_account;
439
+ }
440
+ }
441
+
442
+ $sby_settings['connected_accounts'] = $to_save;
443
+ update_option( 'sby_settings', $sby_settings );
444
+
445
+ echo wp_json_encode( array( 'success' => true ) );
446
+
447
+ die();
448
+ }
449
+ add_action( 'wp_ajax_sby_ca_after_remove_clicked', 'sby_delete_connected_account' );
450
+
451
+ function sby_process_access_token() {
452
+ if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['sby_access_token'] ) ) return;
453
+ $nonce = $_POST['sbspf_nonce'];
454
+ if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
455
+ die ( 'You did not do this the right way!' );
456
+ }
457
+
458
+ $account = sby_attempt_connection();
459
+
460
+ if ( $account ) {
461
+ global $sby_settings;
462
+
463
+ $options = $sby_settings;
464
+ $username = $account['username'] ? $account['username'] : $account['channel_id'];
465
+ if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['favorlocal'] ) && $options['favorlocal' ] === 'on' ) {
466
+ $upload = wp_upload_dir();
467
+ $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBY_UPLOADS_NAME );
468
+ $profile_picture = '<img class="sbspf_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
469
+ } else {
470
+ $profile_picture = $account['profile_picture'] ? '<img class="sbspf_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
471
+ }
472
+
473
+ $text_domain = SBY_TEXT_DOMAIN;
474
+ $slug = SBY_SLUG;
475
+ ob_start();
476
+ include trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates/single-connected-account.php';
477
+ if ( sby_notice_not_dismissed() ) {
478
+ include trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates/modal.php';
479
+ echo '<span class="sby_account_just_added"></span>';
480
+ }
481
+
482
+ $html = ob_get_contents();
483
+ ob_get_clean();
484
+
485
+ $return = array(
486
+ 'account_id' => $account['channel_id'],
487
+ 'html' => $html
488
+ );
489
+ } else {
490
+ $return = array(
491
+ 'error' => __( 'Could not connect your account. Please check to make sure this is a valid access token for the Smash Balloon YouTube App.'),
492
+ 'html' => ''
493
+ );
494
+ }
495
+
496
+ echo wp_json_encode( $return );
497
+
498
+ die();
499
+ }
500
+ add_action( 'wp_ajax_sby_process_access_token', 'sby_process_access_token' );
501
+
502
+ function sby_delete_wp_posts() {
503
+ if ( ! isset( $_POST['sbspf_nonce'] ) ) return;
504
+ $nonce = $_POST['sbspf_nonce'];
505
+ if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
506
+ die ( 'You did not do this the right way!' );
507
+ }
508
+
509
+ sby_clear_wp_posts();
510
+
511
+ echo '{}';
512
+
513
+ die();
514
+ }
515
+ add_action( 'wp_ajax_sby_delete_wp_posts', 'sby_delete_wp_posts' );
516
+
517
+ function sby_attempt_connection() {
518
+ if ( ! current_user_can( 'manage_youtube_feed_options' ) ) {
519
+ return false;
520
+ }
521
+ if ( isset( $_GET['sby_access_token'] ) ) {
522
+ $access_token = sanitize_text_field( urldecode( $_GET['sby_access_token'] ) );
523
+ $refresh_token = '';
524
+ } else {
525
+ $access_token = sanitize_text_field( $_POST['sby_access_token'] );
526
+ $refresh_token = '';
527
+ }
528
+
529
+ $account_info = array(
530
+ 'access_token' => $access_token,
531
+ 'refresh_token' => $refresh_token
532
+ );
533
+ $sby_api_connect = new SBY_API_Connect( $account_info, 'tokeninfo' );
534
+ $sby_api_connect->connect();
535
+
536
+ $data = $sby_api_connect->get_data();
537
+
538
+ if ( isset( $data['audience'] ) ) {
539
+ $expires = $data['expires_in'] + time();
540
+ $sby_api_connect = new SBY_API_Connect( $account_info, 'channels' );
541
+ $sby_api_connect->connect();
542
+ $data = $sby_api_connect->get_data();
543
+
544
+ if ( isset( $data['items'] ) ) {
545
+ $account_info['username'] = $data['items'][0]['snippet']['title'];
546
+ $account_info['channel_id'] = $data['items'][0]['id'];
547
+ $account_info['profile_picture'] = $data['items'][0]['snippet']['thumbnails']['default']['url'];
548
+ $account_info['privacy'] = '';
549
+ $account_info['expires'] = $expires;
550
+ //privacyStatus
551
+ SBY_Admin::connect_account( $account_info );
552
+
553
+ return $account_info;
554
+ } else {
555
+ $account_info['username'] = '(No Channel)';
556
+ $account_info['channel_id'] = '';
557
+ $account_info['profile_picture'] = '';
558
+ $account_info['privacy'] = '';
559
+ $account_info['expires'] = $expires;
560
+ //privacyStatus
561
+ SBY_Admin::connect_account( $account_info );
562
+
563
+ return $account_info;
564
+ }
565
+ }
566
+ return false;
567
+ }
568
+
569
+ function sbspf_account_search() {
570
+ if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['term']) ) return;
571
+ $nonce = $_POST['sbspf_nonce'];
572
+ if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
573
+ die ( 'You did not do this the right way!' );
574
+ }
575
+
576
+ global $sby_settings;
577
+
578
+ $term = sanitize_text_field( $_POST['term'] );
579
+ $params = array(
580
+ 'q' => $term,
581
+ 'type' => 'channel'
582
+ );
583
+
584
+ $connected_account_for_term = array();
585
+ foreach ( $sby_settings['connected_accounts'] as $connected_account ) {
586
+ $connected_account_for_term = $connected_account;
587
+ }
588
+ if ( $connected_account_for_term['expires'] < time() + 5 ) {
589
+ $new_token_data = SBY_API_Connect::refresh_token( sby_get_account_bottom(), $connected_account_for_term['refresh_token'], sby_get_account_top() );
590
+
591
+ if ( isset( $new_token_data['access_token'] ) ) {
592
+ $connected_account_for_term['access_token'] = $new_token_data['access_token'];
593
+ $connected_accounts_for_feed[ $term ]['access_token'] = $new_token_data['access_token'];
594
+ $connected_account_for_term['expires'] = $new_token_data['expires_in'] + time();
595
+ $connected_accounts_for_feed[ $term ]['expires'] = $new_token_data['expires_in'] + time();
596
+
597
+ sby_update_or_connect_account( $connected_account_for_term );
598
+
599
+ }
600
+ }
601
+
602
+ $search = new SBY_API_Connect( $connected_account_for_term, 'search', $params );
603
+
604
+ $search->connect();
605
+
606
+
607
+ echo wp_json_encode( $search->get_data() );
608
+
609
+ die();
610
+ }
611
+ add_action( 'wp_ajax_sbspf_account_search', 'sbspf_account_search' );
612
+
613
+ function sby_reset_cron( $settings ) {
614
+ $sbi_caching_type = isset( $settings['caching_type'] ) ? $settings['caching_type'] : '';
615
+ $sbi_cache_cron_interval = isset( $settings['cache_cron_interval'] ) ? $settings['cache_cron_interval'] : '';
616
+ $sbi_cache_cron_time = isset( $settings['cache_cron_time'] ) ? $settings['cache_cron_time'] : '';
617
+ $sbi_cache_cron_am_pm = isset( $settings['cache_cron_am_pm'] ) ? $settings['cache_cron_am_pm'] : '';
618
+
619
+ if ( $sbi_caching_type === 'background' ) {
620
+ delete_option( 'sby_cron_report' );
621
+ SBY_Cron_Updater::start_cron_job( $sbi_cache_cron_interval, $sbi_cache_cron_time, $sbi_cache_cron_am_pm );
622
+ }
623
+ }
624
+ add_action( 'sby_settings_after_configure_save', 'sby_reset_cron', 10, 1 );
625
+
626
+ function sby_maybe_start_cron_clear_cache( $settings ) {
627
+ $sby_doing_cron_clear = isset( $settings['cronclear'] ) ? $settings['cronclear'] : false;
628
+
629
+ if ( $sby_doing_cron_clear ) {
630
+ wp_clear_scheduled_hook( 'sby_cron_job' );
631
+
632
+ wp_schedule_event( time(), 'hourly', 'sby_cron_job' );
633
+ }
634
+ }
635
+ add_action( 'sby_settings_after_customize_save', 'sby_maybe_start_cron_clear_cache', 10, 1 );
636
+
637
+ function sby_clear_wp_posts() {
638
+
639
+ global $wpdb;
640
+
641
+ $youtube_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type = '".SBY_CPT."';" );
642
+
643
+ $id_string = implode( ', ', $youtube_ids );
644
+ if ( ! empty( $id_string ) ) {
645
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE post_id IN ($id_string);" );
646
+ $wpdb->query( "DELETE FROM $wpdb->posts WHERE post_type = '".SBY_CPT."';" );
647
+ }
648
+ }
649
+
650
+ /** Notices */
651
+
652
+ function sby_dismiss_at_warning_notice() {
653
+
654
+ update_user_meta( get_current_user_id(), 'sby_at_warning_notice', time() );
655
+
656
+ die();
657
+ }
658
+ add_action( 'wp_ajax_sby_dismiss_at_warning_notice', 'sby_dismiss_at_warning_notice' );
659
+
660
+ function sby_dismiss_connect_warning_notice() {
661
+
662
+ update_user_meta( get_current_user_id(), 'sby_connect_warning_notice', time() );
663
+
664
+ die();
665
+ }
666
+ add_action( 'wp_ajax_sby_dismiss_connect_warning_button', 'sby_dismiss_connect_warning_notice' );
667
+
668
+ function sby_notice_not_dismissed( $key = 'sby_at_warning_notice' ) {
669
+ $meta = get_user_meta( get_current_user_id(), $key, true );
670
+ return (int)$meta + DAY_IN_SECONDS < time();
671
+ }
672
+
673
+ function sby_access_token_warning_modal() {
674
+ if ( isset( $_GET['page'] ) && $_GET['page'] === SBY_SLUG && isset( $_GET['sby_access_token'] ) && sby_notice_not_dismissed() ) {
675
+ $text_domain = SBY_TEXT_DOMAIN;
676
+ include trailingslashit( SBY_PLUGIN_DIR ) . 'inc/admin/templates/modal.php';
677
+ echo '<span class="sby_account_just_added"></span>';
678
+ }
679
+
680
+ }
681
+ add_action( 'admin_footer', 'sby_access_token_warning_modal', 1 );
682
+
683
+ function sby_get_current_time() {
684
+ $current_time = time();
685
+
686
+ // where to do tests
687
+ //$current_time = strtotime( 'November 25, 2020' ) + 1;
688
+
689
+ return $current_time;
690
+ }
691
+
692
+ // generates the html for the admin notices
693
+ function sby_notices_html() {
694
+
695
+ //delete_transient( 'instagram_feed_rating_notice_waiting' );
696
+
697
+ //set_transient( 'instagram_feed_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
698
+ //update_option( 'sby_rating_notice', 'pending', false );
699
+
700
+
701
+ }
702
+ //add_action( 'admin_notices', 'sby_notices_html', 12 ); // priority 8 for Instagram, priority 10 for Facebook
703
+
704
+
705
+ function sby_lite_dismiss() {
706
+ if ( ! isset( $_POST['sbspf_nonce'] ) ) return;
707
+ $nonce = $_POST['sbspf_nonce'];
708
+ if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
709
+ die ( 'You did not do this the right way!' );
710
+ }
711
+
712
+ set_transient( 'youtube_feed_dismiss_lite', 'dismiss', 1 * WEEK_IN_SECONDS );
713
+
714
+ die();
715
+ }
716
+ add_action( 'wp_ajax_sby_lite_dismiss', 'sby_lite_dismiss' );
717
+
718
+ function sby_get_future_date( $month, $year, $week, $day, $direction ) {
719
+ if ( $direction > 0 ) {
720
+ $startday = 1;
721
+ } else {
722
+ $startday = date( 't', mktime(0, 0, 0, $month, 1, $year ) );
723
+ }
724
+
725
+ $start = mktime( 0, 0, 0, $month, $startday, $year );
726
+ $weekday = date( 'N', $start );
727
+
728
+ $offset = 0;
729
+ if ( $direction * $day >= $direction * $weekday ) {
730
+ $offset = -$direction * 7;
731
+ }
732
+
733
+ $offset += $direction * ($week * 7) + ($day - $weekday);
734
+ return mktime( 0, 0, 0, $month, $startday + $offset, $year );
735
+ }
736
+
737
+ function sby_admin_hide_unrelated_notices() {
738
+
739
+ // Bail if we're not on a Sby screen or page.
740
+ if ( ! sby_is_admin_page() ) {
741
+ return;
742
+ }
743
+
744
+ // Extra banned classes and callbacks from third-party plugins.
745
+ $blacklist = array(
746
+ 'classes' => array(),
747
+ 'callbacks' => array(
748
+ 'sbydb_admin_notice', // 'Database for Sby' plugin.
749
+ ),
750
+ );
751
+
752
+ global $wp_filter;
753
+
754
+ foreach ( array( 'user_admin_notices', 'admin_notices', 'all_admin_notices' ) as $notices_type ) {
755
+ if ( empty( $wp_filter[ $notices_type ]->callbacks ) || ! is_array( $wp_filter[ $notices_type ]->callbacks ) ) {
756
+ continue;
757
+ }
758
+ foreach ( $wp_filter[ $notices_type ]->callbacks as $priority => $hooks ) {
759
+ foreach ( $hooks as $name => $arr ) {
760
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
761
+ unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
762
+ continue;
763
+ }
764
+ $class = ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) ? strtolower( get_class( $arr['function'][0] ) ) : '';
765
+ if (
766
+ ! empty( $class ) &&
767
+ strpos( $class, 'sby' ) !== false &&
768
+ ! in_array( $class, $blacklist['classes'], true )
769
+ ) {
770
+ continue;
771
+ }
772
+ if (
773
+ ! empty( $name ) && (
774
+ strpos( $name, 'sby' ) === false ||
775
+ in_array( $class, $blacklist['classes'], true ) ||
776
+ in_array( $name, $blacklist['callbacks'], true )
777
+ )
778
+ ) {
779
+ unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
780
+ }
781
+ }
782
+ }
783
+ }
784
+ }
785
  add_action( 'admin_print_scripts', 'sby_admin_hide_unrelated_notices' );
inc/admin/class-sbspf-admin.php CHANGED
@@ -1,1050 +1,1050 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SB_YOUTUBE_Admin {
7
-
8
- protected $vars;
9
-
10
- protected $base_path;
11
-
12
- protected $slug;
13
-
14
- protected $plugin_name;
15
-
16
- protected $capability;
17
-
18
- protected $tabs;
19
-
20
- protected $active_tab;
21
-
22
- protected $settings_sections;
23
-
24
- protected $display_your_feed_sections;
25
-
26
- protected $option_name;
27
-
28
- protected $pro_only;
29
-
30
- protected $types;
31
-
32
- protected $layouts;
33
-
34
- protected $false_fields;
35
-
36
- protected $textarea_fields;
37
-
38
- public function __construct( $vars, $base_path, $slug, $plugin_name, $capability, $icon, $position, $tabs, $settings, $active_tab = false, $option_name = 'sbspf_settings' ) {
39
- $this->vars = $vars;
40
- $this->base_path = $base_path;
41
- $this->slug = $slug;
42
- $this->plugin_name = $plugin_name;
43
- $this->capability = $capability;
44
- $this->icon = $icon;
45
- $this->position = $position;
46
-
47
- $this->tabs = $tabs;
48
-
49
- if ( $active_tab ) {
50
- $this->set_active_tab( $active_tab );
51
- } else {
52
- $this->set_active_tab( $tabs[0]['slug'] );
53
- }
54
- $this->settings = $settings;
55
- $this->option_name = $option_name;
56
- $this->pro_only = array();
57
- $this->false_fields = array();
58
- $this->textarea_fields = array();
59
- $this->display_your_feed_sections = array();
60
- }
61
-
62
- public function get_vars() {
63
- return $this->vars;
64
- }
65
-
66
- public function get_option_name() {
67
- return $this->option_name;
68
- }
69
-
70
- public function verify_post( $post ) {
71
- return wp_verify_nonce( $post[ $this->option_name . '_validate' ], $this->option_name . '_validate' );
72
- }
73
-
74
- public function hidden_fields_for_tab( $tab ) {
75
- wp_nonce_field( $this->get_option_name() . '_validate', $this->get_option_name() . '_validate', true, true );
76
- ?>
77
- <input type="hidden" name="<?php echo $this->get_option_name() . '_tab_marker'; ?>" value="<?php echo esc_attr( $tab ); ?>"/>
78
- <?php
79
- }
80
-
81
- public function init() {
82
- add_action( 'admin_menu', array( $this, 'create_menus' ) );
83
- add_action( 'admin_init', array( $this, 'settings_init' ) );
84
- add_action( 'admin_init', array( $this, 'additional_settings_init' ) );
85
-
86
- }
87
-
88
- public function settings_init() {
89
- $text_domain = $this->vars->text_domain();
90
- /**
91
- * Configure Tab
92
- */
93
- $args = array(
94
- 'id' => 'sbspf_types',
95
- 'tab' => 'configure',
96
- 'save_after' => 'true'
97
- );
98
- $this->add_settings_section( $args );
99
-
100
- /* Types */
101
- $args = array(
102
- 'name' => 'type',
103
- 'section' => 'sbspf_types',
104
- 'callback' => 'types',
105
- 'title' => '<label>' . __( 'Feed Type', $text_domain ) .'</label>',
106
- 'shortcode' => array(
107
- 'key' => 'type',
108
- 'example' => 'channel',
109
- 'description' => __( 'Type of feed to display', $text_domain ) . ' e.g. channel, playlist, search, favorites, live',
110
- 'display_section' => 'configure'
111
- ),
112
- 'types' => $this->types
113
- );
114
- $this->add_settings_field( $args );
115
-
116
- /* Cache */
117
- $args = array(
118
- 'name' => 'cache',
119
- 'section' => 'sbspf_types',
120
- 'callback' => 'cache',
121
- 'title' => __( 'Check for new posts', $text_domain )
122
- );
123
- $this->add_settings_field( $args );
124
-
125
- /**
126
- * Customize Tab
127
- */
128
- $args = array(
129
- 'title' => __( 'General', $text_domain ),
130
- 'id' => 'sbspf_general',
131
- 'tab' => 'customize',
132
- 'save_after' => 'true'
133
- );
134
- $this->add_settings_section( $args );
135
-
136
- /* Width and Height */
137
- $select_options = array(
138
- array(
139
- 'label' => '%',
140
- 'value' => '%'
141
- ),
142
- array(
143
- 'label' => 'px',
144
- 'value' => 'px'
145
- )
146
- );
147
-
148
- $args = array(
149
- 'name' => 'width',
150
- 'default' => '100',
151
- 'section' => 'sbspf_general',
152
- 'callback' => 'text',
153
- 'min' => 1,
154
- 'size' => 4,
155
- 'title' => __( 'Width of Feed', $text_domain ),
156
- 'shortcode' => array(
157
- 'key' => 'width',
158
- 'example' => '300px',
159
- 'description' => __( 'The width of your feed. Any number with a unit like "px" or "%".', $text_domain ),
160
- 'display_section' => 'customize'
161
- ),
162
- 'select_name' => 'widthunit',
163
- 'select_options' => $select_options,
164
- 'hidden' => array(
165
- 'callback' => 'checkbox',
166
- 'name' => 'width_responsive',
167
- 'label' => __( 'Set to be 100% width on mobile?', $text_domain ),
168
- 'before' => '<div id="sbspf_width_options">',
169
- 'after' => '</div>',
170
- 'tooltip_info' => __( 'If you set a width on the feed then this will be used on mobile as well as desktop. Check this setting to set the feed width to be 100% on mobile so that it is responsive.', $text_domain )
171
- ),
172
- );
173
- $this->add_settings_field( $args );
174
-
175
- $select_options = array(
176
- array(
177
- 'label' => '%',
178
- 'value' => '%'
179
- ),
180
- array(
181
- 'label' => 'px',
182
- 'value' => 'px'
183
- )
184
- );
185
- $args = array(
186
- 'name' => 'height',
187
- 'default' => '',
188
- 'section' => 'sbspf_general',
189
- 'callback' => 'text',
190
- 'min' => 1,
191
- 'size' => 4,
192
- 'title' => __( 'Height of Feed', $text_domain ),
193
- 'shortcode' => array(
194
- 'key' => 'height',
195
- 'example' => '500px',
196
- 'description' => __( 'The height of your feed. Any number with a unit like "px" or "em".', $text_domain ),
197
- 'display_section' => 'customize'
198
- ),
199
- 'select_name' => 'heightunit',
200
- 'select_options' => $select_options,
201
- );
202
- $this->add_settings_field( $args );
203
-
204
- $args = array(
205
- 'name' => 'background',
206
- 'default' => '',
207
- 'section' => 'sbspf_general',
208
- 'callback' => 'color',
209
- 'title' => __( 'Background Color', $text_domain ),
210
- 'shortcode' => array(
211
- 'key' => 'background',
212
- 'example' => '#f00',
213
- 'description' => __( 'Background color for the feed. Any hex color code.', $text_domain ),
214
- 'display_section' => 'customize'
215
- ),
216
- );
217
- $this->add_settings_field( $args );
218
-
219
- $args = array(
220
- 'title' => __( 'Layout', $text_domain ),
221
- 'id' => 'sbspf_layout',
222
- 'tab' => 'customize',
223
- 'save_after' => 'true'
224
- );
225
- $this->add_settings_section( $args );
226
-
227
- $args = array(
228
- 'name' => 'layout',
229
- 'section' => 'sbspf_layout',
230
- 'callback' => 'layout',
231
- 'title' => __( 'Layout Type', $text_domain ),
232
- 'layouts' => $this->layouts,
233
- 'shortcode' => array(
234
- 'key' => 'layout',
235
- 'example' => 'list',
236
- 'description' => __( 'How your posts are display visually.', $text_domain ),
237
- 'display_section' => 'layout'
238
- )
239
- );
240
- $this->add_settings_field( $args );
241
- }
242
-
243
- public function additional_settings_init() {
244
-
245
- }
246
-
247
- public function add_false_field( $name, $tab ) {
248
- $this->false_fields[ $tab ][] = $name;
249
- }
250
-
251
- public function get_false_fields( $tab ) {
252
- if ( isset( $this->false_fields[ $tab ] ) ) {
253
- return $this->false_fields[ $tab ];
254
- }
255
-
256
- return array();
257
- }
258
-
259
- public function add_textarea_field( $name, $tab ) {
260
- $this->textarea_fields[ $tab ][] = $name;
261
- }
262
-
263
- public function get_textarea_fields( $tab ) {
264
- if ( isset( $this->textarea_fields[ $tab ] ) ) {
265
- return $this->textarea_fields[ $tab ];
266
- }
267
-
268
- return array();
269
- }
270
-
271
- public function blank() {
272
-
273
- }
274
-
275
- public function add_settings_section( $args ) {
276
- $title = isset( $args['title'] ) ? $args['title'] : '';
277
- $callback = isset( $args['callback'] ) ? $args['callback'] : array( $this, 'blank' );
278
- add_settings_section(
279
- $args['id'],
280
- $title,
281
- $callback,
282
- $args['id']
283
- );
284
-
285
- $save_after = isset( $args['save_after'] ) ? $args['save_after'] : false;
286
- $pro = isset( $args['pro'] ) && ($args['pro'] !== false) ? $args['pro'] : false;
287
- $this->settings_sections[ $args['tab'] ][] = array(
288
- 'id' => $args['id'],
289
- 'save_after' => $save_after,
290
- 'pro' => $pro
291
-
292
- );
293
- }
294
-
295
- public function add_settings_field( $args ) {
296
- $title_after = '';
297
- $shortcode = false;
298
- if ( isset( $args['shortcode'] ) ) {
299
- $title_after = isset( $args['shortcode']['after'] ) ? $args['shortcode']['after'] : '';
300
- $shortcode = $args['shortcode'];
301
- }
302
-
303
- if ( $shortcode ) {
304
- $this->display_your_feed_sections[ $shortcode['display_section'] ]['settings'][] = $shortcode;
305
- if ( isset( $args['pro'] ) ) {
306
- $this->pro_only[] = $args['name'];
307
- }
308
- }
309
-
310
- if ( $args['callback'] === 'types' ) {
311
- $formatted_label = '<label for="' . $this->option_name . '_' . $args['name'] . '">' . $args['title'] .'</label>';
312
- $formatted_label .= '<code class="sbspf_shortcode">type'. "\n";
313
- foreach ( $args['types'] as $type ) {
314
- $shortcode = array(
315
- 'key' => $type['slug'],
316
- 'example' => $type['example'],
317
- 'description' => $type['description'],
318
- 'display_section' => 'configure'
319
- );
320
- $this->display_your_feed_sections[ $shortcode['display_section'] ]['settings'][] = $shortcode;
321
- if ( isset( $type['pro'] ) ) {
322
- $this->pro_only[] = $type['slug'];
323
- }
324
-
325
- $formatted_label .= 'Eg: type=' . $type['slug'] . '<br>';
326
- $formatted_label .= $type['slug'] . '="' . substr( $type['example'], 0, 14) . '"<br>';
327
-
328
- }
329
- $formatted_label .= '</code><br>';
330
-
331
- if ( isset( $args['shortcode']['after_description'] ) ) {
332
- $formatted_label .= $args['shortcode']['after_description'];
333
- }
334
-
335
- $title = $formatted_label;
336
- } else {
337
- $title = $this->format_title( $args['title'], $args['name'], $shortcode, $title_after );
338
- }
339
-
340
- if ( $args['callback'] === 'checkbox' || (isset( $args['falsefield'] ) && $args['falsefield'] === true) ) {
341
- $tab = 'none';
342
- foreach ( $this->settings_sections as $key => $settings_sections ) {
343
- foreach ( $settings_sections as $this_tab_sections ) {
344
- if ( $this_tab_sections['id'] === $args['section'] ) {
345
- $tab = $key;
346
- }
347
- }
348
-
349
- }
350
- $this->add_false_field( $args['name'], $tab );
351
- }
352
-
353
- if ( $args['callback'] === 'layout' || $args['callback'] === 'sub_option' ) {
354
- $tab = 'none';
355
- foreach ( $this->settings_sections as $key => $settings_sections ) {
356
- foreach ( $settings_sections as $this_tab_sections ) {
357
- if ( $this_tab_sections['id'] === $args['section'] ) {
358
- $tab = $key;
359
- }
360
- }
361
-
362
- }
363
- $sub_options = isset( $args['layouts'] ) ? $args['layouts'] : $args['sub_options'];
364
- foreach ( $sub_options as $sub_option ) {
365
- if ( isset( $sub_option['options'] ) ) {
366
- foreach( $sub_option['options'] as $sub_sub_option ) {
367
- if ( ! empty( $sub_sub_option['shortcode'] ) ) {
368
- $key = ! empty( $sub_sub_option['shortcode']['key'] ) ? $sub_sub_option['shortcode']['key'] : $sub_option['slug'] . $sub_sub_option['name'];
369
- $example = ! empty( $sub_sub_option['shortcode']['example'] ) ? $sub_sub_option['shortcode']['example'] : '';
370
- $description = ! empty( $sub_sub_option['shortcode']['description'] ) ? $sub_sub_option['shortcode']['description'] : '';
371
- $display_section = ! empty( $sub_sub_option['shortcode']['display_section'] ) ? $sub_sub_option['shortcode']['display_section'] : str_replace( 'sbspf_', '', $args['section'] );
372
- $sub_shortcode = array(
373
- 'key' => $key,
374
- 'example' => $example,
375
- 'description' => $description,
376
- 'display_section' => $display_section
377
- );
378
- if ( isset( $this->display_your_feed_sections[ $display_section ] ) ) {
379
- $this->display_your_feed_sections[ $display_section ]['settings'][] = $sub_shortcode;
380
- if ( isset( $sub_sub_option['pro'] ) ) {
381
- $this->pro_only[] = $key;
382
- }
383
- }
384
- }
385
- if ( $sub_sub_option['callback'] === 'checkbox' ) {
386
- $this->add_false_field( $sub_option['slug'] . $sub_sub_option['name'], $tab );
387
- }
388
- }
389
- }
390
- }
391
- }
392
-
393
- if ( $args['callback'] === 'textarea' ) {
394
- $tab = 'none';
395
- foreach ( $this->settings_sections as $key => $settings_sections ) {
396
- foreach ( $settings_sections as $this_tab_sections ) {
397
- if ( $this_tab_sections['id'] === $args['section'] ) {
398
- $tab = $key;
399
- }
400
- }
401
-
402
- }
403
- $this->add_textarea_field( $args['name'], $tab );
404
- }
405
-
406
- add_settings_field(
407
- $args['name'],
408
- $title,
409
- array( $this, $args['callback'] ),
410
- $args['section'],
411
- $args['section'],
412
- $args
413
- );
414
-
415
- if ( isset( $args['hidden'] ) ) {
416
- if ( $args['hidden']['callback'] === 'checkbox' ) {
417
- $tab = 'none';
418
- foreach ( $this->settings_sections as $key => $settings_sections ) {
419
- foreach ( $settings_sections as $this_tab_sections ) {
420
- if ( $this_tab_sections['id'] === $args['section'] ) {
421
- $tab = $key;
422
- }
423
- }
424
-
425
- }
426
- $this->add_false_field( $args['hidden']['name'], $tab );
427
- }
428
- }
429
- }
430
-
431
- public function set_feed_types( $types ) {
432
- $this->types = $types;
433
- }
434
-
435
- public function set_feed_layouts( $layouts ) {
436
- $this->layouts = $layouts;
437
- }
438
-
439
- public function set_display_table_sections( $headings ) {
440
- foreach ( $headings as $heading ) {
441
- $this->display_your_feed_sections[ $heading['slug'] ] = array(
442
- 'label' => $heading['label'],
443
- 'settings' => array()
444
- );
445
- }
446
- }
447
-
448
- public function checkbox( $args ) {
449
- $default = isset( $args['default'] ) ? $args['default'] : false;
450
- $selected = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
451
- $label = isset( $args['label'] ) ? $args['label'] : __( 'Yes' );
452
- $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
453
- $has_shortcode = isset( $args['has_shortcode'] ) && $args['has_shortcode'] && isset( $args['shortcode_example'] ) ? '1' : '';
454
- $pro_flag = isset( $args['pro'] ) ? ' <span class="sbspf_pro_only"></span>' : '';
455
- echo $pro_flag;
456
- ?>
457
- <input name="<?php echo $this->option_name .'['.esc_attr( $args['name'] ).']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>" class="sbspf_single_checkbox" type="checkbox"<?php if ( $selected ) echo ' checked'; ?>/>
458
- <label for="<?php echo $this->option_name . '_' . $args['name'] . $has_shortcode; ?>"><?php echo esc_html( $label ); ?></label><?php if ( $has_shortcode === '1' ) : ?><code class="sbspf_shortcode"> <?php echo $args['name'] . "\n"; ?>
459
- Eg: <?php echo $args['name']; ?>=<?php echo $args['shortcode_example']; ?></code><br><?php endif; ?>
460
- <?php if ( isset( $args['tooltip_info'] ) ) : ?>
461
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
462
- <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
463
- <?php
464
- endif;
465
- }
466
-
467
- public function multi_checkbox( $args ) {
468
- $default = isset( $args['default'] ) ? $args['default'] : false;
469
- $selection_array = isset( $this->settings[ $args['name'] ] ) ? (array)$this->settings[ $args['name'] ] : (array)$default;
470
- $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
471
- $index = 0;
472
- ?>
473
- <?php foreach ( $args['select_options'] as $select_option ) :
474
- $selected = in_array( $select_option['value'], $selection_array, true );
475
- $pro_only = (isset( $select_option['pro'] ) && $select_option['pro']) ? ' sbspf_pro_only' : '';
476
- $class = ! empty( $select_option['class'] ) ? ' ' . $select_option['class'] : '';
477
- ?>
478
- <div class="sbspf_multi_checkbox_option<?php echo $pro_only . $class; ?>">
479
- <input name="<?php echo $this->option_name .'['.esc_attr( $args['name'] ).'][]'; ?>" id="<?php echo $this->option_name . '_' . $args['name']. '_' . $index; ?>" value="<?php echo esc_attr( $select_option['value'] ); ?>" type="checkbox"<?php if ( $selected ) echo ' checked'; ?>/>
480
- <label for="<?php echo $this->option_name . '_' . $args['name'] . '_' . $index; ?>"><?php echo esc_html( $select_option['label'] ); ?></label>
481
- </div>
482
- <?php
483
- $index++;
484
- endforeach; ?>
485
-
486
- <?php if ( isset( $args['tooltip_info'] ) ) : ?>
487
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
488
- <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
489
- <?php
490
- endif;
491
- }
492
-
493
- public function text( $args ) {
494
- $default = isset( $args['default'] ) ? $args['default'] : '';
495
- $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
496
- $size = ( isset( $args['size'] ) ) ? ' size="'. $args['size'].'"' : '';
497
- $class = isset( $args['class'] ) ? ' class="'. esc_attr( $args['class'] ) . '"' : '';
498
-
499
- $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
500
- $pro_flag = isset( $args['pro'] ) ? ' <span class="sbspf_pro_only"></span>' : '';
501
- echo $pro_flag;
502
-
503
- if ( isset( $args['min'] ) ) :
504
- $min = ( isset( $args['min'] ) ) ? ' min="'. $args['min'].'"' : '';
505
- $max = ( isset( $args['max'] ) ) ? ' max="'. $args['max'].'"' : '';
506
- $step = ( isset( $args['step'] ) ) ? ' step="'. $args['step'].'"' : '';
507
- $class = isset( $args['class'] ) ? ' class="sbspf_number_field sbspf_size_' . $args['size'] . ' '. esc_attr( $args['class'] ) . '"' : ' class="sbspf_number_field sbspf_size_' . $args['size'] . '"';
508
- ?>
509
- <input name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>"<?php echo $class; ?> type="number"<?php echo $size; ?><?php echo $min; ?><?php echo $max; ?><?php echo $step; ?> value="<?php echo esc_attr( $value ); ?>" />
510
- <?php elseif ( isset( $args['color'] ) ) : ?>
511
- <input name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>" class="sbspf_colorpicker" type="text" value="#<?php echo esc_attr( str_replace('#', '', $value ) ); ?>" />
512
- <?php else: ?>
513
- <input name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>"<?php echo $class; ?> type="text" value="<?php echo esc_attr( stripslashes( $value ) ); ?>" />
514
- <?php endif; ?>
515
-
516
- <?php if ( isset( $args['select_options'] ) ) :
517
- $value = isset( $this->settings[ $args['select_name'] ] ) ? $this->settings[ $args['select_name'] ] : $args['select_options'][0]['value'];
518
- ?>
519
- <select name="<?php echo $this->option_name.'['.$args['select_name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['select_name']; ?>">
520
- <?php foreach ( $args['select_options'] as $select_option ) : ?>
521
- <option value="<?php echo esc_attr( $select_option['value'] ); ?>"<?php if ( (string)$select_option['value'] === (string)$value ) echo ' selected'; ?>><?php echo esc_html( $select_option['label'] ); ?></option>
522
- <?php endforeach; ?>
523
- </select>
524
- <?php endif; ?>
525
-
526
- <?php if ( isset( $args['hidden'] ) ) : ?>
527
-
528
- <?php
529
- if ( is_callable( array( $this, $args['hidden']['callback'] ) ) ){
530
- echo $args['hidden']['before'];
531
- call_user_func_array(
532
- array( $this, $args['hidden']['callback'] ),
533
- array( $args['hidden'] )
534
- );
535
- echo $args['hidden']['after'];
536
- }
537
- ?>
538
- <?php endif; ?>
539
-
540
- <?php if ( isset( $args['additional'] ) ) : ?>
541
- <?php echo $args['additional']; ?>
542
- <?php endif; ?>
543
-
544
- <?php if ( isset( $args['tooltip_info'] ) ) : ?>
545
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
546
- <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
547
- <?php
548
- endif;
549
- }
550
-
551
- public function select( $args ) {
552
- $default = isset( $args['default'] ) ? $args['default'] : $args['options'][0]['value'];
553
- $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
554
-
555
- if ( isset( $args['min'] ) && isset( $args['max'] ) && ((int)$args['min'] < (int)$args['max']) && empty( $args['options'] ) ) {
556
- $args['options'] = array();
557
- $i = (int)$args['min'];
558
-
559
- while ( $i <= (int)$args['max'] ) {
560
- $args['options'][] = array(
561
- 'label' => $i,
562
- 'value' => $i
563
- );
564
- $i++;
565
- }
566
- }
567
-
568
- $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
569
- $pro_class = isset( $args['pro'] ) ? ' class="sbspf_pro_only"' : '';
570
- ?>
571
- <select<?php echo $pro_class; ?> name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>">
572
- <?php foreach ( $args['options'] as $select_option ) : ?>
573
- <option value="<?php echo esc_attr( $select_option['value'] ); ?>"<?php if ( (string)$select_option['value'] === (string)$value ) echo ' selected'; ?>><?php echo esc_html( $select_option['label'] ); ?></option>
574
- <?php endforeach; ?>
575
- </select>
576
-
577
- <?php if ( isset( $args['additional'] ) ) : ?>
578
- <?php echo $args['additional']; ?>
579
- <?php endif; ?>
580
-
581
- <?php if ( isset( $args['tooltip_info'] ) ) : ?>
582
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
583
- <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
584
- <?php endif;
585
- }
586
-
587
- public function textarea( $args ) {
588
- $default = isset( $args['default'] ) ? $args['default'] : '';
589
- $value = isset( $this->settings[ $args['name'] ] ) ? stripslashes( $this->settings[ $args['name'] ] ) : $default;
590
- $pro_class = isset( $args['pro'] ) ? ' class="sbspf_pro_only"' : '';
591
-
592
- if ( isset( $args['tooltip_info'] ) ) : ?>
593
- <span><?php echo $args['tooltip_info']; ?></span><br>
594
- <?php endif; ?>
595
-
596
- <textarea<?php echo $pro_class; ?> name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>"rows="7"><?php echo $value; ?></textarea>
597
-
598
- <?php if ( isset( $args['note'] ) ) : ?>
599
- <br><span class="sbspf_note"><?php echo $args['note']; ?></span>
600
- <?php endif;
601
- }
602
-
603
- public function color( $args ) {
604
- $args['color'] = true;
605
- $this->text( $args );
606
- }
607
-
608
- public function types( $args ) {
609
- $type_selected = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $args['types'][0]['slug'];
610
-
611
- foreach ( $args['types'] as $type ) :
612
- $input_type = isset( $type['input_type'] ) ? $type['input_type'] : 'connected_account';
613
- $selected = ! empty( $this->settings[ $type['slug'] ] ) ? $this->settings[ $type['slug'] ] : $type['default'];
614
- if ( $input_type === 'connected_account' ) {
615
- $selected = isset( $this->settings[ $type['slug'] . '_ids' ] ) ? $this->settings[ $type['slug'] . '_ids' ] : array();
616
- }
617
- $on_select = isset( $type['onselect'] ) ? $type['onselect'] : false;
618
- $pro_class = isset( $type['pro'] ) ? ' sbspf_pro_only' : '';
619
- ?>
620
- <div class="sbspf_row sbspf_type_row<?php echo $pro_class; ?>" style="min-height: 29px;">
621
- <div class="sbspf_col sbspf_one">
622
- <input type="radio" name="<?php echo $this->option_name.'['.esc_attr( $args['name'] ).']'; ?>" class="sbspf_type_input" id="sbspf_type_<?php echo esc_attr( $type['slug'] ); ?>" value="<?php echo esc_attr( $type['slug'] ); ?>"<?php if ( $type_selected === $type['slug'] ) echo 'checked'; ?>>
623
- <label class="sbspf_radio_label" for="sbspf_type_<?php echo esc_attr( $type['slug'] ); ?>"><?php echo esc_html( $type['label'] ); ?>: <a class="sbspf_type_tooltip_link" href="JavaScript:void(0);"><i class="fa fa-question-circle" aria-hidden="true" style="margin-left: 2px;"></i></a></label>
624
- </div>
625
- <div class="sbspf_col sbspf_two">
626
- <?php if ( $input_type === 'text' ) :
627
- $placeholder = isset( $type['note'] ) ? ' placeholder="' . esc_attr( $type['note'] ). '"' : '';
628
- ?>
629
- <input name="<?php echo $this->option_name.'['.esc_attr( $type['slug'] ).']'; ?>" id="sbspf_<?php echo esc_attr( $type['slug'] ); ?>" type="text" value="<?php echo esc_attr( $selected ); ?>" size="45"<?php echo $placeholder; ?>>
630
- <?php else :
631
- $connected_accounts = $this->get_connected_accounts(); ?>
632
- <div class="sbspf_<?php echo esc_attr( $type['slug'] ); ?>_feed_ids_wrap">
633
- <?php foreach ( $connected_accounts as $connected_account ) : if ( in_array( $connected_account['channel_id'], $selected, true ) ) : ?>
634
- <div id="sbspf_<?php echo esc_attr( $type['slug'] ); ?>_feed_id_<?php echo esc_attr( $connected_account['channel_id'] ); ?>" class="sbspf_<?php echo esc_attr( $type['slug'] ); ?>_feed_account_wrap">
635
- <strong><?php echo esc_html( $connected_account['username'] ); ?></strong> <span>(<?php echo esc_attr( $connected_account['channel_id'] ); ?>)</span><input type="hidden" name="<?php echo $this->option_name.'['.esc_attr( $type['slug'] ).'_feed_ids][]'; ?>" value="<?php echo esc_attr( $connected_account['channel_id'] ); ?>">
636
- </div>
637
- <?php endif; endforeach; ?>
638
- </div>
639
- <?php if ( empty( $selected ) ) : ?>
640
- <p class="sbspf_no_accounts" style="margin-top: -3px; margin-right: 10px;"><?php _e( 'Connect an account above', $this->vars->text_domain() ); ?></p>
641
- <?php endif; ?>
642
-
643
- <?php endif; ?>
644
- <?php if ( $input_type !== 'text' && isset( $type['note'] ) ) : ?>
645
- <br><span class="sbspf_note"><?php echo $type['note']; ?></span>
646
- <?php endif; ?>
647
- </div>
648
- <?php if ( $on_select ) : ?>
649
- <div class="sbspf_onselect">
650
- <?php call_user_func_array( array( $this, $on_select ), array( $type ) ); ?>
651
- </div>
652
- <?php endif; ?>
653
-
654
- <div class="sbspf_tooltip sbspf_type_tooltip sbspf_more_info">
655
- <?php if ( ! empty( $type['tooltip'] ) ) : ?>
656
- <?php echo $type['tooltip']; ?>
657
- <?php endif; ?>
658
- </div>
659
-
660
-
661
-
662
- </div>
663
- <?php endforeach;
664
- }
665
-
666
- public function sub_option( $args ) {
667
- $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : 'related';
668
- $pro_flag = isset( $args['pro'] ) ? ' <span class="sbspf_pro_only"></span>' : '';
669
- echo $pro_flag;
670
- $cta_options = $args['sub_options'];
671
- ?>
672
- <?php if ( ! empty( $args['before'] ) ) {
673
- echo $args['before'];
674
- }?>
675
-
676
- <div class="sbspf_sub_options">
677
- <?php foreach ( $cta_options as $sub_option ) :
678
- $pro_class = isset( $sub_option['pro'] ) ? ' sbspf_pro_only' : '';
679
- ?>
680
- <div class="sbspf_sub_option_cell<?php echo esc_attr( $pro_class ); ?>">
681
- <input class="sbspf_sub_option_type" id="sbspf_sub_option_type_<?php echo esc_attr( $sub_option['slug'] ); ?>" name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" type="radio" value="<?php echo esc_attr( $sub_option['slug'] ); ?>"<?php if ( $sub_option['slug'] === $value ) echo ' checked'?>><label for="sbspf_sub_option_type_<?php echo esc_attr( $sub_option['slug'] ); ?>"><span class="sbspf_label"><?php echo $sub_option['label']; ?></span></label>
682
- </div>
683
- <?php endforeach; ?>
684
-
685
- <div class="sbspf_box_setting">
686
- <?php if ( isset( $cta_options ) ) : foreach ( $cta_options as $sub_option ) :
687
- $pro_class = isset( $sub_option['pro'] ) ? ' sbspf_pro_only' : '';
688
- ?>
689
- <div class="sbspf_sub_option_settings sbspf_sub_option_type_<?php echo esc_attr( $sub_option['slug'] ) . $pro_class; ?>">
690
-
691
- <div class="sbspf_sub_option_setting">
692
- <?php echo sby_admin_icon( 'info-circle', 'sbspf_small_svg' ); ?>&nbsp;&nbsp;&nbsp;<span class="sbspf_note" style="margin-left: 0;"><?php echo $sub_option['note']; ?></span>
693
- </div>
694
- <?php if ( ! empty( $sub_option['options'] ) ) : ?>
695
- <?php foreach ( $sub_option['options'] as $option ) :
696
- $option['name'] = $sub_option['slug'].$option['name'];
697
- ?>
698
- <div class="sbspf_sub_option_setting">
699
- <?php if ( $option['callback'] !== 'checkbox' ) :
700
- if ( isset( $option['shortcode'] ) ) : ?>
701
- <label title="<?php echo __( 'Click for shortcode option', $this->vars->text_domain() ); ?>"><?php echo $option['label']; ?></label><code class="sbspf_shortcode"> <?php echo $option['name'] . "\n"; ?>
702
- Eg: <?php echo $option['name']; ?>=<?php echo $option['shortcode']['example']; ?></code><br>
703
- <?php else: ?>
704
- <label><?php echo $option['label']; ?></label><br>
705
- <?php endif; ?>
706
- <?php else:
707
- $option['shortcode_example'] = $option['shortcode']['example'];
708
- $option['has_shortcode'] = true;
709
- endif; ?>
710
- <?php call_user_func_array( array( $this, $option['callback'] ), array( $option ) ); ?>
711
-
712
- </div>
713
-
714
- <?php endforeach; ?>
715
- <?php endif; ?>
716
-
717
- </div>
718
-
719
- <?php endforeach; endif; ?>
720
- </div>
721
- </div>
722
- <?php
723
- }
724
-
725
- public function cache( $args ) {
726
- $social_network = $this->vars->social_network();
727
- $type_selected = isset( $this->settings['caching_type'] ) ? $this->settings['caching_type'] : 'page';
728
- $caching_time = isset( $this->settings['caching_time'] ) ? $this->settings['caching_time'] : 1;
729
- $cache_time_unit_selected = isset( $this->settings['cache_time_unit'] ) ? $this->settings['cache_time_unit'] : 'hours';
730
- $cache_cron_interval_selected = isset( $this->settings['cache_cron_interval'] ) ? $this->settings['cache_cron_interval'] : '';
731
- $cache_cron_time = isset( $this->settings['cache_cron_time'] ) ? $this->settings['cache_cron_time'] : '';
732
- $cache_cron_am_pm = isset( $this->settings['cache_cron_am_pm'] ) ? $this->settings['cache_cron_am_pm'] : '';
733
-
734
- ?>
735
- <div class="sbspf_cache_settings_wrap">
736
- <div class="sbspf_row">
737
- <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" class="sbspf_caching_type_input" id="sbspf_caching_type_page" value="page"<?php if ( $type_selected === 'page' ) echo ' checked'?>>
738
- <label class="sbspf_radio_label" for="sbspf_caching_type_page"><?php _e ( 'When the page loads', $this->vars->text_domain() ); ?></label>
739
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);" style="position: relative; top: 2px;"><?php echo $this->default_tooltip_text() ?></a>
740
- <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __( "Your %s data is temporarily cached by the plugin in your WordPress database. There are two ways that you can set the plugin to check for new data:<br><br>
741
- <b>1. When the page loads</b><br>Selecting this option means that when the cache expires then the plugin will check %s for new posts the next time that the feed is loaded. You can choose how long this data should be cached for with a minimum time of 15 minutes. If you set the time to 60 minutes then the plugin will clear the cached data after that length of time, and the next time the page is viewed it will check for new data. <b>Tip:</b> If you're experiencing an issue with the plugin not updating automatically then try enabling the setting labeled <b>'Force cache to clear on interval'</b> which is located on the 'Customize' tab.<br><br>
742
- <b>2. In the background</b><br>Selecting this option means that the plugin will check for new data in the background so that the feed is updated behind the scenes. You can select at what time and how often the plugin should check for new data using the settings below. <b>Please note</b> that the plugin will initially check for data from Instagram when the page first loads, but then after that will check in the background on the schedule selected - unless the cache is cleared.", $this->vars->text_domain() ), $social_network, $social_network ); ?>
743
- </p>
744
- </div>
745
- <div class="sbspf_row sbspf-caching-page-options" style="display: none;">
746
- <?php _e ( 'Every', $this->vars->text_domain() ); ?>:
747
- <input name="<?php echo $this->option_name.'[caching_time]'; ?>" type="text" value="<?php echo esc_attr( $caching_time ); ?>" size="4">
748
- <select name="<?php echo $this->option_name.'[caching_time_unit]'; ?>">
749
- <option value="minutes"<?php if ( $cache_time_unit_selected === 'minutes' ) echo ' selected'?>><?php _e ( 'Minutes', $this->vars->text_domain() ); ?></option>
750
- <option value="hours"<?php if ( $cache_time_unit_selected === 'hours' ) echo ' selected'?>><?php _e ( 'Hours', $this->vars->text_domain() ); ?></option>
751
- <option value="days"<?php if ( $cache_time_unit_selected === 'days' ) echo ' selected'?>><?php _e ( 'Days', $this->vars->text_domain() ); ?></option>
752
- </select>
753
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php _e ( 'What does this mean?', $this->vars->text_domain() ); ?></a>
754
- <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __("Your %s posts are temporarily cached by the plugin in your WordPress database. You can choose how long the posts should be cached for. If you set the time to 1 hour then the plugin will clear the cache after that length of time and check %s for posts again.", $this->vars->text_domain() ), $social_network, $social_network ); ?></p>
755
- </div>
756
-
757
- <div class="sbspf_row">
758
- <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" id="sbspf_caching_type_cron" class="sbspf_caching_type_input" value="background" <?php if ( $type_selected === 'background' ) echo ' checked'?>>
759
- <label class="sbspf_radio_label" for="sbspf_caching_type_cron"><?php _e ( 'In the background', $this->vars->text_domain() ); ?></label>
760
- </div>
761
- <div class="sbspf_row sbspf-caching-cron-options" style="display: block;">
762
-
763
- <select name="<?php echo $this->option_name.'[cache_cron_interval]'; ?>" id="sbspf_cache_cron_interval">
764
- <option value="30mins"<?php if ( $cache_cron_interval_selected === '30mins' ) echo ' selected'?>><?php _e ( 'Every 30 minutes', $this->vars->text_domain() ); ?></option>
765
- <option value="1hour"<?php if ( $cache_cron_interval_selected === '1hour' ) echo ' selected'?>><?php _e ( 'Every hour', $this->vars->text_domain() ); ?></option>
766
- <option value="12hours"<?php if ( $cache_cron_interval_selected === '12hours' ) echo ' selected'?>><?php _e ( 'Every 12 hours', $this->vars->text_domain() ); ?></option>
767
- <option value="24hours"<?php if ( $cache_cron_interval_selected === '24hours' ) echo ' selected'?>><?php _e ( 'Every 24 hours', $this->vars->text_domain() ); ?></option>
768
- </select>
769
-
770
- <div id="sbspf-caching-time-settings" style="">
771
- <?php _e ( 'at', $this->vars->text_domain() ); ?>
772
- <select name="<?php echo $this->option_name.'[cache_cron_time]'; ?>" style="width: 80px">
773
- <option value="1"<?php if ( (int)$cache_cron_time === 1 ) echo ' selected'?>>1:00</option>
774
- <option value="2"<?php if ( (int)$cache_cron_time === 2 ) echo ' selected'?>>2:00</option>
775
- <option value="3"<?php if ( (int)$cache_cron_time === 3 ) echo ' selected'?>>3:00</option>
776
- <option value="4"<?php if ( (int)$cache_cron_time === 4 ) echo ' selected'?>>4:00</option>
777
- <option value="5"<?php if ( (int)$cache_cron_time === 5 ) echo ' selected'?>>5:00</option>
778
- <option value="6"<?php if ( (int)$cache_cron_time === 6 ) echo ' selected'?>>6:00</option>
779
- <option value="7"<?php if ( (int)$cache_cron_time === 7 ) echo ' selected'?>>7:00</option>
780
- <option value="8"<?php if ( (int)$cache_cron_time === 8 ) echo ' selected'?>>8:00</option>
781
- <option value="9"<?php if ( (int)$cache_cron_time === 9 ) echo ' selected'?>>9:00</option>
782
- <option value="10"<?php if ( (int)$cache_cron_time === 10 ) echo ' selected'?>>10:00</option>
783
- <option value="11"<?php if ( (int)$cache_cron_time === 11 ) echo ' selected'?>>11:00</option>
784
- <option value="0"<?php if ( (int)$cache_cron_time === 0 ) echo ' selected'?>>12:00</option>
785
- </select>
786
-
787
- <select name="<?php echo $this->option_name.'[cache_cron_am_pm]'; ?>" style="width: 50px">
788
- <option value="am"<?php if ( $cache_cron_am_pm === 'am' ) echo ' selected'?>><?php _e ( 'AM', $this->vars->text_domain() ); ?></option>
789
- <option value="pm"<?php if ( $cache_cron_am_pm === 'pm' ) echo ' selected'?>><?php _e ( 'PM', $this->vars->text_domain() ); ?></option>
790
- </select>
791
- </div>
792
-
793
- <?php
794
- if ( wp_next_scheduled( 'sbspf_feed_update' ) ) {
795
- $time_format = get_option( 'time_format' );
796
- if ( ! $time_format ) {
797
- $time_format = 'g:i a';
798
- }
799
- //
800
- $schedule = wp_get_schedule( 'sbspf_feed_update' );
801
- if ( $schedule == '30mins' ) $schedule = __( 'every 30 minutes', $this->vars->text_domain() );
802
- if ( $schedule == 'twicedaily' ) $schedule = __( 'every 12 hours', $this->vars->text_domain() );
803
- $sbspf_next_cron_event = wp_next_scheduled( 'sbspf_feed_update' );
804
- echo '<p class="sbspf-caching-sched-notice"><span><b>' . __( 'Next check', $this->vars->text_domain() ) . ': ' . date( $time_format, $sbspf_next_cron_event + sbspf_get_utc_offset() ) . ' (' . $schedule . ')</b> - ' . __( 'Note: Saving the settings on this page will clear the cache and reset this schedule', $this->vars->text_domain() ) . '</span></p>';
805
- } else {
806
- echo '<p style="font-size: 11px; color: #666;">' . __( 'Nothing currently scheduled', $this->vars->text_domain() ) . '</p>';
807
- }
808
- ?>
809
- </div>
810
- </div>
811
- <?php
812
- }
813
-
814
- public function layout( $args ) {
815
- $default = isset( $args['default'] ) ? $args['default'] : $args['layouts'][0]['slug'];
816
- $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
817
- ?>
818
- <div class="sbspf_layouts">
819
- <?php foreach ( $args['layouts'] as $layout ) :
820
- $pro_class = isset( $layout['pro'] ) ? ' sbspf_pro_only' : '';
821
- ?>
822
- <div class="sbspf_layout_cell<?php echo $pro_class; ?>">
823
- <input class="sbspf_layout_type" id="sbspf_layout_type_<?php echo esc_attr( $layout['slug'] ); ?>" name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" type="radio" value="<?php echo esc_attr( $layout['slug'] ); ?>"<?php if ( $layout['slug'] === $value ) echo ' checked'?>><label for="sbspf_layout_type_<?php echo esc_attr( $layout['slug'] ); ?>"><span class="sbspf_label"><?php echo $layout['label']; ?></span><img src="<?php echo esc_url( $this->vars->plugin_url() . $layout['image'] ); ?>"></label>
824
- </div>
825
- <?php endforeach; ?>
826
-
827
- <div class="sbspf_layout_options_wrap">
828
- <?php foreach ( $args['layouts'] as $layout ) :
829
- $pro_class = isset( $layout['pro'] ) ? ' sbspf_pro_only' : '';
830
- ?>
831
- <div class="sbspf_layout_settings sbspf_layout_type_<?php echo esc_attr( $layout['slug'] ) . $pro_class; ?>">
832
-
833
- <div class="sbspf_layout_setting">
834
- <?php echo sby_admin_icon( 'info-circle' ); ?>&nbsp;&nbsp;&nbsp;<span class="sbspf_note" style="margin-left: 0;"><?php echo $layout['note']; ?></span>
835
- </div>
836
- <?php if ( ! empty( $layout['options'] ) ) : ?>
837
- <?php foreach ( $layout['options'] as $option ) :
838
- $option['name'] = $layout['slug'].$option['name'];
839
- $option['shortcode']['example'] = isset( $option['shortcode']['example'] ) ? $option['shortcode']['example'] : $option['shortcode_example'];
840
-
841
- ?>
842
- <div class="sbspf_layout_setting">
843
- <?php if ( $option['callback'] !== 'checkbox' ) : ?>
844
- <label title="<?php echo __( 'Click for shortcode option', $this->vars->text_domain() ); ?>"><?php echo $option['label']; ?></label><code class="sbspf_shortcode"> <?php echo $option['name'] . "\n"; ?>
845
- Eg: <?php echo $option['name']; ?>=<?php echo $option['shortcode']['example']; ?></code><br>
846
- <?php else:
847
-
848
- $option['has_shortcode'] = true;
849
- endif; ?>
850
- <?php call_user_func_array( array( $this, $option['callback'] ), array( $option ) ); ?>
851
-
852
- </div>
853
-
854
- <?php endforeach; ?>
855
- <?php endif; ?>
856
-
857
- </div>
858
-
859
- <?php endforeach; ?>
860
- </div>
861
- </div>
862
- <?php
863
- }
864
-
865
- public function instructions( $args ) {
866
- ?>
867
- <div class="sbspf_instructions_wrap">
868
- <?php echo $args['instructions']?>
869
- </div>
870
- <?php
871
- }
872
-
873
- public function format_title( $label, $name, $shortcode_args = false, $after = '' ) {
874
- $formatted_label = '<label for="' . $this->option_name . '_' . $name . '">' . $label .'</label>';
875
- if ( $shortcode_args ) {
876
- $formatted_label .= '<code class="sbspf_shortcode"> ' . $shortcode_args['key'] . "\n";
877
- $formatted_label .= 'Eg: ' . $shortcode_args['key'] . '=' . $shortcode_args['example'] . '</code><br>';
878
- }
879
- $formatted_label .= $after;
880
-
881
- return $formatted_label;
882
- }
883
-
884
- public function validate_options( $input, $tab ) {
885
- $updated_options = get_option( $this->option_name, array() );
886
- $false_if_empty_keys = $this->get_false_fields( $tab );
887
- $textarea_keys = $this->get_textarea_fields( $tab );
888
-
889
- foreach ( $false_if_empty_keys as $false_key ) {
890
- $updated_options[ $false_key ] = false;
891
- }
892
-
893
- foreach ( $input as $key => $val ) {
894
- if ( in_array( $key, $false_if_empty_keys ) ) {
895
- $updated_options[ $key ] = ($val === 'on');
896
- } elseif ( in_array( $key, $textarea_keys ) ) {
897
- $updated_options[ $key ] = sanitize_textarea_field( $val );
898
- } elseif ( is_array( $val ) ) {
899
- $updated_options[ $key ] = array();
900
- foreach ( $val as $key2 => $val2 ) {
901
- $updated_options[ $key ][ $key2 ] = sanitize_text_field( $val2 );
902
- }
903
- } else {
904
- $updated_options[ $key ] = sanitize_text_field( $val );
905
- }
906
- }
907
-
908
-
909
- if ( $tab === 'configure' ) {
910
- do_action( $this->option_name . '_after_configure_save', $updated_options );
911
- } elseif ( $tab === 'customize' ) {
912
- do_action( $this->option_name . '_after_customize_save', $updated_options );
913
- }
914
-
915
- return $updated_options;
916
- }
917
-
918
-
919
- public function update_options( $new_settings ) {
920
- update_option( $this->get_option_name(), $new_settings );
921
- $this->settings = $new_settings;
922
- }
923
-
924
- public function get_sections( $tab ) {
925
- if ( isset( $this->settings_sections[ $tab ] ) ) {
926
- return $this->settings_sections[ $tab ];
927
- }
928
- return array();
929
- }
930
-
931
- public function create_menus() {
932
- add_menu_page(
933
- $this->plugin_name,
934
- $this->plugin_name,
935
- $this->capability,
936
- $this->slug,
937
- array( $this, 'create_options_page' ),
938
- $this->icon,
939
- $this->position
940
- );
941
-
942
- foreach ( $this->tabs as $tab ) {
943
- if ( $tab['slug'] !== 'configure'
944
- && ! isset( $tab['has_nav_tab'] ) ) {
945
- $title = isset( $tab['title'] ) ? $tab['title'] : '';
946
- $capability = isset( $tab['capability'] ) ? $tab['capability'] : 'manage_options';
947
- $slug = isset( $tab['slug'] ) ? $tab['slug'] : '';
948
- $callback = isset( $tab['callback'] ) ? $tab['callback'] : array( $this, 'create_options_page' );
949
-
950
- add_submenu_page(
951
- $this->slug,
952
- $title,
953
- $title,
954
- $capability,
955
- $this->slug . '_' . $slug,
956
- $callback
957
- );
958
- }
959
- }
960
-
961
- $this->after_create_menues();
962
- }
963
-
964
- public function after_create_menues() {
965
-
966
- }
967
-
968
- public function set_active_tab( $active_tab ) {
969
- foreach ( $this->tabs as $tab ) {
970
- if ( $tab['slug'] === $active_tab ) {
971
- $this->active_tab = $tab['slug'];
972
- }
973
- }
974
- }
975
-
976
- public function get_tabs() {
977
- return $this->tabs;
978
- }
979
-
980
- public function get_active_tab() {
981
- return $this->active_tab;
982
- }
983
-
984
- public function get_slug() {
985
- return $this->slug;
986
- }
987
-
988
- public function get_plugin_name() {
989
- return $this->plugin_name;
990
- }
991
-
992
- public function get_path( $view ) {
993
- return trailingslashit( $this->base_path ) . $view . '.php';
994
- }
995
-
996
- public function create_options_page() {
997
- require_once trailingslashit( $this->base_path ) . 'main.php';
998
- }
999
-
1000
- public function next_step() {
1001
- $return = array();
1002
- $i = 0;
1003
- foreach ( $this->tabs as $tab ) {
1004
- if ( $this->active_tab === $tab['slug'] && isset( $tab['next_step_instructions'] ) ) {
1005
- $next_tab_slug = isset( $this->tabs[ $i + 1 ]['slug'] ) ? $this->tabs[ $i + 1 ]['slug'] : $tab['slug'];
1006
- $return = array(
1007
- 'instructions' => $tab['next_step_instructions'],
1008
- 'next_tab' => $next_tab_slug
1009
- );
1010
- }
1011
- $i++;
1012
- }
1013
- return $return;
1014
- }
1015
-
1016
- public function get_connected_accounts() {
1017
- global $sbspf_settings;
1018
-
1019
- if ( isset( $sbspf_settings['connected_accounts'] ) ) {
1020
- return $sbspf_settings['connected_accounts'];
1021
- }
1022
- return array();
1023
- }
1024
-
1025
- public static function connect_account( $args ) {
1026
- global $sbspf_settings;
1027
-
1028
- // do connection
1029
-
1030
- // random fake data
1031
- $account_id = time();
1032
-
1033
- $sbspf_settings['connected_accounts'][ $account_id ] = array(
1034
- 'access_token' => 'at_' . str_shuffle( $account_id ),
1035
- 'channel_id' => $account_id,
1036
- 'username' => 'test' . $account_id,
1037
- 'is_valid' => true,
1038
- 'last_checked' => time(),
1039
- 'profile_picture' => $args['profile_picture']
1040
- );
1041
-
1042
- update_option( 'sbspf_settings', $sbspf_settings );
1043
-
1044
- return $sbspf_settings['connected_accounts'][ $account_id ];
1045
- }
1046
-
1047
- public function default_tooltip_text() {
1048
- return '<span class="screen-reader-text">' . __( 'What does this mean?', $this->vars->text_domain() ) . '</span>' . sby_admin_icon( 'question-circle' );
1049
- }
1050
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SB_YOUTUBE_Admin {
7
+
8
+ protected $vars;
9
+
10
+ protected $base_path;
11
+
12
+ protected $slug;
13
+
14
+ protected $plugin_name;
15
+
16
+ protected $capability;
17
+
18
+ protected $tabs;
19
+
20
+ protected $active_tab;
21
+
22
+ protected $settings_sections;
23
+
24
+ protected $display_your_feed_sections;
25
+
26
+ protected $option_name;
27
+
28
+ protected $pro_only;
29
+
30
+ protected $types;
31
+
32
+ protected $layouts;
33
+
34
+ protected $false_fields;
35
+
36
+ protected $textarea_fields;
37
+
38
+ public function __construct( $vars, $base_path, $slug, $plugin_name, $capability, $icon, $position, $tabs, $settings, $active_tab = false, $option_name = 'sbspf_settings' ) {
39
+ $this->vars = $vars;
40
+ $this->base_path = $base_path;
41
+ $this->slug = $slug;
42
+ $this->plugin_name = $plugin_name;
43
+ $this->capability = $capability;
44
+ $this->icon = $icon;
45
+ $this->position = $position;
46
+
47
+ $this->tabs = $tabs;
48
+
49
+ if ( $active_tab ) {
50
+ $this->set_active_tab( $active_tab );
51
+ } else {
52
+ $this->set_active_tab( $tabs[0]['slug'] );
53
+ }
54
+ $this->settings = $settings;
55
+ $this->option_name = $option_name;
56
+ $this->pro_only = array();
57
+ $this->false_fields = array();
58
+ $this->textarea_fields = array();
59
+ $this->display_your_feed_sections = array();
60
+ }
61
+
62
+ public function get_vars() {
63
+ return $this->vars;
64
+ }
65
+
66
+ public function get_option_name() {
67
+ return $this->option_name;
68
+ }
69
+
70
+ public function verify_post( $post ) {
71
+ return wp_verify_nonce( $post[ $this->option_name . '_validate' ], $this->option_name . '_validate' );
72
+ }
73
+
74
+ public function hidden_fields_for_tab( $tab ) {
75
+ wp_nonce_field( $this->get_option_name() . '_validate', $this->get_option_name() . '_validate', true, true );
76
+ ?>
77
+ <input type="hidden" name="<?php echo $this->get_option_name() . '_tab_marker'; ?>" value="<?php echo esc_attr( $tab ); ?>"/>
78
+ <?php
79
+ }
80
+
81
+ public function init() {
82
+ add_action( 'admin_menu', array( $this, 'create_menus' ) );
83
+ add_action( 'admin_init', array( $this, 'settings_init' ) );
84
+ add_action( 'admin_init', array( $this, 'additional_settings_init' ) );
85
+
86
+ }
87
+
88
+ public function settings_init() {
89
+ $text_domain = $this->vars->text_domain();
90
+ /**
91
+ * Configure Tab
92
+ */
93
+ $args = array(
94
+ 'id' => 'sbspf_types',
95
+ 'tab' => 'configure',
96
+ 'save_after' => 'true'
97
+ );
98
+ $this->add_settings_section( $args );
99
+
100
+ /* Types */
101
+ $args = array(
102
+ 'name' => 'type',
103
+ 'section' => 'sbspf_types',
104
+ 'callback' => 'types',
105
+ 'title' => '<label>' . __( 'Feed Type', $text_domain ) .'</label>',
106
+ 'shortcode' => array(
107
+ 'key' => 'type',
108
+ 'example' => 'channel',
109
+ 'description' => __( 'Type of feed to display', $text_domain ) . ' e.g. channel, playlist, search, favorites, live',
110
+ 'display_section' => 'configure'
111
+ ),
112
+ 'types' => $this->types
113
+ );
114
+ $this->add_settings_field( $args );
115
+
116
+ /* Cache */
117
+ $args = array(
118
+ 'name' => 'cache',
119
+ 'section' => 'sbspf_types',
120
+ 'callback' => 'cache',
121
+ 'title' => __( 'Check for new posts', $text_domain )
122
+ );
123
+ $this->add_settings_field( $args );
124
+
125
+ /**
126
+ * Customize Tab
127
+ */
128
+ $args = array(
129
+ 'title' => __( 'General', $text_domain ),
130
+ 'id' => 'sbspf_general',
131
+ 'tab' => 'customize',
132
+ 'save_after' => 'true'
133
+ );
134
+ $this->add_settings_section( $args );
135
+
136
+ /* Width and Height */
137
+ $select_options = array(
138
+ array(
139
+ 'label' => '%',
140
+ 'value' => '%'
141
+ ),
142
+ array(
143
+ 'label' => 'px',
144
+ 'value' => 'px'
145
+ )
146
+ );
147
+
148
+ $args = array(
149
+ 'name' => 'width',
150
+ 'default' => '100',
151
+ 'section' => 'sbspf_general',
152
+ 'callback' => 'text',
153
+ 'min' => 1,
154
+ 'size' => 4,
155
+ 'title' => __( 'Width of Feed', $text_domain ),
156
+ 'shortcode' => array(
157
+ 'key' => 'width',
158
+ 'example' => '300px',
159
+ 'description' => __( 'The width of your feed. Any number with a unit like "px" or "%".', $text_domain ),
160
+ 'display_section' => 'customize'
161
+ ),
162
+ 'select_name' => 'widthunit',
163
+ 'select_options' => $select_options,
164
+ 'hidden' => array(
165
+ 'callback' => 'checkbox',
166
+ 'name' => 'width_responsive',
167
+ 'label' => __( 'Set to be 100% width on mobile?', $text_domain ),
168
+ 'before' => '<div id="sbspf_width_options">',
169
+ 'after' => '</div>',
170
+ 'tooltip_info' => __( 'If you set a width on the feed then this will be used on mobile as well as desktop. Check this setting to set the feed width to be 100% on mobile so that it is responsive.', $text_domain )
171
+ ),
172
+ );
173
+ $this->add_settings_field( $args );
174
+
175
+ $select_options = array(
176
+ array(
177
+ 'label' => '%',
178
+ 'value' => '%'
179
+ ),
180
+ array(
181
+ 'label' => 'px',
182
+ 'value' => 'px'
183
+ )
184
+ );
185
+ $args = array(
186
+ 'name' => 'height',
187
+ 'default' => '',
188
+ 'section' => 'sbspf_general',
189
+ 'callback' => 'text',
190
+ 'min' => 1,
191
+ 'size' => 4,
192
+ 'title' => __( 'Height of Feed', $text_domain ),
193
+ 'shortcode' => array(
194
+ 'key' => 'height',
195
+ 'example' => '500px',
196
+ 'description' => __( 'The height of your feed. Any number with a unit like "px" or "em".', $text_domain ),
197
+ 'display_section' => 'customize'
198
+ ),
199
+ 'select_name' => 'heightunit',
200
+ 'select_options' => $select_options,
201
+ );
202
+ $this->add_settings_field( $args );
203
+
204
+ $args = array(
205
+ 'name' => 'background',
206
+ 'default' => '',
207
+ 'section' => 'sbspf_general',
208
+ 'callback' => 'color',
209
+ 'title' => __( 'Background Color', $text_domain ),
210
+ 'shortcode' => array(
211
+ 'key' => 'background',
212
+ 'example' => '#f00',
213
+ 'description' => __( 'Background color for the feed. Any hex color code.', $text_domain ),
214
+ 'display_section' => 'customize'
215
+ ),
216
+ );
217
+ $this->add_settings_field( $args );
218
+
219
+ $args = array(
220
+ 'title' => __( 'Layout', $text_domain ),
221
+ 'id' => 'sbspf_layout',
222
+ 'tab' => 'customize',
223
+ 'save_after' => 'true'
224
+ );
225
+ $this->add_settings_section( $args );
226
+
227
+ $args = array(
228
+ 'name' => 'layout',
229
+ 'section' => 'sbspf_layout',
230
+ 'callback' => 'layout',
231
+ 'title' => __( 'Layout Type', $text_domain ),
232
+ 'layouts' => $this->layouts,
233
+ 'shortcode' => array(
234
+ 'key' => 'layout',
235
+ 'example' => 'list',
236
+ 'description' => __( 'How your posts are display visually.', $text_domain ),
237
+ 'display_section' => 'layout'
238
+ )
239
+ );
240
+ $this->add_settings_field( $args );
241
+ }
242
+
243
+ public function additional_settings_init() {
244
+
245
+ }
246
+
247
+ public function add_false_field( $name, $tab ) {
248
+ $this->false_fields[ $tab ][] = $name;
249
+ }
250
+
251
+ public function get_false_fields( $tab ) {
252
+ if ( isset( $this->false_fields[ $tab ] ) ) {
253
+ return $this->false_fields[ $tab ];
254
+ }
255
+
256
+ return array();
257
+ }
258
+
259
+ public function add_textarea_field( $name, $tab ) {
260
+ $this->textarea_fields[ $tab ][] = $name;
261
+ }
262
+
263
+ public function get_textarea_fields( $tab ) {
264
+ if ( isset( $this->textarea_fields[ $tab ] ) ) {
265
+ return $this->textarea_fields[ $tab ];
266
+ }
267
+
268
+ return array();
269
+ }
270
+
271
+ public function blank() {
272
+
273
+ }
274
+
275
+ public function add_settings_section( $args ) {
276
+ $title = isset( $args['title'] ) ? $args['title'] : '';
277
+ $callback = isset( $args['callback'] ) ? $args['callback'] : array( $this, 'blank' );
278
+ add_settings_section(
279
+ $args['id'],
280
+ $title,
281
+ $callback,
282
+ $args['id']
283
+ );
284
+
285
+ $save_after = isset( $args['save_after'] ) ? $args['save_after'] : false;
286
+ $pro = isset( $args['pro'] ) && ($args['pro'] !== false) ? $args['pro'] : false;
287
+ $this->settings_sections[ $args['tab'] ][] = array(
288
+ 'id' => $args['id'],
289
+ 'save_after' => $save_after,
290
+ 'pro' => $pro
291
+
292
+ );
293
+ }
294
+
295
+ public function add_settings_field( $args ) {
296
+ $title_after = '';
297
+ $shortcode = false;
298
+ if ( isset( $args['shortcode'] ) ) {
299
+ $title_after = isset( $args['shortcode']['after'] ) ? $args['shortcode']['after'] : '';
300
+ $shortcode = $args['shortcode'];
301
+ }
302
+
303
+ if ( $shortcode ) {
304
+ $this->display_your_feed_sections[ $shortcode['display_section'] ]['settings'][] = $shortcode;
305
+ if ( isset( $args['pro'] ) ) {
306
+ $this->pro_only[] = $args['name'];
307
+ }
308
+ }
309
+
310
+ if ( $args['callback'] === 'types' ) {
311
+ $formatted_label = '<label for="' . $this->option_name . '_' . $args['name'] . '">' . $args['title'] .'</label>';
312
+ $formatted_label .= '<code class="sbspf_shortcode">type'. "\n";
313
+ foreach ( $args['types'] as $type ) {
314
+ $shortcode = array(
315
+ 'key' => $type['slug'],
316
+ 'example' => $type['example'],
317
+ 'description' => $type['description'],
318
+ 'display_section' => 'configure'
319
+ );
320
+ $this->display_your_feed_sections[ $shortcode['display_section'] ]['settings'][] = $shortcode;
321
+ if ( isset( $type['pro'] ) ) {
322
+ $this->pro_only[] = $type['slug'];
323
+ }
324
+
325
+ $formatted_label .= 'Eg: type=' . $type['slug'] . '<br>';
326
+ $formatted_label .= $type['slug'] . '="' . substr( $type['example'], 0, 14) . '"<br>';
327
+
328
+ }
329
+ $formatted_label .= '</code><br>';
330
+
331
+ if ( isset( $args['shortcode']['after_description'] ) ) {
332
+ $formatted_label .= $args['shortcode']['after_description'];
333
+ }
334
+
335
+ $title = $formatted_label;
336
+ } else {
337
+ $title = $this->format_title( $args['title'], $args['name'], $shortcode, $title_after );
338
+ }
339
+
340
+ if ( $args['callback'] === 'checkbox' || (isset( $args['falsefield'] ) && $args['falsefield'] === true) ) {
341
+ $tab = 'none';
342
+ foreach ( $this->settings_sections as $key => $settings_sections ) {
343
+ foreach ( $settings_sections as $this_tab_sections ) {
344
+ if ( $this_tab_sections['id'] === $args['section'] ) {
345
+ $tab = $key;
346
+ }
347
+ }
348
+
349
+ }
350
+ $this->add_false_field( $args['name'], $tab );
351
+ }
352
+
353
+ if ( $args['callback'] === 'layout' || $args['callback'] === 'sub_option' ) {
354
+ $tab = 'none';
355
+ foreach ( $this->settings_sections as $key => $settings_sections ) {
356
+ foreach ( $settings_sections as $this_tab_sections ) {
357
+ if ( $this_tab_sections['id'] === $args['section'] ) {
358
+ $tab = $key;
359
+ }
360
+ }
361
+
362
+ }
363
+ $sub_options = isset( $args['layouts'] ) ? $args['layouts'] : $args['sub_options'];
364
+ foreach ( $sub_options as $sub_option ) {
365
+ if ( isset( $sub_option['options'] ) ) {
366
+ foreach( $sub_option['options'] as $sub_sub_option ) {
367
+ if ( ! empty( $sub_sub_option['shortcode'] ) ) {
368
+ $key = ! empty( $sub_sub_option['shortcode']['key'] ) ? $sub_sub_option['shortcode']['key'] : $sub_option['slug'] . $sub_sub_option['name'];
369
+ $example = ! empty( $sub_sub_option['shortcode']['example'] ) ? $sub_sub_option['shortcode']['example'] : '';
370
+ $description = ! empty( $sub_sub_option['shortcode']['description'] ) ? $sub_sub_option['shortcode']['description'] : '';
371
+ $display_section = ! empty( $sub_sub_option['shortcode']['display_section'] ) ? $sub_sub_option['shortcode']['display_section'] : str_replace( 'sbspf_', '', $args['section'] );
372
+ $sub_shortcode = array(
373
+ 'key' => $key,
374
+ 'example' => $example,
375
+ 'description' => $description,
376
+ 'display_section' => $display_section
377
+ );
378
+ if ( isset( $this->display_your_feed_sections[ $display_section ] ) ) {
379
+ $this->display_your_feed_sections[ $display_section ]['settings'][] = $sub_shortcode;
380
+ if ( isset( $sub_sub_option['pro'] ) ) {
381
+ $this->pro_only[] = $key;
382
+ }
383
+ }
384
+ }
385
+ if ( $sub_sub_option['callback'] === 'checkbox' ) {
386
+ $this->add_false_field( $sub_option['slug'] . $sub_sub_option['name'], $tab );
387
+ }
388
+ }
389
+ }
390
+ }
391
+ }
392
+
393
+ if ( $args['callback'] === 'textarea' ) {
394
+ $tab = 'none';
395
+ foreach ( $this->settings_sections as $key => $settings_sections ) {
396
+ foreach ( $settings_sections as $this_tab_sections ) {
397
+ if ( $this_tab_sections['id'] === $args['section'] ) {
398
+ $tab = $key;
399
+ }
400
+ }
401
+
402
+ }
403
+ $this->add_textarea_field( $args['name'], $tab );
404
+ }
405
+
406
+ add_settings_field(
407
+ $args['name'],
408
+ $title,
409
+ array( $this, $args['callback'] ),
410
+ $args['section'],
411
+ $args['section'],
412
+ $args
413
+ );
414
+
415
+ if ( isset( $args['hidden'] ) ) {
416
+ if ( $args['hidden']['callback'] === 'checkbox' ) {
417
+ $tab = 'none';
418
+ foreach ( $this->settings_sections as $key => $settings_sections ) {
419
+ foreach ( $settings_sections as $this_tab_sections ) {
420
+ if ( $this_tab_sections['id'] === $args['section'] ) {
421
+ $tab = $key;
422
+ }
423
+ }
424
+
425
+ }
426
+ $this->add_false_field( $args['hidden']['name'], $tab );
427
+ }
428
+ }
429
+ }
430
+
431
+ public function set_feed_types( $types ) {
432
+ $this->types = $types;
433
+ }
434
+
435
+ public function set_feed_layouts( $layouts ) {
436
+ $this->layouts = $layouts;
437
+ }
438
+
439
+ public function set_display_table_sections( $headings ) {
440
+ foreach ( $headings as $heading ) {
441
+ $this->display_your_feed_sections[ $heading['slug'] ] = array(
442
+ 'label' => $heading['label'],
443
+ 'settings' => array()
444
+ );
445
+ }
446
+ }
447
+
448
+ public function checkbox( $args ) {
449
+ $default = isset( $args['default'] ) ? $args['default'] : false;
450
+ $selected = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
451
+ $label = isset( $args['label'] ) ? $args['label'] : __( 'Yes' );
452
+ $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
453
+ $has_shortcode = isset( $args['has_shortcode'] ) && $args['has_shortcode'] && isset( $args['shortcode_example'] ) ? '1' : '';
454
+ $pro_flag = isset( $args['pro'] ) ? ' <span class="sbspf_pro_only"></span>' : '';
455
+ echo $pro_flag;
456
+ ?>
457
+ <input name="<?php echo $this->option_name .'['.esc_attr( $args['name'] ).']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>" class="sbspf_single_checkbox" type="checkbox"<?php if ( $selected ) echo ' checked'; ?>/>
458
+ <label for="<?php echo $this->option_name . '_' . $args['name'] . $has_shortcode; ?>"><?php echo esc_html( $label ); ?></label><?php if ( $has_shortcode === '1' ) : ?><code class="sbspf_shortcode"> <?php echo $args['name'] . "\n"; ?>
459
+ Eg: <?php echo $args['name']; ?>=<?php echo $args['shortcode_example']; ?></code><br><?php endif; ?>
460
+ <?php if ( isset( $args['tooltip_info'] ) ) : ?>
461
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
462
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
463
+ <?php
464
+ endif;
465
+ }
466
+
467
+ public function multi_checkbox( $args ) {
468
+ $default = isset( $args['default'] ) ? $args['default'] : false;
469
+ $selection_array = isset( $this->settings[ $args['name'] ] ) ? (array)$this->settings[ $args['name'] ] : (array)$default;
470
+ $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
471
+ $index = 0;
472
+ ?>
473
+ <?php foreach ( $args['select_options'] as $select_option ) :
474
+ $selected = in_array( $select_option['value'], $selection_array, true );
475
+ $pro_only = (isset( $select_option['pro'] ) && $select_option['pro']) ? ' sbspf_pro_only' : '';
476
+ $class = ! empty( $select_option['class'] ) ? ' ' . $select_option['class'] : '';
477
+ ?>
478
+ <div class="sbspf_multi_checkbox_option<?php echo $pro_only . $class; ?>">
479
+ <input name="<?php echo $this->option_name .'['.esc_attr( $args['name'] ).'][]'; ?>" id="<?php echo $this->option_name . '_' . $args['name']. '_' . $index; ?>" value="<?php echo esc_attr( $select_option['value'] ); ?>" type="checkbox"<?php if ( $selected ) echo ' checked'; ?>/>
480
+ <label for="<?php echo $this->option_name . '_' . $args['name'] . '_' . $index; ?>"><?php echo esc_html( $select_option['label'] ); ?></label>
481
+ </div>
482
+ <?php
483
+ $index++;
484
+ endforeach; ?>
485
+
486
+ <?php if ( isset( $args['tooltip_info'] ) ) : ?>
487
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
488
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
489
+ <?php
490
+ endif;
491
+ }
492
+
493
+ public function text( $args ) {
494
+ $default = isset( $args['default'] ) ? $args['default'] : '';
495
+ $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
496
+ $size = ( isset( $args['size'] ) ) ? ' size="'. $args['size'].'"' : '';
497
+ $class = isset( $args['class'] ) ? ' class="'. esc_attr( $args['class'] ) . '"' : '';
498
+
499
+ $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
500
+ $pro_flag = isset( $args['pro'] ) ? ' <span class="sbspf_pro_only"></span>' : '';
501
+ echo $pro_flag;
502
+
503
+ if ( isset( $args['min'] ) ) :
504
+ $min = ( isset( $args['min'] ) ) ? ' min="'. $args['min'].'"' : '';
505
+ $max = ( isset( $args['max'] ) ) ? ' max="'. $args['max'].'"' : '';
506
+ $step = ( isset( $args['step'] ) ) ? ' step="'. $args['step'].'"' : '';
507
+ $class = isset( $args['class'] ) ? ' class="sbspf_number_field sbspf_size_' . $args['size'] . ' '. esc_attr( $args['class'] ) . '"' : ' class="sbspf_number_field sbspf_size_' . $args['size'] . '"';
508
+ ?>
509
+ <input name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>"<?php echo $class; ?> type="number"<?php echo $size; ?><?php echo $min; ?><?php echo $max; ?><?php echo $step; ?> value="<?php echo esc_attr( $value ); ?>" />
510
+ <?php elseif ( isset( $args['color'] ) ) : ?>
511
+ <input name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>" class="sbspf_colorpicker" type="text" value="#<?php echo esc_attr( str_replace('#', '', $value ) ); ?>" />
512
+ <?php else: ?>
513
+ <input name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>"<?php echo $class; ?> type="text" value="<?php echo esc_attr( stripslashes( $value ) ); ?>" />
514
+ <?php endif; ?>
515
+
516
+ <?php if ( isset( $args['select_options'] ) ) :
517
+ $value = isset( $this->settings[ $args['select_name'] ] ) ? $this->settings[ $args['select_name'] ] : $args['select_options'][0]['value'];
518
+ ?>
519
+ <select name="<?php echo $this->option_name.'['.$args['select_name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['select_name']; ?>">
520
+ <?php foreach ( $args['select_options'] as $select_option ) : ?>
521
+ <option value="<?php echo esc_attr( $select_option['value'] ); ?>"<?php if ( (string)$select_option['value'] === (string)$value ) echo ' selected'; ?>><?php echo esc_html( $select_option['label'] ); ?></option>
522
+ <?php endforeach; ?>
523
+ </select>
524
+ <?php endif; ?>
525
+
526
+ <?php if ( isset( $args['hidden'] ) ) : ?>
527
+
528
+ <?php
529
+ if ( is_callable( array( $this, $args['hidden']['callback'] ) ) ){
530
+ echo $args['hidden']['before'];
531
+ call_user_func_array(
532
+ array( $this, $args['hidden']['callback'] ),
533
+ array( $args['hidden'] )
534
+ );
535
+ echo $args['hidden']['after'];
536
+ }
537
+ ?>
538
+ <?php endif; ?>
539
+
540
+ <?php if ( isset( $args['additional'] ) ) : ?>
541
+ <?php echo $args['additional']; ?>
542
+ <?php endif; ?>
543
+
544
+ <?php if ( isset( $args['tooltip_info'] ) ) : ?>
545
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
546
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
547
+ <?php
548
+ endif;
549
+ }
550
+
551
+ public function select( $args ) {
552
+ $default = isset( $args['default'] ) ? $args['default'] : $args['options'][0]['value'];
553
+ $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
554
+
555
+ if ( isset( $args['min'] ) && isset( $args['max'] ) && ((int)$args['min'] < (int)$args['max']) && empty( $args['options'] ) ) {
556
+ $args['options'] = array();
557
+ $i = (int)$args['min'];
558
+
559
+ while ( $i <= (int)$args['max'] ) {
560
+ $args['options'][] = array(
561
+ 'label' => $i,
562
+ 'value' => $i
563
+ );
564
+ $i++;
565
+ }
566
+ }
567
+
568
+ $tooltip_text = isset( $args['tooltip_text'] ) ? $args['label'] : $this->default_tooltip_text();
569
+ $pro_class = isset( $args['pro'] ) ? ' class="sbspf_pro_only"' : '';
570
+ ?>
571
+ <select<?php echo $pro_class; ?> name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>">
572
+ <?php foreach ( $args['options'] as $select_option ) : ?>
573
+ <option value="<?php echo esc_attr( $select_option['value'] ); ?>"<?php if ( (string)$select_option['value'] === (string)$value ) echo ' selected'; ?>><?php echo esc_html( $select_option['label'] ); ?></option>
574
+ <?php endforeach; ?>
575
+ </select>
576
+
577
+ <?php if ( isset( $args['additional'] ) ) : ?>
578
+ <?php echo $args['additional']; ?>
579
+ <?php endif; ?>
580
+
581
+ <?php if ( isset( $args['tooltip_info'] ) ) : ?>
582
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $tooltip_text; ?></a>
583
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo $args['tooltip_info']; ?></p>
584
+ <?php endif;
585
+ }
586
+
587
+ public function textarea( $args ) {
588
+ $default = isset( $args['default'] ) ? $args['default'] : '';
589
+ $value = isset( $this->settings[ $args['name'] ] ) ? stripslashes( $this->settings[ $args['name'] ] ) : $default;
590
+ $pro_class = isset( $args['pro'] ) ? ' class="sbspf_pro_only"' : '';
591
+
592
+ if ( isset( $args['tooltip_info'] ) ) : ?>
593
+ <span><?php echo $args['tooltip_info']; ?></span><br>
594
+ <?php endif; ?>
595
+
596
+ <textarea<?php echo $pro_class; ?> name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" id="<?php echo $this->option_name . '_' . $args['name']; ?>"rows="7"><?php echo $value; ?></textarea>
597
+
598
+ <?php if ( isset( $args['note'] ) ) : ?>
599
+ <br><span class="sbspf_note"><?php echo $args['note']; ?></span>
600
+ <?php endif;
601
+ }
602
+
603
+ public function color( $args ) {
604
+ $args['color'] = true;
605
+ $this->text( $args );
606
+ }
607
+
608
+ public function types( $args ) {
609
+ $type_selected = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $args['types'][0]['slug'];
610
+
611
+ foreach ( $args['types'] as $type ) :
612
+ $input_type = isset( $type['input_type'] ) ? $type['input_type'] : 'connected_account';
613
+ $selected = ! empty( $this->settings[ $type['slug'] ] ) ? $this->settings[ $type['slug'] ] : $type['default'];
614
+ if ( $input_type === 'connected_account' ) {
615
+ $selected = isset( $this->settings[ $type['slug'] . '_ids' ] ) ? $this->settings[ $type['slug'] . '_ids' ] : array();
616
+ }
617
+ $on_select = isset( $type['onselect'] ) ? $type['onselect'] : false;
618
+ $pro_class = isset( $type['pro'] ) ? ' sbspf_pro_only' : '';
619
+ ?>
620
+ <div class="sbspf_row sbspf_type_row<?php echo $pro_class; ?>" style="min-height: 29px;">
621
+ <div class="sbspf_col sbspf_one">
622
+ <input type="radio" name="<?php echo $this->option_name.'['.esc_attr( $args['name'] ).']'; ?>" class="sbspf_type_input" id="sbspf_type_<?php echo esc_attr( $type['slug'] ); ?>" value="<?php echo esc_attr( $type['slug'] ); ?>"<?php if ( $type_selected === $type['slug'] ) echo 'checked'; ?>>
623
+ <label class="sbspf_radio_label" for="sbspf_type_<?php echo esc_attr( $type['slug'] ); ?>"><?php echo esc_html( $type['label'] ); ?>: <a class="sbspf_type_tooltip_link" href="JavaScript:void(0);"><i class="fa fa-question-circle" aria-hidden="true" style="margin-left: 2px;"></i></a></label>
624
+ </div>
625
+ <div class="sbspf_col sbspf_two">
626
+ <?php if ( $input_type === 'text' ) :
627
+ $placeholder = isset( $type['note'] ) ? ' placeholder="' . esc_attr( $type['note'] ). '"' : '';
628
+ ?>
629
+ <input name="<?php echo $this->option_name.'['.esc_attr( $type['slug'] ).']'; ?>" id="sbspf_<?php echo esc_attr( $type['slug'] ); ?>" type="text" value="<?php echo esc_attr( $selected ); ?>" size="45"<?php echo $placeholder; ?>>
630
+ <?php else :
631
+ $connected_accounts = $this->get_connected_accounts(); ?>
632
+ <div class="sbspf_<?php echo esc_attr( $type['slug'] ); ?>_feed_ids_wrap">
633
+ <?php foreach ( $connected_accounts as $connected_account ) : if ( in_array( $connected_account['channel_id'], $selected, true ) ) : ?>
634
+ <div id="sbspf_<?php echo esc_attr( $type['slug'] ); ?>_feed_id_<?php echo esc_attr( $connected_account['channel_id'] ); ?>" class="sbspf_<?php echo esc_attr( $type['slug'] ); ?>_feed_account_wrap">
635
+ <strong><?php echo esc_html( $connected_account['username'] ); ?></strong> <span>(<?php echo esc_attr( $connected_account['channel_id'] ); ?>)</span><input type="hidden" name="<?php echo $this->option_name.'['.esc_attr( $type['slug'] ).'_feed_ids][]'; ?>" value="<?php echo esc_attr( $connected_account['channel_id'] ); ?>">
636
+ </div>
637
+ <?php endif; endforeach; ?>
638
+ </div>
639
+ <?php if ( empty( $selected ) ) : ?>
640
+ <p class="sbspf_no_accounts" style="margin-top: -3px; margin-right: 10px;"><?php _e( 'Connect an account above', $this->vars->text_domain() ); ?></p>
641
+ <?php endif; ?>
642
+
643
+ <?php endif; ?>
644
+ <?php if ( $input_type !== 'text' && isset( $type['note'] ) ) : ?>
645
+ <br><span class="sbspf_note"><?php echo $type['note']; ?></span>
646
+ <?php endif; ?>
647
+ </div>
648
+ <?php if ( $on_select ) : ?>
649
+ <div class="sbspf_onselect">
650
+ <?php call_user_func_array( array( $this, $on_select ), array( $type ) ); ?>
651
+ </div>
652
+ <?php endif; ?>
653
+
654
+ <div class="sbspf_tooltip sbspf_type_tooltip sbspf_more_info">
655
+ <?php if ( ! empty( $type['tooltip'] ) ) : ?>
656
+ <?php echo $type['tooltip']; ?>
657
+ <?php endif; ?>
658
+ </div>
659
+
660
+
661
+
662
+ </div>
663
+ <?php endforeach;
664
+ }
665
+
666
+ public function sub_option( $args ) {
667
+ $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : 'related';
668
+ $pro_flag = isset( $args['pro'] ) ? ' <span class="sbspf_pro_only"></span>' : '';
669
+ echo $pro_flag;
670
+ $cta_options = $args['sub_options'];
671
+ ?>
672
+ <?php if ( ! empty( $args['before'] ) ) {
673
+ echo $args['before'];
674
+ }?>
675
+
676
+ <div class="sbspf_sub_options">
677
+ <?php foreach ( $cta_options as $sub_option ) :
678
+ $pro_class = isset( $sub_option['pro'] ) ? ' sbspf_pro_only' : '';
679
+ ?>
680
+ <div class="sbspf_sub_option_cell<?php echo esc_attr( $pro_class ); ?>">
681
+ <input class="sbspf_sub_option_type" id="sbspf_sub_option_type_<?php echo esc_attr( $sub_option['slug'] ); ?>" name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" type="radio" value="<?php echo esc_attr( $sub_option['slug'] ); ?>"<?php if ( $sub_option['slug'] === $value ) echo ' checked'?>><label for="sbspf_sub_option_type_<?php echo esc_attr( $sub_option['slug'] ); ?>"><span class="sbspf_label"><?php echo $sub_option['label']; ?></span></label>
682
+ </div>
683
+ <?php endforeach; ?>
684
+
685
+ <div class="sbspf_box_setting">
686
+ <?php if ( isset( $cta_options ) ) : foreach ( $cta_options as $sub_option ) :
687
+ $pro_class = isset( $sub_option['pro'] ) ? ' sbspf_pro_only' : '';
688
+ ?>
689
+ <div class="sbspf_sub_option_settings sbspf_sub_option_type_<?php echo esc_attr( $sub_option['slug'] ) . $pro_class; ?>">
690
+
691
+ <div class="sbspf_sub_option_setting">
692
+ <?php echo sby_admin_icon( 'info-circle', 'sbspf_small_svg' ); ?>&nbsp;&nbsp;&nbsp;<span class="sbspf_note" style="margin-left: 0;"><?php echo $sub_option['note']; ?></span>
693
+ </div>
694
+ <?php if ( ! empty( $sub_option['options'] ) ) : ?>
695
+ <?php foreach ( $sub_option['options'] as $option ) :
696
+ $option['name'] = $sub_option['slug'].$option['name'];
697
+ ?>
698
+ <div class="sbspf_sub_option_setting">
699
+ <?php if ( $option['callback'] !== 'checkbox' ) :
700
+ if ( isset( $option['shortcode'] ) ) : ?>
701
+ <label title="<?php echo __( 'Click for shortcode option', $this->vars->text_domain() ); ?>"><?php echo $option['label']; ?></label><code class="sbspf_shortcode"> <?php echo $option['name'] . "\n"; ?>
702
+ Eg: <?php echo $option['name']; ?>=<?php echo $option['shortcode']['example']; ?></code><br>
703
+ <?php else: ?>
704
+ <label><?php echo $option['label']; ?></label><br>
705
+ <?php endif; ?>
706
+ <?php else:
707
+ $option['shortcode_example'] = $option['shortcode']['example'];
708
+ $option['has_shortcode'] = true;
709
+ endif; ?>
710
+ <?php call_user_func_array( array( $this, $option['callback'] ), array( $option ) ); ?>
711
+
712
+ </div>
713
+
714
+ <?php endforeach; ?>
715
+ <?php endif; ?>
716
+
717
+ </div>
718
+
719
+ <?php endforeach; endif; ?>
720
+ </div>
721
+ </div>
722
+ <?php
723
+ }
724
+
725
+ public function cache( $args ) {
726
+ $social_network = $this->vars->social_network();
727
+ $type_selected = isset( $this->settings['caching_type'] ) ? $this->settings['caching_type'] : 'page';
728
+ $caching_time = isset( $this->settings['caching_time'] ) ? $this->settings['caching_time'] : 1;
729
+ $cache_time_unit_selected = isset( $this->settings['cache_time_unit'] ) ? $this->settings['cache_time_unit'] : 'hours';
730
+ $cache_cron_interval_selected = isset( $this->settings['cache_cron_interval'] ) ? $this->settings['cache_cron_interval'] : '';
731
+ $cache_cron_time = isset( $this->settings['cache_cron_time'] ) ? $this->settings['cache_cron_time'] : '';
732
+ $cache_cron_am_pm = isset( $this->settings['cache_cron_am_pm'] ) ? $this->settings['cache_cron_am_pm'] : '';
733
+
734
+ ?>
735
+ <div class="sbspf_cache_settings_wrap">
736
+ <div class="sbspf_row">
737
+ <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" class="sbspf_caching_type_input" id="sbspf_caching_type_page" value="page"<?php if ( $type_selected === 'page' ) echo ' checked'?>>
738
+ <label class="sbspf_radio_label" for="sbspf_caching_type_page"><?php _e ( 'When the page loads', $this->vars->text_domain() ); ?></label>
739
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);" style="position: relative; top: 2px;"><?php echo $this->default_tooltip_text() ?></a>
740
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __( "Your %s data is temporarily cached by the plugin in your WordPress database. There are two ways that you can set the plugin to check for new data:<br><br>
741
+ <b>1. When the page loads</b><br>Selecting this option means that when the cache expires then the plugin will check %s for new posts the next time that the feed is loaded. You can choose how long this data should be cached for with a minimum time of 15 minutes. If you set the time to 60 minutes then the plugin will clear the cached data after that length of time, and the next time the page is viewed it will check for new data. <b>Tip:</b> If you're experiencing an issue with the plugin not updating automatically then try enabling the setting labeled <b>'Force cache to clear on interval'</b> which is located on the 'Customize' tab.<br><br>
742
+ <b>2. In the background</b><br>Selecting this option means that the plugin will check for new data in the background so that the feed is updated behind the scenes. You can select at what time and how often the plugin should check for new data using the settings below. <b>Please note</b> that the plugin will initially check for data from Instagram when the page first loads, but then after that will check in the background on the schedule selected - unless the cache is cleared.", $this->vars->text_domain() ), $social_network, $social_network ); ?>
743
+ </p>
744
+ </div>
745
+ <div class="sbspf_row sbspf-caching-page-options" style="display: none;">
746
+ <?php _e ( 'Every', $this->vars->text_domain() ); ?>:
747
+ <input name="<?php echo $this->option_name.'[caching_time]'; ?>" type="text" value="<?php echo esc_attr( $caching_time ); ?>" size="4">
748
+ <select name="<?php echo $this->option_name.'[caching_time_unit]'; ?>">
749
+ <option value="minutes"<?php if ( $cache_time_unit_selected === 'minutes' ) echo ' selected'?>><?php _e ( 'Minutes', $this->vars->text_domain() ); ?></option>
750
+ <option value="hours"<?php if ( $cache_time_unit_selected === 'hours' ) echo ' selected'?>><?php _e ( 'Hours', $this->vars->text_domain() ); ?></option>
751
+ <option value="days"<?php if ( $cache_time_unit_selected === 'days' ) echo ' selected'?>><?php _e ( 'Days', $this->vars->text_domain() ); ?></option>
752
+ </select>
753
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php _e ( 'What does this mean?', $this->vars->text_domain() ); ?></a>
754
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __("Your %s posts are temporarily cached by the plugin in your WordPress database. You can choose how long the posts should be cached for. If you set the time to 1 hour then the plugin will clear the cache after that length of time and check %s for posts again.", $this->vars->text_domain() ), $social_network, $social_network ); ?></p>
755
+ </div>
756
+
757
+ <div class="sbspf_row">
758
+ <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" id="sbspf_caching_type_cron" class="sbspf_caching_type_input" value="background" <?php if ( $type_selected === 'background' ) echo ' checked'?>>
759
+ <label class="sbspf_radio_label" for="sbspf_caching_type_cron"><?php _e ( 'In the background', $this->vars->text_domain() ); ?></label>
760
+ </div>
761
+ <div class="sbspf_row sbspf-caching-cron-options" style="display: block;">
762
+
763
+ <select name="<?php echo $this->option_name.'[cache_cron_interval]'; ?>" id="sbspf_cache_cron_interval">
764
+ <option value="30mins"<?php if ( $cache_cron_interval_selected === '30mins' ) echo ' selected'?>><?php _e ( 'Every 30 minutes', $this->vars->text_domain() ); ?></option>
765
+ <option value="1hour"<?php if ( $cache_cron_interval_selected === '1hour' ) echo ' selected'?>><?php _e ( 'Every hour', $this->vars->text_domain() ); ?></option>
766
+ <option value="12hours"<?php if ( $cache_cron_interval_selected === '12hours' ) echo ' selected'?>><?php _e ( 'Every 12 hours', $this->vars->text_domain() ); ?></option>
767
+ <option value="24hours"<?php if ( $cache_cron_interval_selected === '24hours' ) echo ' selected'?>><?php _e ( 'Every 24 hours', $this->vars->text_domain() ); ?></option>
768
+ </select>
769
+
770
+ <div id="sbspf-caching-time-settings" style="">
771
+ <?php _e ( 'at', $this->vars->text_domain() ); ?>
772
+ <select name="<?php echo $this->option_name.'[cache_cron_time]'; ?>" style="width: 80px">
773
+ <option value="1"<?php if ( (int)$cache_cron_time === 1 ) echo ' selected'?>>1:00</option>
774
+ <option value="2"<?php if ( (int)$cache_cron_time === 2 ) echo ' selected'?>>2:00</option>
775
+ <option value="3"<?php if ( (int)$cache_cron_time === 3 ) echo ' selected'?>>3:00</option>
776
+ <option value="4"<?php if ( (int)$cache_cron_time === 4 ) echo ' selected'?>>4:00</option>
777
+ <option value="5"<?php if ( (int)$cache_cron_time === 5 ) echo ' selected'?>>5:00</option>
778
+ <option value="6"<?php if ( (int)$cache_cron_time === 6 ) echo ' selected'?>>6:00</option>
779
+ <option value="7"<?php if ( (int)$cache_cron_time === 7 ) echo ' selected'?>>7:00</option>
780
+ <option value="8"<?php if ( (int)$cache_cron_time === 8 ) echo ' selected'?>>8:00</option>
781
+ <option value="9"<?php if ( (int)$cache_cron_time === 9 ) echo ' selected'?>>9:00</option>
782
+ <option value="10"<?php if ( (int)$cache_cron_time === 10 ) echo ' selected'?>>10:00</option>
783
+ <option value="11"<?php if ( (int)$cache_cron_time === 11 ) echo ' selected'?>>11:00</option>
784
+ <option value="0"<?php if ( (int)$cache_cron_time === 0 ) echo ' selected'?>>12:00</option>
785
+ </select>
786
+
787
+ <select name="<?php echo $this->option_name.'[cache_cron_am_pm]'; ?>" style="width: 50px">
788
+ <option value="am"<?php if ( $cache_cron_am_pm === 'am' ) echo ' selected'?>><?php _e ( 'AM', $this->vars->text_domain() ); ?></option>
789
+ <option value="pm"<?php if ( $cache_cron_am_pm === 'pm' ) echo ' selected'?>><?php _e ( 'PM', $this->vars->text_domain() ); ?></option>
790
+ </select>
791
+ </div>
792
+
793
+ <?php
794
+ if ( wp_next_scheduled( 'sbspf_feed_update' ) ) {
795
+ $time_format = get_option( 'time_format' );
796
+ if ( ! $time_format ) {
797
+ $time_format = 'g:i a';
798
+ }
799
+ //
800
+ $schedule = wp_get_schedule( 'sbspf_feed_update' );
801
+ if ( $schedule == '30mins' ) $schedule = __( 'every 30 minutes', $this->vars->text_domain() );
802
+ if ( $schedule == 'twicedaily' ) $schedule = __( 'every 12 hours', $this->vars->text_domain() );
803
+ $sbspf_next_cron_event = wp_next_scheduled( 'sbspf_feed_update' );
804
+ echo '<p class="sbspf-caching-sched-notice"><span><b>' . __( 'Next check', $this->vars->text_domain() ) . ': ' . date( $time_format, $sbspf_next_cron_event + sbspf_get_utc_offset() ) . ' (' . $schedule . ')</b> - ' . __( 'Note: Saving the settings on this page will clear the cache and reset this schedule', $this->vars->text_domain() ) . '</span></p>';
805
+ } else {
806
+ echo '<p style="font-size: 11px; color: #666;">' . __( 'Nothing currently scheduled', $this->vars->text_domain() ) . '</p>';
807
+ }
808
+ ?>
809
+ </div>
810
+ </div>
811
+ <?php
812
+ }
813
+
814
+ public function layout( $args ) {
815
+ $default = isset( $args['default'] ) ? $args['default'] : $args['layouts'][0]['slug'];
816
+ $value = isset( $this->settings[ $args['name'] ] ) ? $this->settings[ $args['name'] ] : $default;
817
+ ?>
818
+ <div class="sbspf_layouts">
819
+ <?php foreach ( $args['layouts'] as $layout ) :
820
+ $pro_class = isset( $layout['pro'] ) ? ' sbspf_pro_only' : '';
821
+ ?>
822
+ <div class="sbspf_layout_cell<?php echo $pro_class; ?>">
823
+ <input class="sbspf_layout_type" id="sbspf_layout_type_<?php echo esc_attr( $layout['slug'] ); ?>" name="<?php echo $this->option_name.'['.$args['name'].']'; ?>" type="radio" value="<?php echo esc_attr( $layout['slug'] ); ?>"<?php if ( $layout['slug'] === $value ) echo ' checked'?>><label for="sbspf_layout_type_<?php echo esc_attr( $layout['slug'] ); ?>"><span class="sbspf_label"><?php echo $layout['label']; ?></span><img src="<?php echo esc_url( $this->vars->plugin_url() . $layout['image'] ); ?>"></label>
824
+ </div>
825
+ <?php endforeach; ?>
826
+
827
+ <div class="sbspf_layout_options_wrap">
828
+ <?php foreach ( $args['layouts'] as $layout ) :
829
+ $pro_class = isset( $layout['pro'] ) ? ' sbspf_pro_only' : '';
830
+ ?>
831
+ <div class="sbspf_layout_settings sbspf_layout_type_<?php echo esc_attr( $layout['slug'] ) . $pro_class; ?>">
832
+
833
+ <div class="sbspf_layout_setting">
834
+ <?php echo sby_admin_icon( 'info-circle' ); ?>&nbsp;&nbsp;&nbsp;<span class="sbspf_note" style="margin-left: 0;"><?php echo $layout['note']; ?></span>
835
+ </div>
836
+ <?php if ( ! empty( $layout['options'] ) ) : ?>
837
+ <?php foreach ( $layout['options'] as $option ) :
838
+ $option['name'] = $layout['slug'].$option['name'];
839
+ $option['shortcode']['example'] = isset( $option['shortcode']['example'] ) ? $option['shortcode']['example'] : $option['shortcode_example'];
840
+
841
+ ?>
842
+ <div class="sbspf_layout_setting">
843
+ <?php if ( $option['callback'] !== 'checkbox' ) : ?>
844
+ <label title="<?php echo __( 'Click for shortcode option', $this->vars->text_domain() ); ?>"><?php echo $option['label']; ?></label><code class="sbspf_shortcode"> <?php echo $option['name'] . "\n"; ?>
845
+ Eg: <?php echo $option['name']; ?>=<?php echo $option['shortcode']['example']; ?></code><br>
846
+ <?php else:
847
+
848
+ $option['has_shortcode'] = true;
849
+ endif; ?>
850
+ <?php call_user_func_array( array( $this, $option['callback'] ), array( $option ) ); ?>
851
+
852
+ </div>
853
+
854
+ <?php endforeach; ?>
855
+ <?php endif; ?>
856
+
857
+ </div>
858
+
859
+ <?php endforeach; ?>
860
+ </div>
861
+ </div>
862
+ <?php
863
+ }
864
+
865
+ public function instructions( $args ) {
866
+ ?>
867
+ <div class="sbspf_instructions_wrap">
868
+ <?php echo $args['instructions']?>
869
+ </div>
870
+ <?php
871
+ }
872
+
873
+ public function format_title( $label, $name, $shortcode_args = false, $after = '' ) {
874
+ $formatted_label = '<label for="' . $this->option_name . '_' . $name . '">' . $label .'</label>';
875
+ if ( $shortcode_args ) {
876
+ $formatted_label .= '<code class="sbspf_shortcode"> ' . $shortcode_args['key'] . "\n";
877
+ $formatted_label .= 'Eg: ' . $shortcode_args['key'] . '=' . $shortcode_args['example'] . '</code><br>';
878
+ }
879
+ $formatted_label .= $after;
880
+
881
+ return $formatted_label;
882
+ }
883
+
884
+ public function validate_options( $input, $tab ) {
885
+ $updated_options = get_option( $this->option_name, array() );
886
+ $false_if_empty_keys = $this->get_false_fields( $tab );
887
+ $textarea_keys = $this->get_textarea_fields( $tab );
888
+
889
+ foreach ( $false_if_empty_keys as $false_key ) {
890
+ $updated_options[ $false_key ] = false;
891
+ }
892
+
893
+ foreach ( $input as $key => $val ) {
894
+ if ( in_array( $key, $false_if_empty_keys ) ) {
895
+ $updated_options[ $key ] = ($val === 'on');
896
+ } elseif ( in_array( $key, $textarea_keys ) ) {
897
+ $updated_options[ $key ] = sanitize_textarea_field( $val );
898
+ } elseif ( is_array( $val ) ) {
899
+ $updated_options[ $key ] = array();
900
+ foreach ( $val as $key2 => $val2 ) {
901
+ $updated_options[ $key ][ $key2 ] = sanitize_text_field( $val2 );
902
+ }
903
+ } else {
904
+ $updated_options[ $key ] = sanitize_text_field( $val );
905
+ }
906
+ }
907
+
908
+
909
+ if ( $tab === 'configure' ) {
910
+ do_action( $this->option_name . '_after_configure_save', $updated_options );
911
+ } elseif ( $tab === 'customize' ) {
912
+ do_action( $this->option_name . '_after_customize_save', $updated_options );
913
+ }
914
+
915
+ return $updated_options;
916
+ }
917
+
918
+
919
+ public function update_options( $new_settings ) {
920
+ update_option( $this->get_option_name(), $new_settings );
921
+ $this->settings = $new_settings;
922
+ }
923
+
924
+ public function get_sections( $tab ) {
925
+ if ( isset( $this->settings_sections[ $tab ] ) ) {
926
+ return $this->settings_sections[ $tab ];
927
+ }
928
+ return array();
929
+ }
930
+
931
+ public function create_menus() {
932
+ add_menu_page(
933
+ $this->plugin_name,
934
+ $this->plugin_name,
935
+ $this->capability,
936
+ $this->slug,
937
+ array( $this, 'create_options_page' ),
938
+ $this->icon,
939
+ $this->position
940
+ );
941
+
942
+ foreach ( $this->tabs as $tab ) {
943
+ if ( $tab['slug'] !== 'configure'
944
+ && ! isset( $tab['has_nav_tab'] ) ) {
945
+ $title = isset( $tab['title'] ) ? $tab['title'] : '';
946
+ $capability = isset( $tab['capability'] ) ? $tab['capability'] : 'manage_options';
947
+ $slug = isset( $tab['slug'] ) ? $tab['slug'] : '';
948
+ $callback = isset( $tab['callback'] ) ? $tab['callback'] : array( $this, 'create_options_page' );
949
+
950
+ add_submenu_page(
951
+ $this->slug,
952
+ $title,
953
+ $title,
954
+ $capability,
955
+ $this->slug . '_' . $slug,
956
+ $callback
957
+ );
958
+ }
959
+ }
960
+
961
+ $this->after_create_menues();
962
+ }
963
+
964
+ public function after_create_menues() {
965
+
966
+ }
967
+
968
+ public function set_active_tab( $active_tab ) {
969
+ foreach ( $this->tabs as $tab ) {
970
+ if ( $tab['slug'] === $active_tab ) {
971
+ $this->active_tab = $tab['slug'];
972
+ }
973
+ }
974
+ }
975
+
976
+ public function get_tabs() {
977
+ return $this->tabs;
978
+ }
979
+
980
+ public function get_active_tab() {
981
+ return $this->active_tab;
982
+ }
983
+
984
+ public function get_slug() {
985
+ return $this->slug;
986
+ }
987
+
988
+ public function get_plugin_name() {
989
+ return $this->plugin_name;
990
+ }
991
+
992
+ public function get_path( $view ) {
993
+ return trailingslashit( $this->base_path ) . $view . '.php';
994
+ }
995
+
996
+ public function create_options_page() {
997
+ require_once trailingslashit( $this->base_path ) . 'main.php';
998
+ }
999
+
1000
+ public function next_step() {
1001
+ $return = array();
1002
+ $i = 0;
1003
+ foreach ( $this->tabs as $tab ) {
1004
+ if ( $this->active_tab === $tab['slug'] && isset( $tab['next_step_instructions'] ) ) {
1005
+ $next_tab_slug = isset( $this->tabs[ $i + 1 ]['slug'] ) ? $this->tabs[ $i + 1 ]['slug'] : $tab['slug'];
1006
+ $return = array(
1007
+ 'instructions' => $tab['next_step_instructions'],
1008
+ 'next_tab' => $next_tab_slug
1009
+ );
1010
+ }
1011
+ $i++;
1012
+ }
1013
+ return $return;
1014
+ }
1015
+
1016
+ public function get_connected_accounts() {
1017
+ global $sbspf_settings;
1018
+
1019
+ if ( isset( $sbspf_settings['connected_accounts'] ) ) {
1020
+ return $sbspf_settings['connected_accounts'];
1021
+ }
1022
+ return array();
1023
+ }
1024
+
1025
+ public static function connect_account( $args ) {
1026
+ global $sbspf_settings;
1027
+
1028
+ // do connection
1029
+
1030
+ // random fake data
1031
+ $account_id = time();
1032
+
1033
+ $sbspf_settings['connected_accounts'][ $account_id ] = array(
1034
+ 'access_token' => 'at_' . str_shuffle( $account_id ),
1035
+ 'channel_id' => $account_id,
1036
+ 'username' => 'test' . $account_id,
1037
+ 'is_valid' => true,
1038
+ 'last_checked' => time(),
1039
+ 'profile_picture' => $args['profile_picture']
1040
+ );
1041
+
1042
+ update_option( 'sbspf_settings', $sbspf_settings );
1043
+
1044
+ return $sbspf_settings['connected_accounts'][ $account_id ];
1045
+ }
1046
+
1047
+ public function default_tooltip_text() {
1048
+ return '<span class="screen-reader-text">' . __( 'What does this mean?', $this->vars->text_domain() ) . '</span>' . sby_admin_icon( 'question-circle' );
1049
+ }
1050
+ }
inc/admin/class-sby-admin.php CHANGED
@@ -1,1108 +1,1108 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SBY_Admin extends SB_YOUTUBE_Admin {
7
-
8
- public function settings_init() {
9
- $text_domain = $this->vars->text_domain();
10
-
11
- $defaults = sby_settings_defaults();
12
- $this->add_false_field( 'disablecdn', 'customize' );
13
-
14
- /**
15
- * Configure Tab
16
- */
17
- $args = array(
18
- 'id' => 'sbspf_types',
19
- 'tab' => 'configure',
20
- 'save_after' => 'true'
21
- );
22
- $this->add_settings_section( $args );
23
-
24
- $locator_html = '';
25
- if ( SBY_Feed_Locator::count_unique() > -1 ) {
26
- $locator_html .= '<div class="sby_locations_link">';
27
- $locator_html .= '<a href="?page=' . $this->slug .'&amp;tab=allfeeds"><svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="search" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-search fa-w-16 fa-2x"><path fill="currentColor" d="M508.5 468.9L387.1 347.5c-2.3-2.3-5.3-3.5-8.5-3.5h-13.2c31.5-36.5 50.6-84 50.6-136C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c52 0 99.5-19.1 136-50.6v13.2c0 3.2 1.3 6.2 3.5 8.5l121.4 121.4c4.7 4.7 12.3 4.7 17 0l22.6-22.6c4.7-4.7 4.7-12.3 0-17zM208 368c-88.4 0-160-71.6-160-160S119.6 48 208 48s160 71.6 160 160-71.6 160-160 160z" class=""></path></svg> ' . __( 'Feed Finder', $text_domain ) . '</a>';
28
- $locator_html .= '</div>';
29
- }
30
- /* Types */
31
- $args = array(
32
- 'name' => 'type',
33
- 'section' => 'sbspf_types',
34
- 'callback' => 'types',
35
- 'title' => '<label>' . __( 'Select a Feed Type', $text_domain ) .'</label>',
36
- 'shortcode' => array(
37
- 'key' => 'type',
38
- 'example' => 'channel',
39
- 'description' => __( 'Type of feed to display', $text_domain ) . ' e.g. channel, playlist, search, favorites, live',
40
- 'after_description' => $locator_html,
41
- 'display_section' => 'configure'
42
- ),
43
- 'types' => $this->types
44
- );
45
- $this->add_settings_field( $args );
46
-
47
- $this->pro_only[] = 'type';
48
-
49
-
50
- /* Cache */
51
- $args = array(
52
- 'name' => 'cache',
53
- 'section' => 'sbspf_types',
54
- 'callback' => 'cache',
55
- 'title' => __( 'Check for new posts', $text_domain )
56
- );
57
- $this->add_settings_field( $args );
58
-
59
-
60
- /**
61
- * Customize Tab
62
- */
63
- $args = array(
64
- 'title' => __( 'General', $text_domain ),
65
- 'id' => 'sbspf_general',
66
- 'tab' => 'customize',
67
- 'save_after' => 'true'
68
- );
69
- $this->add_settings_section( $args );
70
-
71
- /* Width and Height */
72
- $select_options = array(
73
- array(
74
- 'label' => '%',
75
- 'value' => '%'
76
- ),
77
- array(
78
- 'label' => 'px',
79
- 'value' => 'px'
80
- )
81
- );
82
-
83
- $args = array(
84
- 'name' => 'width',
85
- 'default' => '100',
86
- 'section' => 'sbspf_general',
87
- 'callback' => 'text',
88
- 'min' => 1,
89
- 'size' => 4,
90
- 'title' => __( 'Width of Feed', $text_domain ),
91
- 'shortcode' => array(
92
- 'key' => 'width',
93
- 'example' => '300px',
94
- 'description' => __( 'The width of your feed. Any number with a unit like "px" or "%".', $text_domain ),
95
- 'display_section' => 'customize'
96
- ),
97
- 'select_name' => 'widthunit',
98
- 'select_options' => $select_options,
99
- 'hidden' => array(
100
- 'callback' => 'checkbox',
101
- 'name' => 'width_responsive',
102
- 'label' => __( 'Set to be 100% width on mobile?', $text_domain ),
103
- 'before' => '<div id="sbspf_width_options">',
104
- 'after' => '</div>',
105
- 'tooltip_info' => __( 'If you set a width on the feed then this will be used on mobile as well as desktop. Check this setting to set the feed width to be 100% on mobile so that it is responsive.', $text_domain )
106
- ),
107
- );
108
- $this->add_settings_field( $args );
109
-
110
- $select_options = array(
111
- array(
112
- 'label' => '%',
113
- 'value' => '%'
114
- ),
115
- array(
116
- 'label' => 'px',
117
- 'value' => 'px'
118
- )
119
- );
120
- $args = array(
121
- 'name' => 'height',
122
- 'default' => '',
123
- 'section' => 'sbspf_general',
124
- 'callback' => 'text',
125
- 'min' => 1,
126
- 'size' => 4,
127
- 'title' => __( 'Height of Feed', $text_domain ),
128
- 'shortcode' => array(
129
- 'key' => 'height',
130
- 'example' => '500px',
131
- 'description' => __( 'The height of your feed. Any number with a unit like "px" or "em".', $text_domain ),
132
- 'display_section' => 'customize'
133
- ),
134
- 'select_name' => 'heightunit',
135
- 'select_options' => $select_options,
136
- );
137
- $this->add_settings_field( $args );
138
-
139
- $args = array(
140
- 'name' => 'background',
141
- 'default' => '',
142
- 'section' => 'sbspf_general',
143
- 'callback' => 'color',
144
- 'title' => __( 'Background Color', $text_domain ),
145
- 'shortcode' => array(
146
- 'key' => 'background',
147
- 'example' => '#f00',
148
- 'description' => __( 'Background color for the feed. Any hex color code.', $text_domain ),
149
- 'display_section' => 'customize'
150
- ),
151
- );
152
- $this->add_settings_field( $args );
153
-
154
- $args = array(
155
- 'title' => __( 'Layout', $text_domain ),
156
- 'id' => 'sbspf_layout',
157
- 'tab' => 'customize',
158
- 'save_after' => 'true'
159
- );
160
- $this->add_settings_section( $args );
161
-
162
- $args = array(
163
- 'name' => 'layout',
164
- 'section' => 'sbspf_layout',
165
- 'callback' => 'layout',
166
- 'title' => __( 'Layout Type', $text_domain ),
167
- 'layouts' => $this->layouts,
168
- 'shortcode' => array(
169
- 'key' => 'layout',
170
- 'example' => 'list',
171
- 'description' => __( 'How your posts are displayed visually.', $text_domain ) . ' e.g. list, grid, gallery',
172
- 'display_section' => 'layout'
173
- )
174
- );
175
- $this->add_settings_field( $args );
176
-
177
- $this->pro_only[] = 'carouselcols';
178
- $this->pro_only[] = 'carouselcolsmobile';
179
- $this->pro_only[] = 'carouselrows';
180
- $this->pro_only[] = 'carouselloop';
181
- $this->pro_only[] = 'carouselarrows';
182
- $this->pro_only[] = 'carouselpag';
183
- $this->pro_only[] = 'carouselautoplay';
184
- $this->pro_only[] = 'carouseltime';
185
-
186
- $select_options = array(
187
- array(
188
- 'label' => 'px',
189
- 'value' => 'px'
190
- ),
191
- array(
192
- 'label' => '%',
193
- 'value' => '%'
194
- )
195
- );
196
-
197
- $args = array(
198
- 'name' => 'num',
199
- 'default' => $defaults['num'],
200
- 'section' => 'sbspf_layout',
201
- 'callback' => 'text',
202
- 'min' => 1,
203
- 'max' => 50,
204
- 'size' => 4,
205
- 'title' => __( 'Number of Videos', $text_domain ),
206
- 'additional' => '<span class="sby_note">' . __( 'Number of videos to show initially.', $text_domain ) . '</span>',
207
- 'shortcode' => array(
208
- 'key' => 'num',
209
- 'example' => 5,
210
- 'description' => __( 'The number of videos in the feed', $text_domain ),
211
- 'display_section' => 'layout'
212
- )
213
- );
214
- $this->add_settings_field( $args );
215
-
216
- $include_options = array(
217
- array(
218
- 'label' => __( 'Play Icon', $text_domain ),
219
- 'value' => 'icon'
220
- ),
221
- array(
222
- 'label' => __( 'Title', $text_domain ),
223
- 'value' => 'title',
224
- 'pro' => true
225
- ),
226
- array(
227
- 'label' => __( 'User Name', $text_domain ),
228
- 'value' => 'user',
229
- 'pro' => true
230
- ),
231
- array(
232
- 'label' => __( 'Views', $text_domain ),
233
- 'value' => 'views',
234
- 'pro' => true
235
- ),
236
- array(
237
- 'label' => __( 'Date', $text_domain ),
238
- 'value' => 'date',
239
- 'pro' => true
240
- ),
241
- array(
242
- 'label' => __( 'Live Stream Countdown (when applies)', $text_domain ),
243
- 'value' => 'countdown',
244
- 'pro' => true
245
- ),
246
- array(
247
- 'label' => __( 'Stats (like and comment counts)', $text_domain ),
248
- 'value' => 'stats',
249
- 'pro' => true
250
- ),
251
- array(
252
- 'label' => __( 'Description', $text_domain ),
253
- 'value' => 'description',
254
- 'pro' => true
255
- ),
256
- );
257
- $args = array(
258
- 'name' => 'include',
259
- 'default' => $defaults['include'],
260
- 'section' => 'sbspf_layout',
261
- 'callback' => 'multi_checkbox',
262
- 'title' => __( 'Show/Hide', $text_domain ),
263
- 'shortcode' => array(
264
- 'key' => 'include',
265
- 'example' => '"icon"',
266
- 'description' => __( 'What video information will display in the feed. eg.', $text_domain ) . ' icon',
267
- 'display_section' => 'customize'
268
- ),
269
- 'select_options' => $include_options,
270
- );
271
- $this->add_settings_field( $args );
272
-
273
- $args = array(
274
- 'name' => 'itemspacing',
275
- 'default' => 5,
276
- 'section' => 'sbspf_layout',
277
- 'callback' => 'text',
278
- 'min' => 0,
279
- 'size' => 4,
280
- 'title' => __( 'Spacing between videos', $text_domain ),
281
- 'shortcode' => array(
282
- 'key' => 'itemspacing',
283
- 'example' => '5px',
284
- 'description' => __( 'The spacing/padding around the videos in the feed. Any number with a unit like "px" or "em".', $text_domain ),
285
- 'display_section' => 'layout'
286
- ),
287
- 'select_name' => 'itemspacingunit',
288
- 'select_options' => $select_options,
289
- );
290
- $this->add_settings_field( $args );
291
-
292
- $select_options = array(
293
- array(
294
- 'label' => __( 'Below video thumbnail', $text_domain ),
295
- 'value' => 'below'
296
- ),
297
- array(
298
- 'label' => __( 'Next to video thumbnail', $text_domain ),
299
- 'value' => 'side'
300
- )
301
- );
302
- $args = array(
303
- 'name' => 'infoposition',
304
- 'default' => 'below',
305
- 'section' => 'sbspf_layout',
306
- 'pro' => true,
307
- 'callback' => 'select',
308
- 'title' => __( 'Position', $text_domain ),
309
- 'shortcode' => array(
310
- 'key' => 'infoposition',
311
- 'example' => 'side',
312
- 'description' => __( 'Where the information (title, description, stats) will display. eg.', $text_domain ) . ' below, side, none',
313
- 'display_section' => 'customize'
314
- ),
315
- 'options' => $select_options,
316
- );
317
- $this->add_settings_field( $args );
318
-
319
- $args = array(
320
- 'title' => __( 'Header', $text_domain ),
321
- 'id' => 'sbspf_header',
322
- 'tab' => 'customize',
323
- );
324
- $this->add_settings_section( $args );
325
-
326
- $args = array(
327
- 'name' => 'showheader',
328
- 'section' => 'sbspf_header',
329
- 'callback' => 'checkbox',
330
- 'title' => __( 'Show Header', $text_domain ),
331
- 'default' => true,
332
- 'shortcode' => array(
333
- 'key' => 'showheader',
334
- 'example' => 'false',
335
- 'description' => __( 'Include a header for this feed.', $text_domain ),
336
- 'display_section' => 'header'
337
- )
338
- );
339
- $this->add_settings_field( $args );
340
-
341
- $args = array(
342
- 'name' => 'showdescription',
343
- 'section' => 'sbspf_header',
344
- 'callback' => 'checkbox',
345
- 'title' => __( 'Show Channel Description', $text_domain ),
346
- 'default' => true,
347
- 'shortcode' => array(
348
- 'key' => 'showdescription',
349
- 'example' => 'false',
350
- 'description' => __( 'Include the channel description in the header.', $text_domain ),
351
- 'display_section' => 'header'
352
- )
353
- );
354
- $this->add_settings_field( $args );
355
-
356
- $args = array(
357
- 'name' => 'showsubscribers',
358
- 'section' => 'sbspf_header',
359
- 'callback' => 'checkbox',
360
- 'pro' => true,
361
- 'title' => __( 'Show Subscribers', $text_domain ),
362
- 'default' => true,
363
- 'shortcode' => array(
364
- 'key' => 'showsubscribers',
365
- 'example' => 'false',
366
- 'description' => __( 'Include the number of subscribers in the header.', $text_domain ),
367
- 'display_section' => 'header'
368
- )
369
- );
370
- $this->add_settings_field( $args );
371
-
372
- $args = array(
373
- 'title' => __( '"Load More" Button', $text_domain ),
374
- 'id' => 'sbspf_loadmore',
375
- 'tab' => 'customize',
376
- );
377
- $this->add_settings_section( $args );
378
-
379
- $args = array(
380
- 'name' => 'showbutton',
381
- 'section' => 'sbspf_loadmore',
382
- 'callback' => 'checkbox',
383
- 'title' => __( 'Show "Load More" Button', $text_domain ),
384
- 'default' => true,
385
- 'shortcode' => array(
386
- 'key' => 'showbutton',
387
- 'example' => 'false',
388
- 'description' => __( 'Include a "Load More" button at the bottom of the feed to load more videos.', $text_domain ),
389
- 'display_section' => 'button'
390
- )
391
- );
392
- $this->add_settings_field( $args );
393
-
394
- $args = array(
395
- 'name' => 'buttoncolor',
396
- 'default' => '',
397
- 'section' => 'sbspf_loadmore',
398
- 'callback' => 'color',
399
- 'title' => __( 'Button Background Color', $text_domain ),
400
- 'shortcode' => array(
401
- 'key' => 'buttoncolor',
402
- 'example' => '#0f0',
403
- 'description' => __( 'Background color for the "Load More" button. Any hex color code.', $text_domain ),
404
- 'display_section' => 'button'
405
- ),
406
- );
407
- $this->add_settings_field( $args );
408
-
409
- $args = array(
410
- 'name' => 'buttontextcolor',
411
- 'default' => '',
412
- 'section' => 'sbspf_loadmore',
413
- 'callback' => 'color',
414
- 'title' => __( 'Button Text Color', $text_domain ),
415
- 'shortcode' => array(
416
- 'key' => 'buttontextcolor',
417
- 'example' => '#00f',
418
- 'description' => __( 'Text color for the "Load More" button. Any hex color code.', $text_domain ),
419
- 'display_section' => 'button'
420
- ),
421
- );
422
- $this->add_settings_field( $args );
423
-
424
- $args = array(
425
- 'name' => 'buttontext',
426
- 'default' => __( 'Load More...', $text_domain ),
427
- 'section' => 'sbspf_loadmore',
428
- 'callback' => 'text',
429
- 'title' => __( 'Button Text', $text_domain ),
430
- 'shortcode' => array(
431
- 'key' => 'buttontext',
432
- 'example' => '"More Videos"',
433
- 'description' => __( 'The text that appers on the "Load More" button.', $text_domain ),
434
- 'display_section' => 'button'
435
- )
436
- );
437
- $this->add_settings_field( $args );
438
-
439
- /* Subscribe button */
440
- $args = array(
441
- 'title' => __( '"Subscribe" Button', $text_domain ),
442
- 'id' => 'sbspf_subscribe',
443
- 'tab' => 'customize',
444
- 'save_after' => true
445
- );
446
- $this->add_settings_section( $args );
447
-
448
- $args = array(
449
- 'name' => 'showsubscribe',
450
- 'section' => 'sbspf_subscribe',
451
- 'callback' => 'checkbox',
452
- 'title' => __( 'Show "Subscribe" Button', $text_domain ),
453
- 'default' => true,
454
- 'shortcode' => array(
455
- 'key' => 'showsubscribe',
456
- 'example' => 'false',
457
- 'description' => __( 'Include a "Subscribe" button at the bottom of the feed to load more videos.', $text_domain ),
458
- 'display_section' => 'subscribe'
459
- )
460
- );
461
- $this->add_settings_field( $args );
462
-
463
- $args = array(
464
- 'name' => 'subscribecolor',
465
- 'default' => '',
466
- 'section' => 'sbspf_subscribe',
467
- 'callback' => 'color',
468
- 'title' => __( 'Subscribe Background Color', $text_domain ),
469
- 'shortcode' => array(
470
- 'key' => 'subscribecolor',
471
- 'example' => '#0f0',
472
- 'description' => __( 'Background color for the "Subscribe" button. Any hex color code.', $text_domain ),
473
- 'display_section' => 'subscribe'
474
- ),
475
- );
476
- $this->add_settings_field( $args );
477
-
478
- $args = array(
479
- 'name' => 'subscribetextcolor',
480
- 'default' => '',
481
- 'section' => 'sbspf_subscribe',
482
- 'callback' => 'color',
483
- 'title' => __( 'Subscribe Text Color', $text_domain ),
484
- 'shortcode' => array(
485
- 'key' => 'subscribetextcolor',
486
- 'example' => '#00f',
487
- 'description' => __( 'Text color for the "Subscribe" button. Any hex color code.', $text_domain ),
488
- 'display_section' => 'subscribe'
489
- ),
490
- );
491
- $this->add_settings_field( $args );
492
-
493
- $args = array(
494
- 'name' => 'subscribetext',
495
- 'default' => __( 'Subscribe', $text_domain ),
496
- 'section' => 'sbspf_subscribe',
497
- 'callback' => 'text',
498
- 'title' => __( 'Subscribe Text', $text_domain ),
499
- 'shortcode' => array(
500
- 'key' => 'subscribetext',
501
- 'example' => '"Subscribe to My Channel"',
502
- 'description' => __( 'The text that appers on the "Subscribe" button.', $text_domain ),
503
- 'display_section' => 'subscribe'
504
- )
505
- );
506
- $this->add_settings_field( $args );
507
-
508
- $args = array(
509
- 'title' => __( 'Video Experience', $text_domain ),
510
- 'id' => 'sbspf_experience',
511
- 'tab' => 'customize',
512
- );
513
- $this->add_settings_section( $args );
514
-
515
- $select_options = array(
516
- array(
517
- 'label' => '9:16',
518
- 'value' => '9:16'
519
- ),
520
- array(
521
- 'label' => '3:4',
522
- 'value' => '3:4'
523
- ),
524
- );
525
- $args = array(
526
- 'name' => 'playerratio',
527
- 'default' => '9:16',
528
- 'section' => 'sbspf_experience',
529
- 'callback' => 'select',
530
- 'title' => __( 'Player Size Ratio', $text_domain ),
531
- 'shortcode' => array(
532
- 'key' => 'playerratio',
533
- 'example' => '9:16',
534
- 'description' => __( 'Player height relative to width e.g.', $text_domain ) . ' 9:16, 3:4',
535
- 'display_section' => 'experience'
536
- ),
537
- 'options' => $select_options,
538
- 'tooltip_info' => __( 'A 9:16 ratio does not leave room for video title and playback tools while a 3:4 ratio does.', $text_domain )
539
- );
540
- $this->add_settings_field( $args );
541
-
542
- $select_options = array(
543
- array(
544
- 'label' => __( 'Play when clicked', $text_domain ),
545
- 'value' => 'onclick'
546
- ),
547
- array(
548
- 'label' => 'Play automatically (desktop only)',
549
- 'value' => 'automatically'
550
- )
551
- );
552
- $args = array(
553
- 'name' => 'playvideo',
554
- 'default' => 'onclick',
555
- 'section' => 'sbspf_experience',
556
- 'callback' => 'select',
557
- 'title' => __( 'When does video play?', $text_domain ),
558
- 'shortcode' => array(
559
- 'key' => 'playvideo',
560
- 'example' => 'onclick',
561
- 'description' => __( 'What the user needs to do to play a video. eg.', $text_domain ) . ' onclick, automatically',
562
- 'display_section' => 'customize'
563
- ),
564
- 'options' => $select_options,
565
- 'tooltip_info' => __( 'List layout will not play automatically. Choose whether to play the video automatically in the player or wait until the user clicks the play button after the video is loaded.', $text_domain )
566
- );
567
- $this->add_settings_field( $args );
568
-
569
- $cta_options = array(
570
- array(
571
- 'label' => __( 'Related Videos', SBY_TEXT_DOMAIN ),
572
- 'slug' => 'related',
573
- 'pro' => true,
574
- 'note' => __( 'Display video thumbnails from the feed that play on your site when clicked.', SBY_TEXT_DOMAIN )
575
- ),
576
- array(
577
- 'label' => 'Custom Link',
578
- 'slug' => 'link',
579
- 'pro' => true,
580
- 'note' => __( 'Display a button link to a custom URL.', SBY_TEXT_DOMAIN ),
581
- 'options' => array(
582
- array(
583
- 'name' => 'instructions',
584
- 'callback' => 'instructions',
585
- 'instructions' => __( 'To set a link for each video individually, add the link and button text in the video description on YouTube in this format:', SBY_TEXT_DOMAIN ) . '<br><br><code>{Link: Button Text https://my-site.com/buy-now/my-product/}</code>',
586
- 'label' => __( 'Custom link for each video', SBY_TEXT_DOMAIN ),
587
- ),
588
- array(
589
- 'name' => 'url',
590
- 'callback' => 'text',
591
- 'label' => __( 'Default Link', SBY_TEXT_DOMAIN ),
592
- 'class' => 'large-text',
593
- 'default' => '',
594
- 'shortcode' => array(
595
- 'example' => 'https://my-site.com/buy-now/my-product/',
596
- 'description' => __( 'URL for viewer to visit for the call to action.', $text_domain ),
597
- )
598
- ),
599
- array(
600
- 'name' => 'opentype',
601
- 'callback' => 'select',
602
- 'options' => array(
603
- array(
604
- 'label' => __( 'Same window', SBY_TEXT_DOMAIN ),
605
- 'value' => 'same'
606
- ),
607
- array(
608
- 'label' => __( 'New window', SBY_TEXT_DOMAIN ),
609
- 'value' => 'newwindow'
610
- )
611
- ),
612
- 'label' => __( 'Link Open Type', SBY_TEXT_DOMAIN ),
613
- 'default' => 'same',
614
- 'shortcode' => array(
615
- 'example' => 'newwindow',
616
- 'description' => __( 'Whether to open the page in a new window or the same window.', $text_domain ),
617
- )
618
- ),
619
- array(
620
- 'name' => 'text',
621
- 'callback' => 'text',
622
- 'label' => __( 'Default Button Text', SBY_TEXT_DOMAIN ),
623
- 'default' => __( 'Learn More', SBY_TEXT_DOMAIN ),
624
- 'shortcode' => array(
625
- 'example' => 'Buy Now',
626
- 'description' => __( 'Text that appears on the call-to-action button.', $text_domain ),
627
- )
628
- ),
629
- array(
630
- 'name' => 'color',
631
- 'default' => '',
632
- 'callback' => 'color',
633
- 'label' => __( 'Button Background Color', SBY_TEXT_DOMAIN ),
634
- 'shortcode' => array(
635
- 'example' => '#0f0',
636
- 'description' => __( 'Button background. Turns opaque on hover.', $text_domain ),
637
- )
638
- ),
639
- array(
640
- 'name' => 'textcolor',
641
- 'default' => '',
642
- 'callback' => 'color',
643
- 'label' => __( 'Button Text Color', SBY_TEXT_DOMAIN ),
644
- 'shortcode' => array(
645
- 'example' => '#0f0',
646
- 'description' => __( 'Color of the text on the call-to-action-button', $text_domain ),
647
- )
648
- )
649
- )
650
- ),
651
- array(
652
- 'label' => __( 'YouTube Default', SBY_TEXT_DOMAIN ),
653
- 'slug' => 'default',
654
- 'pro' => true,
655
- 'note' => __( 'YouTube suggested videos from your channel that play on YouTube when clicked.', SBY_TEXT_DOMAIN )
656
- ),
657
- );
658
- $this->pro_only[] = 'linkurl';
659
- $this->pro_only[] = 'linkopentype';
660
- $this->pro_only[] = 'linktext';
661
- $this->pro_only[] = 'linkcolor';
662
- $this->pro_only[] = 'linktextcolor';
663
-
664
- $args = array(
665
- 'name' => 'cta',
666
- 'default' => 'related',
667
- 'section' => 'sbspf_experience',
668
- 'callback' => 'sub_option',
669
- 'pro' => true,
670
- 'sub_options' => $cta_options,
671
- 'title' => __( 'Call to Action', $text_domain ),
672
- 'before' => '<p style="margin-bottom: 10px">' . __( 'What the user sees when a video pauses or ends.', $text_domain ) . '</p>',
673
- 'shortcode' => array(
674
- 'key' => 'cta',
675
- 'example' => 'link',
676
- 'description' => __( 'What the user sees when a video pauses or ends. eg.', $text_domain ) . ' related, link',
677
- 'display_section' => 'experience'
678
- ),
679
- 'tooltip_info' => __( 'Choose what will happen after a video is paused or completes.', $text_domain )
680
- );
681
- $this->add_settings_field( $args );
682
-
683
- $args = array(
684
- 'title' => __( 'Moderation', $text_domain ),
685
- 'id' => 'sbspf_moderation',
686
- 'tab' => 'customize',
687
- 'pro' => __( 'Upgrade to Pro to enable Moderation settings', $text_domain ),
688
- );
689
- $this->add_settings_section( $args );
690
-
691
- $args = array(
692
- 'name' => 'includewords',
693
- 'default' => '',
694
- 'section' => 'sbspf_moderation',
695
- 'callback' => 'text',
696
- 'class' => 'large-text',
697
- 'title' => __( 'Show videos containing these words or hashtags', $text_domain ),
698
- 'shortcode' => array(
699
- 'key' => 'includewords',
700
- 'example' => '#filter',
701
- 'description' => __( 'Show videos that have specific text in the title or description.', $text_domain ),
702
- 'display_section' => 'customize'
703
- ),
704
- 'additional' => __( '"includewords" separate multiple words with commas, include "#" for hashtags', $text_domain )
705
- );
706
- $this->add_settings_field( $args );
707
-
708
- $args = array(
709
- 'name' => 'excludewords',
710
- 'default' => '',
711
- 'section' => 'sbspf_moderation',
712
- 'callback' => 'text',
713
- 'class' => 'large-text',
714
- 'title' => __( 'Remove videos containing these words or hashtags', $text_domain ),
715
- 'shortcode' => array(
716
- 'key' => 'excludewords',
717
- 'example' => '#filter',
718
- 'description' => __( 'Remove videos that have specific text in the title or description.', $text_domain ),
719
- 'display_section' => 'customize'
720
- ),
721
- 'additional' => __( '"excludewords" separate multiple words with commas, include "#" for hashtags', $text_domain )
722
- );
723
- $this->add_settings_field( $args );
724
- $this->pro_only[] = 'includewords';
725
- $this->pro_only[] = 'excludewords';
726
-
727
- $args = array(
728
- 'name' => 'hidevideos',
729
- 'default' => '',
730
- 'section' => 'sbspf_moderation',
731
- 'callback' => 'textarea',
732
- 'title' => __( 'Hide Specific Videos', $text_domain ),
733
- 'options' => $select_options,
734
- 'tooltip_info' => __( 'Separate IDs with commas.', $text_domain ) . '<a class="sbspf_tooltip_link" href="JavaScript:void(0);">'.$this->default_tooltip_text().'</a>
735
- <p class="sbspf_tooltip sbspf_more_info">' . __( 'These are the specific ID numbers associated with a video or with a post. You can find the ID of a video by viewing the video on YouTube and copy/pasting the ID number from the end of the URL. ex. <code>https://www.youtube.com/watch?v=<span class="sbspf-highlight">Ij1KvL8eN</span></code>', $text_domain ) . '</p>'
736
- );
737
- $this->add_settings_field( $args );
738
-
739
- $args = array(
740
- 'title' => __( 'Custom Code Snippets', $text_domain ),
741
- 'id' => 'sbspf_custom_snippets',
742
- 'tab' => 'customize'
743
- );
744
- $this->add_settings_section( $args );
745
-
746
- $args = array(
747
- 'name' => 'custom_css',
748
- 'default' => '',
749
- 'section' => 'sbspf_custom_snippets',
750
- 'callback' => 'textarea',
751
- 'title' => __( 'Custom CSS', $text_domain ),
752
- 'options' => $select_options,
753
- 'tooltip_info' => __( 'Enter your own custom CSS in the box below', $text_domain )
754
- );
755
- $this->add_settings_field( $args );
756
-
757
- $args = array(
758
- 'name' => 'custom_js',
759
- 'default' => '',
760
- 'section' => 'sbspf_custom_snippets',
761
- 'callback' => 'textarea',
762
- 'title' => __( 'Custom JavaScript', $text_domain ),
763
- 'options' => $select_options,
764
- 'tooltip_info' => __( 'Enter your own custom JavaScript/jQuery in the box below', $text_domain ),
765
- 'note' => __( 'Note: Custom JavaScript reruns every time more videos are loaded into the feed', $text_domain )
766
- );
767
- $this->add_settings_field( $args );
768
-
769
- $args = array(
770
- 'title' => __( 'GDPR', $text_domain ),
771
- 'id' => 'sbspf_gdpr',
772
- 'tab' => 'customize',
773
- 'save_after' => 'true'
774
- );
775
- $this->add_settings_section( $args );
776
-
777
- $this->add_settings_field( array(
778
- 'name' => 'gdpr',
779
- 'title' => __( 'Enable GDPR Settings', $text_domain ),
780
- 'callback' => 'gdpr', // name of the function that outputs the html
781
- 'section' => 'sbspf_gdpr', // matches the section name
782
- ));
783
-
784
- $args = array(
785
- 'title' => __( 'Advanced', $text_domain ),
786
- 'id' => 'sbspf_advanced',
787
- 'tab' => 'customize',
788
- 'save_after' => true
789
- );
790
- $this->add_settings_section( $args );
791
-
792
- $args = array(
793
- 'name' => 'preserve_settings',
794
- 'section' => 'sbspf_advanced',
795
- 'callback' => 'checkbox',
796
- 'title' => __( 'Preserve settings when plugin is removed', $text_domain ),
797
- 'default' => false,
798
- 'tooltip_info' => __( 'When removing the plugin your settings are automatically erased. Checking this box will prevent any settings from being deleted. This means that you can uninstall and reinstall the plugin without losing your settings.', $text_domain )
799
- );
800
- $this->add_settings_field( $args );
801
-
802
- $select_options = array(
803
- array(
804
- 'label' => __( 'Background', $text_domain ),
805
- 'value' => 'background'
806
- ),
807
- array(
808
- 'label' => __( 'Page', $text_domain ),
809
- 'value' => 'page'
810
- ),
811
- array(
812
- 'label' => __( 'None', $text_domain ),
813
- 'value' => 'none'
814
- )
815
- );
816
- $additional = '<input id="sby-clear-cache" class="button-secondary sbspf-button-action" data-sby-action="sby_delete_wp_posts" data-sby-confirm="'.esc_attr( 'This will permanently delete all YouTube posts from the wp_posts table and the related data in the postmeta table. Existing feeds will only have 15 or fewer videos available initially. Continue?', $text_domain ).'" style="margin-top: 1px;" type="submit" value="'.esc_attr( 'Clear YouTube Posts', $text_domain ).'">';
817
- $args = array(
818
- 'name' => 'storage_process',
819
- 'default' => '',
820
- 'section' => 'sbspf_advanced',
821
- 'callback' => 'select',
822
- 'title' => __( 'Local storage process', $text_domain ),
823
- 'options' => $select_options,
824
- 'additional' => $additional,
825
- 'tooltip_info' => __( 'To preserve your feeds and videos even if the YouTube API is unavailable, a record of each video is added to the wp_posts table in the WordPress database. Please note that changing this setting to "none" will limit the number of posts available in the feed to 15 or less.', $text_domain )
826
- );
827
- $this->add_settings_field( $args );
828
-
829
- $args = array(
830
- 'name' => 'cronclear',
831
- 'section' => 'sbspf_advanced',
832
- 'callback' => 'checkbox',
833
- 'title' => __( 'Cron Clear Cache', $text_domain ),
834
- 'default' => false,
835
- 'tooltip_info' => __( 'If your YouTube feed is not updating, your WordPress installation may have a rare issue with clearing temporary data in your database. Enable this setting to use WordPress cron to clear your feed caches.', $text_domain )
836
- );
837
- $this->add_settings_field( $args );
838
-
839
- $args = array(
840
- 'name' => 'ajaxtheme',
841
- 'section' => 'sbspf_advanced',
842
- 'callback' => 'checkbox',
843
- 'title' => __( 'Are you using an AJAX theme?', $text_domain ),
844
- 'default' => false,
845
- 'tooltip_info' => __( 'When navigating your site, if your theme uses Ajax to load content into your pages (meaning your page doesn\'t refresh) then check this setting. If you\'re not sure then it\'s best to leave this setting unchecked while checking with your theme author, otherwise checking it may cause a problem.', $text_domain )
846
- );
847
- $this->add_settings_field( $args );
848
-
849
- $args = array(
850
- 'name' => 'customtemplates',
851
- 'section' => 'sbspf_advanced',
852
- 'callback' => 'checkbox',
853
- 'title' => __( 'Enable Custom Templates', $text_domain ),
854
- 'default' => false,
855
- 'tooltip_info' => __( 'The default HTML for the feed can be replaced with custom templates added to your theme\'s folder. Enable this setting to use these templates. See <a href="https://smashballoon.com/youtube-custom-templates/" target="_blank">this guide</a>', $text_domain )
856
- );
857
- $this->add_settings_field( $args );
858
-
859
- $args = array(
860
- 'name' => 'eagerload',
861
- 'section' => 'sbspf_advanced',
862
- 'callback' => 'checkbox',
863
- 'title' => __( 'Load Iframes on Page Load', $text_domain ),
864
- 'default' => false,
865
- 'tooltip_info' => __( 'To optimize the performance of your site and feeds, the plugin loads iframes only after a visitor interacts with the feed. Enabling this setting will cause YouTube player iframes to load when the page loads. Some features may work differently when this is enabled.', $text_domain )
866
- );
867
- $this->add_settings_field( $args );
868
-
869
- $args = array(
870
- 'name' => 'enqueue_js_in_head',
871
- 'section' => 'sbspf_advanced',
872
- 'callback' => 'checkbox',
873
- 'title' => __( 'Enqueue JS file in head', $text_domain ),
874
- 'default' => false,
875
- 'tooltip_info' => __( 'Check this box if you\'d like to enqueue the JavaScript file for the plugin in the head instead of the footer.', $text_domain )
876
- );
877
- $this->add_settings_field( $args );
878
-
879
- }
880
-
881
- public function cache( $args ) {
882
- $social_network = $this->vars->social_network();
883
- $type_selected = isset( $this->settings['caching_type'] ) ? $this->settings['caching_type'] : 'page';
884
- $caching_time = isset( $this->settings['caching_time'] ) ? $this->settings['caching_time'] : 1;
885
- $cache_time_unit_selected = isset( $this->settings['cache_time_unit'] ) ? $this->settings['cache_time_unit'] : 'hours';
886
-
887
- $cache_cron_interval_selected = isset( $this->settings['cache_cron_interval'] ) ? $this->settings['cache_cron_interval'] : '';
888
- $cache_cron_time = isset( $this->settings['cache_cron_time'] ) ? $this->settings['cache_cron_time'] : '';
889
- $cache_cron_am_pm = isset( $this->settings['cache_cron_am_pm'] ) ? $this->settings['cache_cron_am_pm'] : '';
890
-
891
- ?>
892
- <div class="sbspf_cache_settings_wrap">
893
- <div class="sbspf_row">
894
- <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" class="sbspf_caching_type_input" id="sbspf_caching_type_page" value="page"<?php if ( $type_selected === 'page' ) echo ' checked'?>>
895
- <label class="sbspf_radio_label" for="sbspf_caching_type_page"><?php _e ( 'When the page loads', $this->vars->text_domain() ); ?></label>
896
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);" style="position: relative; top: 2px;"><?php echo $this->default_tooltip_text() ?></a>
897
- <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __( "Your %s data is temporarily cached by the plugin in your WordPress database. There are two ways that you can set the plugin to check for new data:<br><br>
898
- <b>1. When the page loads</b><br>Selecting this option means that when the cache expires then the plugin will check %s for new posts the next time that the feed is loaded. You can choose how long this data should be cached for with a minimum time of 15 minutes. If you set the time to 60 minutes then the plugin will clear the cached data after that length of time, and the next time the page is viewed it will check for new data. <b>Tip:</b> If you're experiencing an issue with the plugin not updating automatically then try enabling the setting labeled <b>'Force cache to clear on interval'</b> which is located on the 'Customize' tab.<br><br>
899
- <b>2. In the background</b><br>Selecting this option means that the plugin will check for new data in the background so that the feed is updated behind the scenes. You can select at what time and how often the plugin should check for new data using the settings below. <b>Please note</b> that the plugin will initially check for data from Instagram when the page first loads, but then after that will check in the background on the schedule selected - unless the cache is cleared.", $this->vars->text_domain() ), $social_network, $social_network ); ?>
900
- </p>
901
- </div>
902
- <div class="sbspf_row sbspf-caching-page-options" style="display: none;">
903
- <?php _e ( 'Every', $this->vars->text_domain() ); ?>:
904
- <input name="<?php echo $this->option_name.'[caching_time]'; ?>" type="text" value="<?php echo esc_attr( $caching_time ); ?>" size="4">
905
- <select name="<?php echo $this->option_name.'[cache_time_unit]'; ?>">
906
- <option value="minutes"<?php if ( $cache_time_unit_selected === 'minutes' ) echo ' selected'?>><?php _e ( 'Minutes', $this->vars->text_domain() ); ?></option>
907
- <option value="hours"<?php if ( $cache_time_unit_selected === 'hours' ) echo ' selected'?>><?php _e ( 'Hours', $this->vars->text_domain() ); ?></option>
908
- <option value="days"<?php if ( $cache_time_unit_selected === 'days' ) echo ' selected'?>><?php _e ( 'Days', $this->vars->text_domain() ); ?></option>
909
- </select>
910
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php _e ( 'What does this mean?', $this->vars->text_domain() ); ?></a>
911
- <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __("Your %s posts are temporarily cached by the plugin in your WordPress database. You can choose how long the posts should be cached for. If you set the time to 1 hour then the plugin will clear the cache after that length of time and check %s for posts again.", $this->vars->text_domain() ), $social_network, $social_network ); ?></p>
912
- </div>
913
-
914
- <div class="sbspf_row">
915
- <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" id="sbspf_caching_type_cron" class="sbspf_caching_type_input" value="background" <?php if ( $type_selected === 'background' ) echo ' checked'?>>
916
- <label class="sbspf_radio_label" for="sbspf_caching_type_cron"><?php _e ( 'In the background', $this->vars->text_domain() ); ?></label>
917
- </div>
918
- <div class="sbspf_row sbspf-caching-cron-options" style="display: block;">
919
-
920
- <select name="<?php echo $this->option_name.'[cache_cron_interval]'; ?>" id="sbspf_cache_cron_interval">
921
- <option value="30mins"<?php if ( $cache_cron_interval_selected === '30mins' ) echo ' selected'?>><?php _e ( 'Every 30 minutes', $this->vars->text_domain() ); ?></option>
922
- <option value="1hour"<?php if ( $cache_cron_interval_selected === '1hour' ) echo ' selected'?>><?php _e ( 'Every hour', $this->vars->text_domain() ); ?></option>
923
- <option value="12hours"<?php if ( $cache_cron_interval_selected === '12hours' ) echo ' selected'?>><?php _e ( 'Every 12 hours', $this->vars->text_domain() ); ?></option>
924
- <option value="24hours"<?php if ( $cache_cron_interval_selected === '24hours' ) echo ' selected'?>><?php _e ( 'Every 24 hours', $this->vars->text_domain() ); ?></option>
925
- </select>
926
-
927
- <div id="sbspf-caching-time-settings" style="">
928
- <?php _e ( 'at', $this->vars->text_domain() ); ?>
929
- <select name="<?php echo $this->option_name.'[cache_cron_time]'; ?>" style="width: 80px">
930
- <option value="1"<?php if ( (int)$cache_cron_time === 1 ) echo ' selected'?>>1:00</option>
931
- <option value="2"<?php if ( (int)$cache_cron_time === 2 ) echo ' selected'?>>2:00</option>
932
- <option value="3"<?php if ( (int)$cache_cron_time === 3 ) echo ' selected'?>>3:00</option>
933
- <option value="4"<?php if ( (int)$cache_cron_time === 4 ) echo ' selected'?>>4:00</option>
934
- <option value="5"<?php if ( (int)$cache_cron_time === 5 ) echo ' selected'?>>5:00</option>
935
- <option value="6"<?php if ( (int)$cache_cron_time === 6 ) echo ' selected'?>>6:00</option>
936
- <option value="7"<?php if ( (int)$cache_cron_time === 7 ) echo ' selected'?>>7:00</option>
937
- <option value="8"<?php if ( (int)$cache_cron_time === 8 ) echo ' selected'?>>8:00</option>
938
- <option value="9"<?php if ( (int)$cache_cron_time === 9 ) echo ' selected'?>>9:00</option>
939
- <option value="10"<?php if ( (int)$cache_cron_time === 10 ) echo ' selected'?>>10:00</option>
940
- <option value="11"<?php if ( (int)$cache_cron_time === 11 ) echo ' selected'?>>11:00</option>
941
- <option value="0"<?php if ( (int)$cache_cron_time === 0 ) echo ' selected'?>>12:00</option>
942
- </select>
943
-
944
- <select name="<?php echo $this->option_name.'[cache_cron_am_pm]'; ?>" style="width: 50px">
945
- <option value="am"<?php if ( $cache_cron_am_pm === 'am' ) echo ' selected'?>><?php _e ( 'AM', $this->vars->text_domain() ); ?></option>
946
- <option value="pm"<?php if ( $cache_cron_am_pm === 'pm' ) echo ' selected'?>><?php _e ( 'PM', $this->vars->text_domain() ); ?></option>
947
- </select>
948
- </div>
949
-
950
- <?php
951
- if ( wp_next_scheduled( 'sbspf_feed_update' ) ) {
952
- $time_format = get_option( 'time_format' );
953
- if ( ! $time_format ) {
954
- $time_format = 'g:i a';
955
- }
956
- //
957
- $schedule = wp_get_schedule( 'sbspf_feed_update' );
958
- if ( $schedule == '30mins' ) $schedule = __( 'every 30 minutes', $this->vars->text_domain() );
959
- if ( $schedule == 'twicedaily' ) $schedule = __( 'every 12 hours', $this->vars->text_domain() );
960
- $sbspf_next_cron_event = wp_next_scheduled( 'sbspf_feed_update' );
961
- echo '<p class="sbspf-caching-sched-notice"><span><b>' . __( 'Next check', $this->vars->text_domain() ) . ': ' . date( $time_format, $sbspf_next_cron_event + sbspf_get_utc_offset() ) . ' (' . $schedule . ')</b> - ' . __( 'Note: Saving the settings on this page will clear the cache and reset this schedule', $this->vars->text_domain() ) . '</span></p>';
962
- } else {
963
- echo '<p style="font-size: 11px; color: #666;">' . __( 'Nothing currently scheduled', $this->vars->text_domain() ) . '</p>';
964
- }
965
- ?>
966
- </div>
967
- </div>
968
- <?php
969
- }
970
-
971
- public function gdpr( $args ) {
972
- $gdpr = ( isset( $this->settings['gdpr'] ) ) ? $this->settings['gdpr'] : 'auto';
973
- $select_options = array(
974
- array(
975
- 'label' => __( 'Automatic', 'youtube-feed' ),
976
- 'value' => 'auto'
977
- ),
978
- array(
979
- 'label' => __( 'Yes', 'youtube-feed' ),
980
- 'value' => 'yes'
981
- ),
982
- array(
983
- 'label' => __( 'No', 'youtube-feed' ),
984
- 'value' => 'no'
985
- )
986
- )
987
- ?>
988
- <?php
989
- $gdpr_list = "<ul class='sby-list'>
990
- <li>" . __('YouTube Player API will not be loaded.', 'youtube-feed') . "</li>
991
- <li>" . __('Thumbnail images for videos will display instead of actual video.', 'youtube-feed') . "</li>
992
- <li>" . __('To view videos, visitors will click on links to view the video on youtube.com.', 'youtube-feed') . "</li>
993
- </ul>";
994
- ?>
995
- <div>
996
- <select name="<?php echo $this->option_name.'[gdpr]'; ?>" id="sbspf_gdpr_setting">
997
- <?php foreach ( $select_options as $select_option ) :
998
- $selected = $select_option['value'] === $gdpr ? ' selected' : '';
999
- ?>
1000
- <option value="<?php echo esc_attr( $select_option['value'] ); ?>"<?php echo $selected; ?> ><?php echo esc_html( $select_option['label'] ); ?></option>
1001
- <?php endforeach; ?>
1002
- </select>
1003
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $this->default_tooltip_text(); ?></a>
1004
- <div class="sbspf_tooltip sbspf_more_info gdpr_tooltip">
1005
-
1006
- <p><span><?php _e("Yes", 'youtube-feed' ); ?>:</span> <?php _e("Enabling this setting prevents all videos and external code from loading on your website. To accommodate this, some features of the plugin will be disabled or limited.", 'youtube-feed' ); ?> <a href="JavaScript:void(0);" class="sbspf_show_gdpr_list"><?php _e( 'What will be limited?', 'youtube-feed' ); ?></a></p>
1007
-
1008
- <?php echo "<div class='sbspf_gdpr_list'>" . $gdpr_list . '</div>'; ?>
1009
-
1010
-
1011
- <p><span><?php _e("No", 'youtube-feed' ); ?>:</span> <?php _e("The plugin will still make some requests to display and play videos directly from YouTube.", 'youtube-feed' ); ?></p>
1012
-
1013
-
1014
- <p><span><?php _e("Automatic", 'youtube-feed' ); ?>:</span> <?php echo sprintf( __( 'The plugin will only videos if consent has been given by one of these integrated %s', 'youtube-feed' ), '<a href="https://smashballoon.com/doc/gdpr-plugin-list/?youtube" target="_blank" rel="noopener">' . __( 'GDPR cookie plugins', 'youtube-feed' ) . '</a>' ); ?></p>
1015
-
1016
- <p><?php echo sprintf( __( '%s to learn more about GDPR compliance in the Feeds for YouTube plugin.', 'youtube-feed' ), '<a href="https://smashballoon.com/doc/feeds-for-youtube-gdpr-compliance/?youtube" target="_blank" rel="noopener">'. __( 'Click here', 'youtube-feed' ).'</a>' ); ?></p>
1017
- </div>
1018
- </div>
1019
-
1020
- <div id="sbspf_images_options" class="sbspf_box">
1021
- <div class="sbspf_box_setting">
1022
- <?php
1023
- $checked = isset( $this->settings['disablecdn'] ) && $this->settings['disablecdn'] ? ' checked' : false;
1024
- ?>
1025
- <input name="<?php echo $this->option_name.'[disablecdn]'; ?>" id="sbspf_disablecdn" class="sbspf_single_checkbox" type="checkbox"<?php echo $checked; ?>>
1026
- <label for="sbspf_disablecdn"><?php _e("Block CDN Images", 'youtube-feed' ); ?></label>
1027
- <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $this->default_tooltip_text(); ?></a>
1028
- <div class="sbspf_tooltip sbspf_more_info">
1029
- <?php _e("Images in the feed come from YouTube's CDN. Enabling this setting will show a placeholder image until consent is given.", 'youtube-feed' ); ?>
1030
- </div>
1031
- </div>
1032
- </div>
1033
-
1034
- <?php if ( ! SBY_GDPR_Integrations::gdpr_tests_successful( isset( $_GET['retest'] ) ) ) :
1035
- $errors = SBY_GDPR_Integrations::gdpr_tests_error_message();
1036
- ?>
1037
- <div class="sbspf_box sbspf_gdpr_error">
1038
- <div class="sbspf_box_setting">
1039
- <p>
1040
- <strong><?php _e( 'Error:', 'youtube-feed' ); ?></strong> <?php _e("Due to a configuration issue on your web server, the GDPR setting is unable to be enabled. Please see below for more information.", 'youtube-feed' ); ?></p>
1041
- <p>
1042
- <?php echo $errors; ?>
1043
- </p>
1044
- </div>
1045
- </div>
1046
- <?php else: ?>
1047
-
1048
- <div class="sbspf_gdpr_auto">
1049
- <?php if ( SBY_GDPR_Integrations::gdpr_plugins_active() ) :
1050
- $active_plugin = SBY_GDPR_Integrations::gdpr_plugins_active();
1051
- ?>
1052
- <div class="sbspf_gdpr_plugin_active">
1053
- <div class="sbspf_active">
1054
- <p>
1055
- <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-check-circle fa-w-16 fa-2x"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z" class=""></path></svg>
1056
- <b><?php echo sprintf( __( '%s detected', 'youtube-feed' ), $active_plugin ); ?></b>
1057
- <br />
1058
- <?php _e( 'Some Feeds for YouTube features will be limited for visitors to ensure GDPR compliance until they give consent.', 'youtube-feed' ); ?>
1059
- <a href="JavaScript:void(0);" class="sbspf_show_gdpr_list"><?php _e( 'What will be limited?', 'youtube-feed' ); ?></a>
1060
- </p>
1061
- <?php echo "<div class='sbspf_gdpr_list'>" . $gdpr_list . '</div>'; ?>
1062
- </div>
1063
-
1064
- </div>
1065
- <?php else: ?>
1066
- <div class="sbspf_box">
1067
- <div class="sbspf_box_setting">
1068
- <p><?php _e( 'No GDPR consent plugin detected. Install a compatible <a href="https://smashballoon.com/doc/gdpr-plugin-list/?youtube">GDPR consent plugin</a>, or manually enable the setting above to display a GDPR compliant version of the feed to all visitors.', 'youtube-feed' ); ?></p>
1069
- </div>
1070
- </div>
1071
- <?php endif; ?>
1072
- </div>
1073
-
1074
- <div class="sbspf_box sbspf_gdpr_yes">
1075
- <div class="sbspf_box_setting">
1076
- <p><?php _e( "No requests will be made to third-party websites. To accommodate this, some features of the plugin will be limited:", 'youtube-feed' ); ?></p>
1077
- <?php echo $gdpr_list; ?>
1078
- </div>
1079
- </div>
1080
-
1081
- <div class="sbspf_box sbspf_gdpr_no">
1082
- <div class="sbspf_box_setting">
1083
- <p><?php _e( "The plugin will function as normal and load images and videos directly from Twitter.", 'youtube-feed' ); ?></p>
1084
- </div>
1085
- </div>
1086
-
1087
- <?php endif;
1088
- }
1089
-
1090
- public function get_connected_accounts() {
1091
- global $sby_settings;
1092
-
1093
- if ( isset( $sby_settings['connected_accounts'] ) ) {
1094
- return $sby_settings['connected_accounts'];
1095
- }
1096
- return array();
1097
- }
1098
-
1099
- public function access_token_listener() {
1100
- if ( isset( $_GET['page'] ) && $_GET['page'] === SBY_SLUG && isset( $_GET['sby_access_token'] ) ) {
1101
- sby_attempt_connection();
1102
- }
1103
- }
1104
-
1105
- public static function connect_account( $args ) {
1106
- sby_update_or_connect_account( $args );
1107
- }
1108
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SBY_Admin extends SB_YOUTUBE_Admin {
7
+
8
+ public function settings_init() {
9
+ $text_domain = $this->vars->text_domain();
10
+
11
+ $defaults = sby_settings_defaults();
12
+ $this->add_false_field( 'disablecdn', 'customize' );
13
+
14
+ /**
15
+ * Configure Tab
16
+ */
17
+ $args = array(
18
+ 'id' => 'sbspf_types',
19
+ 'tab' => 'configure',
20
+ 'save_after' => 'true'
21
+ );
22
+ $this->add_settings_section( $args );
23
+
24
+ $locator_html = '';
25
+ if ( SBY_Feed_Locator::count_unique() > -1 ) {
26
+ $locator_html .= '<div class="sby_locations_link">';
27
+ $locator_html .= '<a href="?page=' . $this->slug .'&amp;tab=allfeeds"><svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="search" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-search fa-w-16 fa-2x"><path fill="currentColor" d="M508.5 468.9L387.1 347.5c-2.3-2.3-5.3-3.5-8.5-3.5h-13.2c31.5-36.5 50.6-84 50.6-136C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c52 0 99.5-19.1 136-50.6v13.2c0 3.2 1.3 6.2 3.5 8.5l121.4 121.4c4.7 4.7 12.3 4.7 17 0l22.6-22.6c4.7-4.7 4.7-12.3 0-17zM208 368c-88.4 0-160-71.6-160-160S119.6 48 208 48s160 71.6 160 160-71.6 160-160 160z" class=""></path></svg> ' . __( 'Feed Finder', $text_domain ) . '</a>';
28
+ $locator_html .= '</div>';
29
+ }
30
+ /* Types */
31
+ $args = array(
32
+ 'name' => 'type',
33
+ 'section' => 'sbspf_types',
34
+ 'callback' => 'types',
35
+ 'title' => '<label>' . __( 'Select a Feed Type', $text_domain ) .'</label>',
36
+ 'shortcode' => array(
37
+ 'key' => 'type',
38
+ 'example' => 'channel',
39
+ 'description' => __( 'Type of feed to display', $text_domain ) . ' e.g. channel, playlist, search, favorites, live',
40
+ 'after_description' => $locator_html,
41
+ 'display_section' => 'configure'
42
+ ),
43
+ 'types' => $this->types
44
+ );
45
+ $this->add_settings_field( $args );
46
+
47
+ $this->pro_only[] = 'type';
48
+
49
+
50
+ /* Cache */
51
+ $args = array(
52
+ 'name' => 'cache',
53
+ 'section' => 'sbspf_types',
54
+ 'callback' => 'cache',
55
+ 'title' => __( 'Check for new posts', $text_domain )
56
+ );
57
+ $this->add_settings_field( $args );
58
+
59
+
60
+ /**
61
+ * Customize Tab
62
+ */
63
+ $args = array(
64
+ 'title' => __( 'General', $text_domain ),
65
+ 'id' => 'sbspf_general',
66
+ 'tab' => 'customize',
67
+ 'save_after' => 'true'
68
+ );
69
+ $this->add_settings_section( $args );
70
+
71
+ /* Width and Height */
72
+ $select_options = array(
73
+ array(
74
+ 'label' => '%',
75
+ 'value' => '%'
76
+ ),
77
+ array(
78
+ 'label' => 'px',
79
+ 'value' => 'px'
80
+ )
81
+ );
82
+
83
+ $args = array(
84
+ 'name' => 'width',
85
+ 'default' => '100',
86
+ 'section' => 'sbspf_general',
87
+ 'callback' => 'text',
88
+ 'min' => 1,
89
+ 'size' => 4,
90
+ 'title' => __( 'Width of Feed', $text_domain ),
91
+ 'shortcode' => array(
92
+ 'key' => 'width',
93
+ 'example' => '300px',
94
+ 'description' => __( 'The width of your feed. Any number with a unit like "px" or "%".', $text_domain ),
95
+ 'display_section' => 'customize'
96
+ ),
97
+ 'select_name' => 'widthunit',
98
+ 'select_options' => $select_options,
99
+ 'hidden' => array(
100
+ 'callback' => 'checkbox',
101
+ 'name' => 'width_responsive',
102
+ 'label' => __( 'Set to be 100% width on mobile?', $text_domain ),
103
+ 'before' => '<div id="sbspf_width_options">',
104
+ 'after' => '</div>',
105
+ 'tooltip_info' => __( 'If you set a width on the feed then this will be used on mobile as well as desktop. Check this setting to set the feed width to be 100% on mobile so that it is responsive.', $text_domain )
106
+ ),
107
+ );
108
+ $this->add_settings_field( $args );
109
+
110
+ $select_options = array(
111
+ array(
112
+ 'label' => '%',
113
+ 'value' => '%'
114
+ ),
115
+ array(
116
+ 'label' => 'px',
117
+ 'value' => 'px'
118
+ )
119
+ );
120
+ $args = array(
121
+ 'name' => 'height',
122
+ 'default' => '',
123
+ 'section' => 'sbspf_general',
124
+ 'callback' => 'text',
125
+ 'min' => 1,
126
+ 'size' => 4,
127
+ 'title' => __( 'Height of Feed', $text_domain ),
128
+ 'shortcode' => array(
129
+ 'key' => 'height',
130
+ 'example' => '500px',
131
+ 'description' => __( 'The height of your feed. Any number with a unit like "px" or "em".', $text_domain ),
132
+ 'display_section' => 'customize'
133
+ ),
134
+ 'select_name' => 'heightunit',
135
+ 'select_options' => $select_options,
136
+ );
137
+ $this->add_settings_field( $args );
138
+
139
+ $args = array(
140
+ 'name' => 'background',
141
+ 'default' => '',
142
+ 'section' => 'sbspf_general',
143
+ 'callback' => 'color',
144
+ 'title' => __( 'Background Color', $text_domain ),
145
+ 'shortcode' => array(
146
+ 'key' => 'background',
147
+ 'example' => '#f00',
148
+ 'description' => __( 'Background color for the feed. Any hex color code.', $text_domain ),
149
+ 'display_section' => 'customize'
150
+ ),
151
+ );
152
+ $this->add_settings_field( $args );
153
+
154
+ $args = array(
155
+ 'title' => __( 'Layout', $text_domain ),
156
+ 'id' => 'sbspf_layout',
157
+ 'tab' => 'customize',
158
+ 'save_after' => 'true'
159
+ );
160
+ $this->add_settings_section( $args );
161
+
162
+ $args = array(
163
+ 'name' => 'layout',
164
+ 'section' => 'sbspf_layout',
165
+ 'callback' => 'layout',
166
+ 'title' => __( 'Layout Type', $text_domain ),
167
+ 'layouts' => $this->layouts,
168
+ 'shortcode' => array(
169
+ 'key' => 'layout',
170
+ 'example' => 'list',
171
+ 'description' => __( 'How your posts are displayed visually.', $text_domain ) . ' e.g. list, grid, gallery',
172
+ 'display_section' => 'layout'
173
+ )
174
+ );
175
+ $this->add_settings_field( $args );
176
+
177
+ $this->pro_only[] = 'carouselcols';
178
+ $this->pro_only[] = 'carouselcolsmobile';
179
+ $this->pro_only[] = 'carouselrows';
180
+ $this->pro_only[] = 'carouselloop';
181
+ $this->pro_only[] = 'carouselarrows';
182
+ $this->pro_only[] = 'carouselpag';
183
+ $this->pro_only[] = 'carouselautoplay';
184
+ $this->pro_only[] = 'carouseltime';
185
+
186
+ $select_options = array(
187
+ array(
188
+ 'label' => 'px',
189
+ 'value' => 'px'
190
+ ),
191
+ array(
192
+ 'label' => '%',
193
+ 'value' => '%'
194
+ )
195
+ );
196
+
197
+ $args = array(
198
+ 'name' => 'num',
199
+ 'default' => $defaults['num'],
200
+ 'section' => 'sbspf_layout',
201
+ 'callback' => 'text',
202
+ 'min' => 1,
203
+ 'max' => 50,
204
+ 'size' => 4,
205
+ 'title' => __( 'Number of Videos', $text_domain ),
206
+ 'additional' => '<span class="sby_note">' . __( 'Number of videos to show initially.', $text_domain ) . '</span>',
207
+ 'shortcode' => array(
208
+ 'key' => 'num',
209
+ 'example' => 5,
210
+ 'description' => __( 'The number of videos in the feed', $text_domain ),
211
+ 'display_section' => 'layout'
212
+ )
213
+ );
214
+ $this->add_settings_field( $args );
215
+
216
+ $include_options = array(
217
+ array(
218
+ 'label' => __( 'Play Icon', $text_domain ),
219
+ 'value' => 'icon'
220
+ ),
221
+ array(
222
+ 'label' => __( 'Title', $text_domain ),
223
+ 'value' => 'title',
224
+ 'pro' => true
225
+ ),
226
+ array(
227
+ 'label' => __( 'User Name', $text_domain ),
228
+ 'value' => 'user',
229
+ 'pro' => true
230
+ ),
231
+ array(
232
+ 'label' => __( 'Views', $text_domain ),
233
+ 'value' => 'views',
234
+ 'pro' => true
235
+ ),
236
+ array(
237
+ 'label' => __( 'Date', $text_domain ),
238
+ 'value' => 'date',
239
+ 'pro' => true
240
+ ),
241
+ array(
242
+ 'label' => __( 'Live Stream Countdown (when applies)', $text_domain ),
243
+ 'value' => 'countdown',
244
+ 'pro' => true
245
+ ),
246
+ array(
247
+ 'label' => __( 'Stats (like and comment counts)', $text_domain ),
248
+ 'value' => 'stats',
249
+ 'pro' => true
250
+ ),
251
+ array(
252
+ 'label' => __( 'Description', $text_domain ),
253
+ 'value' => 'description',
254
+ 'pro' => true
255
+ ),
256
+ );
257
+ $args = array(
258
+ 'name' => 'include',
259
+ 'default' => $defaults['include'],
260
+ 'section' => 'sbspf_layout',
261
+ 'callback' => 'multi_checkbox',
262
+ 'title' => __( 'Show/Hide', $text_domain ),
263
+ 'shortcode' => array(
264
+ 'key' => 'include',
265
+ 'example' => '"icon"',
266
+ 'description' => __( 'What video information will display in the feed. eg.', $text_domain ) . ' icon',
267
+ 'display_section' => 'customize'
268
+ ),
269
+ 'select_options' => $include_options,
270
+ );
271
+ $this->add_settings_field( $args );
272
+
273
+ $args = array(
274
+ 'name' => 'itemspacing',
275
+ 'default' => 5,
276
+ 'section' => 'sbspf_layout',
277
+ 'callback' => 'text',
278
+ 'min' => 0,
279
+ 'size' => 4,
280
+ 'title' => __( 'Spacing between videos', $text_domain ),
281
+ 'shortcode' => array(
282
+ 'key' => 'itemspacing',
283
+ 'example' => '5px',
284
+ 'description' => __( 'The spacing/padding around the videos in the feed. Any number with a unit like "px" or "em".', $text_domain ),
285
+ 'display_section' => 'layout'
286
+ ),
287
+ 'select_name' => 'itemspacingunit',
288
+ 'select_options' => $select_options,
289
+ );
290
+ $this->add_settings_field( $args );
291
+
292
+ $select_options = array(
293
+ array(
294
+ 'label' => __( 'Below video thumbnail', $text_domain ),
295
+ 'value' => 'below'
296
+ ),
297
+ array(
298
+ 'label' => __( 'Next to video thumbnail', $text_domain ),
299
+ 'value' => 'side'
300
+ )
301
+ );
302
+ $args = array(
303
+ 'name' => 'infoposition',
304
+ 'default' => 'below',
305
+ 'section' => 'sbspf_layout',
306
+ 'pro' => true,
307
+ 'callback' => 'select',
308
+ 'title' => __( 'Position', $text_domain ),
309
+ 'shortcode' => array(
310
+ 'key' => 'infoposition',
311
+ 'example' => 'side',
312
+ 'description' => __( 'Where the information (title, description, stats) will display. eg.', $text_domain ) . ' below, side, none',
313
+ 'display_section' => 'customize'
314
+ ),
315
+ 'options' => $select_options,
316
+ );
317
+ $this->add_settings_field( $args );
318
+
319
+ $args = array(
320
+ 'title' => __( 'Header', $text_domain ),
321
+ 'id' => 'sbspf_header',
322
+ 'tab' => 'customize',
323
+ );
324
+ $this->add_settings_section( $args );
325
+
326
+ $args = array(
327
+ 'name' => 'showheader',
328
+ 'section' => 'sbspf_header',
329
+ 'callback' => 'checkbox',
330
+ 'title' => __( 'Show Header', $text_domain ),
331
+ 'default' => true,
332
+ 'shortcode' => array(
333
+ 'key' => 'showheader',
334
+ 'example' => 'false',
335
+ 'description' => __( 'Include a header for this feed.', $text_domain ),
336
+ 'display_section' => 'header'
337
+ )
338
+ );
339
+ $this->add_settings_field( $args );
340
+
341
+ $args = array(
342
+ 'name' => 'showdescription',
343
+ 'section' => 'sbspf_header',
344
+ 'callback' => 'checkbox',
345
+ 'title' => __( 'Show Channel Description', $text_domain ),
346
+ 'default' => true,
347
+ 'shortcode' => array(
348
+ 'key' => 'showdescription',
349
+ 'example' => 'false',
350
+ 'description' => __( 'Include the channel description in the header.', $text_domain ),
351
+ 'display_section' => 'header'
352
+ )
353
+ );
354
+ $this->add_settings_field( $args );
355
+
356
+ $args = array(
357
+ 'name' => 'showsubscribers',
358
+ 'section' => 'sbspf_header',
359
+ 'callback' => 'checkbox',
360
+ 'pro' => true,
361
+ 'title' => __( 'Show Subscribers', $text_domain ),
362
+ 'default' => true,
363
+ 'shortcode' => array(
364
+ 'key' => 'showsubscribers',
365
+ 'example' => 'false',
366
+ 'description' => __( 'Include the number of subscribers in the header.', $text_domain ),
367
+ 'display_section' => 'header'
368
+ )
369
+ );
370
+ $this->add_settings_field( $args );
371
+
372
+ $args = array(
373
+ 'title' => __( '"Load More" Button', $text_domain ),
374
+ 'id' => 'sbspf_loadmore',
375
+ 'tab' => 'customize',
376
+ );
377
+ $this->add_settings_section( $args );
378
+
379
+ $args = array(
380
+ 'name' => 'showbutton',
381
+ 'section' => 'sbspf_loadmore',
382
+ 'callback' => 'checkbox',
383
+ 'title' => __( 'Show "Load More" Button', $text_domain ),
384
+ 'default' => true,
385
+ 'shortcode' => array(
386
+ 'key' => 'showbutton',
387
+ 'example' => 'false',
388
+ 'description' => __( 'Include a "Load More" button at the bottom of the feed to load more videos.', $text_domain ),
389
+ 'display_section' => 'button'
390
+ )
391
+ );
392
+ $this->add_settings_field( $args );
393
+
394
+ $args = array(
395
+ 'name' => 'buttoncolor',
396
+ 'default' => '',
397
+ 'section' => 'sbspf_loadmore',
398
+ 'callback' => 'color',
399
+ 'title' => __( 'Button Background Color', $text_domain ),
400
+ 'shortcode' => array(
401
+ 'key' => 'buttoncolor',
402
+ 'example' => '#0f0',
403
+ 'description' => __( 'Background color for the "Load More" button. Any hex color code.', $text_domain ),
404
+ 'display_section' => 'button'
405
+ ),
406
+ );
407
+ $this->add_settings_field( $args );
408
+
409
+ $args = array(
410
+ 'name' => 'buttontextcolor',
411
+ 'default' => '',
412
+ 'section' => 'sbspf_loadmore',
413
+ 'callback' => 'color',
414
+ 'title' => __( 'Button Text Color', $text_domain ),
415
+ 'shortcode' => array(
416
+ 'key' => 'buttontextcolor',
417
+ 'example' => '#00f',
418
+ 'description' => __( 'Text color for the "Load More" button. Any hex color code.', $text_domain ),
419
+ 'display_section' => 'button'
420
+ ),
421
+ );
422
+ $this->add_settings_field( $args );
423
+
424
+ $args = array(
425
+ 'name' => 'buttontext',
426
+ 'default' => __( 'Load More...', $text_domain ),
427
+ 'section' => 'sbspf_loadmore',
428
+ 'callback' => 'text',
429
+ 'title' => __( 'Button Text', $text_domain ),
430
+ 'shortcode' => array(
431
+ 'key' => 'buttontext',
432
+ 'example' => '"More Videos"',
433
+ 'description' => __( 'The text that appers on the "Load More" button.', $text_domain ),
434
+ 'display_section' => 'button'
435
+ )
436
+ );
437
+ $this->add_settings_field( $args );
438
+
439
+ /* Subscribe button */
440
+ $args = array(
441
+ 'title' => __( '"Subscribe" Button', $text_domain ),
442
+ 'id' => 'sbspf_subscribe',
443
+ 'tab' => 'customize',
444
+ 'save_after' => true
445
+ );
446
+ $this->add_settings_section( $args );
447
+
448
+ $args = array(
449
+ 'name' => 'showsubscribe',
450
+ 'section' => 'sbspf_subscribe',
451
+ 'callback' => 'checkbox',
452
+ 'title' => __( 'Show "Subscribe" Button', $text_domain ),
453
+ 'default' => true,
454
+ 'shortcode' => array(
455
+ 'key' => 'showsubscribe',
456
+ 'example' => 'false',
457
+ 'description' => __( 'Include a "Subscribe" button at the bottom of the feed to load more videos.', $text_domain ),
458
+ 'display_section' => 'subscribe'
459
+ )
460
+ );
461
+ $this->add_settings_field( $args );
462
+
463
+ $args = array(
464
+ 'name' => 'subscribecolor',
465
+ 'default' => '',
466
+ 'section' => 'sbspf_subscribe',
467
+ 'callback' => 'color',
468
+ 'title' => __( 'Subscribe Background Color', $text_domain ),
469
+ 'shortcode' => array(
470
+ 'key' => 'subscribecolor',
471
+ 'example' => '#0f0',
472
+ 'description' => __( 'Background color for the "Subscribe" button. Any hex color code.', $text_domain ),
473
+ 'display_section' => 'subscribe'
474
+ ),
475
+ );
476
+ $this->add_settings_field( $args );
477
+
478
+ $args = array(
479
+ 'name' => 'subscribetextcolor',
480
+ 'default' => '',
481
+ 'section' => 'sbspf_subscribe',
482
+ 'callback' => 'color',
483
+ 'title' => __( 'Subscribe Text Color', $text_domain ),
484
+ 'shortcode' => array(
485
+ 'key' => 'subscribetextcolor',
486
+ 'example' => '#00f',
487
+ 'description' => __( 'Text color for the "Subscribe" button. Any hex color code.', $text_domain ),
488
+ 'display_section' => 'subscribe'
489
+ ),
490
+ );
491
+ $this->add_settings_field( $args );
492
+
493
+ $args = array(
494
+ 'name' => 'subscribetext',
495
+ 'default' => __( 'Subscribe', $text_domain ),
496
+ 'section' => 'sbspf_subscribe',
497
+ 'callback' => 'text',
498
+ 'title' => __( 'Subscribe Text', $text_domain ),
499
+ 'shortcode' => array(
500
+ 'key' => 'subscribetext',
501
+ 'example' => '"Subscribe to My Channel"',
502
+ 'description' => __( 'The text that appers on the "Subscribe" button.', $text_domain ),
503
+ 'display_section' => 'subscribe'
504
+ )
505
+ );
506
+ $this->add_settings_field( $args );
507
+
508
+ $args = array(
509
+ 'title' => __( 'Video Experience', $text_domain ),
510
+ 'id' => 'sbspf_experience',
511
+ 'tab' => 'customize',
512
+ );
513
+ $this->add_settings_section( $args );
514
+
515
+ $select_options = array(
516
+ array(
517
+ 'label' => '9:16',
518
+ 'value' => '9:16'
519
+ ),
520
+ array(
521
+ 'label' => '3:4',
522
+ 'value' => '3:4'
523
+ ),
524
+ );
525
+ $args = array(
526
+ 'name' => 'playerratio',
527
+ 'default' => '9:16',
528
+ 'section' => 'sbspf_experience',
529
+ 'callback' => 'select',
530
+ 'title' => __( 'Player Size Ratio', $text_domain ),
531
+ 'shortcode' => array(
532
+ 'key' => 'playerratio',
533
+ 'example' => '9:16',
534
+ 'description' => __( 'Player height relative to width e.g.', $text_domain ) . ' 9:16, 3:4',
535
+ 'display_section' => 'experience'
536
+ ),
537
+ 'options' => $select_options,
538
+ 'tooltip_info' => __( 'A 9:16 ratio does not leave room for video title and playback tools while a 3:4 ratio does.', $text_domain )
539
+ );
540
+ $this->add_settings_field( $args );
541
+
542
+ $select_options = array(
543
+ array(
544
+ 'label' => __( 'Play when clicked', $text_domain ),
545
+ 'value' => 'onclick'
546
+ ),
547
+ array(
548
+ 'label' => 'Play automatically (desktop only)',
549
+ 'value' => 'automatically'
550
+ )
551
+ );
552
+ $args = array(
553
+ 'name' => 'playvideo',
554
+ 'default' => 'onclick',
555
+ 'section' => 'sbspf_experience',
556
+ 'callback' => 'select',
557
+ 'title' => __( 'When does video play?', $text_domain ),
558
+ 'shortcode' => array(
559
+ 'key' => 'playvideo',
560
+ 'example' => 'onclick',
561
+ 'description' => __( 'What the user needs to do to play a video. eg.', $text_domain ) . ' onclick, automatically',
562
+ 'display_section' => 'customize'
563
+ ),
564
+ 'options' => $select_options,
565
+ 'tooltip_info' => __( 'List layout will not play automatically. Choose whether to play the video automatically in the player or wait until the user clicks the play button after the video is loaded.', $text_domain )
566
+ );
567
+ $this->add_settings_field( $args );
568
+
569
+ $cta_options = array(
570
+ array(
571
+ 'label' => __( 'Related Videos', SBY_TEXT_DOMAIN ),
572
+ 'slug' => 'related',
573
+ 'pro' => true,
574
+ 'note' => __( 'Display video thumbnails from the feed that play on your site when clicked.', SBY_TEXT_DOMAIN )
575
+ ),
576
+ array(
577
+ 'label' => 'Custom Link',
578
+ 'slug' => 'link',
579
+ 'pro' => true,
580
+ 'note' => __( 'Display a button link to a custom URL.', SBY_TEXT_DOMAIN ),
581
+ 'options' => array(
582
+ array(
583
+ 'name' => 'instructions',
584
+ 'callback' => 'instructions',
585
+ 'instructions' => __( 'To set a link for each video individually, add the link and button text in the video description on YouTube in this format:', SBY_TEXT_DOMAIN ) . '<br><br><code>{Link: Button Text https://my-site.com/buy-now/my-product/}</code>',
586
+ 'label' => __( 'Custom link for each video', SBY_TEXT_DOMAIN ),
587
+ ),
588
+ array(
589
+ 'name' => 'url',
590
+ 'callback' => 'text',
591
+ 'label' => __( 'Default Link', SBY_TEXT_DOMAIN ),
592
+ 'class' => 'large-text',
593
+ 'default' => '',
594
+ 'shortcode' => array(
595
+ 'example' => 'https://my-site.com/buy-now/my-product/',
596
+ 'description' => __( 'URL for viewer to visit for the call to action.', $text_domain ),
597
+ )
598
+ ),
599
+ array(
600
+ 'name' => 'opentype',
601
+ 'callback' => 'select',
602
+ 'options' => array(
603
+ array(
604
+ 'label' => __( 'Same window', SBY_TEXT_DOMAIN ),
605
+ 'value' => 'same'
606
+ ),
607
+ array(
608
+ 'label' => __( 'New window', SBY_TEXT_DOMAIN ),
609
+ 'value' => 'newwindow'
610
+ )
611
+ ),
612
+ 'label' => __( 'Link Open Type', SBY_TEXT_DOMAIN ),
613
+ 'default' => 'same',
614
+ 'shortcode' => array(
615
+ 'example' => 'newwindow',
616
+ 'description' => __( 'Whether to open the page in a new window or the same window.', $text_domain ),
617
+ )
618
+ ),
619
+ array(
620
+ 'name' => 'text',
621
+ 'callback' => 'text',
622
+ 'label' => __( 'Default Button Text', SBY_TEXT_DOMAIN ),
623
+ 'default' => __( 'Learn More', SBY_TEXT_DOMAIN ),
624
+ 'shortcode' => array(
625
+ 'example' => 'Buy Now',
626
+ 'description' => __( 'Text that appears on the call-to-action button.', $text_domain ),
627
+ )
628
+ ),
629
+ array(
630
+ 'name' => 'color',
631
+ 'default' => '',
632
+ 'callback' => 'color',
633
+ 'label' => __( 'Button Background Color', SBY_TEXT_DOMAIN ),
634
+ 'shortcode' => array(
635
+ 'example' => '#0f0',
636
+ 'description' => __( 'Button background. Turns opaque on hover.', $text_domain ),
637
+ )
638
+ ),
639
+ array(
640
+ 'name' => 'textcolor',
641
+ 'default' => '',
642
+ 'callback' => 'color',
643
+ 'label' => __( 'Button Text Color', SBY_TEXT_DOMAIN ),
644
+ 'shortcode' => array(
645
+ 'example' => '#0f0',
646
+ 'description' => __( 'Color of the text on the call-to-action-button', $text_domain ),
647
+ )
648
+ )
649
+ )
650
+ ),
651
+ array(
652
+ 'label' => __( 'YouTube Default', SBY_TEXT_DOMAIN ),
653
+ 'slug' => 'default',
654
+ 'pro' => true,
655
+ 'note' => __( 'YouTube suggested videos from your channel that play on YouTube when clicked.', SBY_TEXT_DOMAIN )
656
+ ),
657
+ );
658
+ $this->pro_only[] = 'linkurl';
659
+ $this->pro_only[] = 'linkopentype';
660
+ $this->pro_only[] = 'linktext';
661
+ $this->pro_only[] = 'linkcolor';
662
+ $this->pro_only[] = 'linktextcolor';
663
+
664
+ $args = array(
665
+ 'name' => 'cta',
666
+ 'default' => 'related',
667
+ 'section' => 'sbspf_experience',
668
+ 'callback' => 'sub_option',
669
+ 'pro' => true,
670
+ 'sub_options' => $cta_options,
671
+ 'title' => __( 'Call to Action', $text_domain ),
672
+ 'before' => '<p style="margin-bottom: 10px">' . __( 'What the user sees when a video pauses or ends.', $text_domain ) . '</p>',
673
+ 'shortcode' => array(
674
+ 'key' => 'cta',
675
+ 'example' => 'link',
676
+ 'description' => __( 'What the user sees when a video pauses or ends. eg.', $text_domain ) . ' related, link',
677
+ 'display_section' => 'experience'
678
+ ),
679
+ 'tooltip_info' => __( 'Choose what will happen after a video is paused or completes.', $text_domain )
680
+ );
681
+ $this->add_settings_field( $args );
682
+
683
+ $args = array(
684
+ 'title' => __( 'Moderation', $text_domain ),
685
+ 'id' => 'sbspf_moderation',
686
+ 'tab' => 'customize',
687
+ 'pro' => __( 'Upgrade to Pro to enable Moderation settings', $text_domain ),
688
+ );
689
+ $this->add_settings_section( $args );
690
+
691
+ $args = array(
692
+ 'name' => 'includewords',
693
+ 'default' => '',
694
+ 'section' => 'sbspf_moderation',
695
+ 'callback' => 'text',
696
+ 'class' => 'large-text',
697
+ 'title' => __( 'Show videos containing these words or hashtags', $text_domain ),
698
+ 'shortcode' => array(
699
+ 'key' => 'includewords',
700
+ 'example' => '#filter',
701
+ 'description' => __( 'Show videos that have specific text in the title or description.', $text_domain ),
702
+ 'display_section' => 'customize'
703
+ ),
704
+ 'additional' => __( '"includewords" separate multiple words with commas, include "#" for hashtags', $text_domain )
705
+ );
706
+ $this->add_settings_field( $args );
707
+
708
+ $args = array(
709
+ 'name' => 'excludewords',
710
+ 'default' => '',
711
+ 'section' => 'sbspf_moderation',
712
+ 'callback' => 'text',
713
+ 'class' => 'large-text',
714
+ 'title' => __( 'Remove videos containing these words or hashtags', $text_domain ),
715
+ 'shortcode' => array(
716
+ 'key' => 'excludewords',
717
+ 'example' => '#filter',
718
+ 'description' => __( 'Remove videos that have specific text in the title or description.', $text_domain ),
719
+ 'display_section' => 'customize'
720
+ ),
721
+ 'additional' => __( '"excludewords" separate multiple words with commas, include "#" for hashtags', $text_domain )
722
+ );
723
+ $this->add_settings_field( $args );
724
+ $this->pro_only[] = 'includewords';
725
+ $this->pro_only[] = 'excludewords';
726
+
727
+ $args = array(
728
+ 'name' => 'hidevideos',
729
+ 'default' => '',
730
+ 'section' => 'sbspf_moderation',
731
+ 'callback' => 'textarea',
732
+ 'title' => __( 'Hide Specific Videos', $text_domain ),
733
+ 'options' => $select_options,
734
+ 'tooltip_info' => __( 'Separate IDs with commas.', $text_domain ) . '<a class="sbspf_tooltip_link" href="JavaScript:void(0);">'.$this->default_tooltip_text().'</a>
735
+ <p class="sbspf_tooltip sbspf_more_info">' . __( 'These are the specific ID numbers associated with a video or with a post. You can find the ID of a video by viewing the video on YouTube and copy/pasting the ID number from the end of the URL. ex. <code>https://www.youtube.com/watch?v=<span class="sbspf-highlight">Ij1KvL8eN</span></code>', $text_domain ) . '</p>'
736
+ );
737
+ $this->add_settings_field( $args );
738
+
739
+ $args = array(
740
+ 'title' => __( 'Custom Code Snippets', $text_domain ),
741
+ 'id' => 'sbspf_custom_snippets',
742
+ 'tab' => 'customize'
743
+ );
744
+ $this->add_settings_section( $args );
745
+
746
+ $args = array(
747
+ 'name' => 'custom_css',
748
+ 'default' => '',
749
+ 'section' => 'sbspf_custom_snippets',
750
+ 'callback' => 'textarea',
751
+ 'title' => __( 'Custom CSS', $text_domain ),
752
+ 'options' => $select_options,
753
+ 'tooltip_info' => __( 'Enter your own custom CSS in the box below', $text_domain )
754
+ );
755
+ $this->add_settings_field( $args );
756
+
757
+ $args = array(
758
+ 'name' => 'custom_js',
759
+ 'default' => '',
760
+ 'section' => 'sbspf_custom_snippets',
761
+ 'callback' => 'textarea',
762
+ 'title' => __( 'Custom JavaScript', $text_domain ),
763
+ 'options' => $select_options,
764
+ 'tooltip_info' => __( 'Enter your own custom JavaScript/jQuery in the box below', $text_domain ),
765
+ 'note' => __( 'Note: Custom JavaScript reruns every time more videos are loaded into the feed', $text_domain )
766
+ );
767
+ $this->add_settings_field( $args );
768
+
769
+ $args = array(
770
+ 'title' => __( 'GDPR', $text_domain ),
771
+ 'id' => 'sbspf_gdpr',
772
+ 'tab' => 'customize',
773
+ 'save_after' => 'true'
774
+ );
775
+ $this->add_settings_section( $args );
776
+
777
+ $this->add_settings_field( array(
778
+ 'name' => 'gdpr',
779
+ 'title' => __( 'Enable GDPR Settings', $text_domain ),
780
+ 'callback' => 'gdpr', // name of the function that outputs the html
781
+ 'section' => 'sbspf_gdpr', // matches the section name
782
+ ));
783
+
784
+ $args = array(
785
+ 'title' => __( 'Advanced', $text_domain ),
786
+ 'id' => 'sbspf_advanced',
787
+ 'tab' => 'customize',
788
+ 'save_after' => true
789
+ );
790
+ $this->add_settings_section( $args );
791
+
792
+ $args = array(
793
+ 'name' => 'preserve_settings',
794
+ 'section' => 'sbspf_advanced',
795
+ 'callback' => 'checkbox',
796
+ 'title' => __( 'Preserve settings when plugin is removed', $text_domain ),
797
+ 'default' => false,
798
+ 'tooltip_info' => __( 'When removing the plugin your settings are automatically erased. Checking this box will prevent any settings from being deleted. This means that you can uninstall and reinstall the plugin without losing your settings.', $text_domain )
799
+ );
800
+ $this->add_settings_field( $args );
801
+
802
+ $select_options = array(
803
+ array(
804
+ 'label' => __( 'Background', $text_domain ),
805
+ 'value' => 'background'
806
+ ),
807
+ array(
808
+ 'label' => __( 'Page', $text_domain ),
809
+ 'value' => 'page'
810
+ ),
811
+ array(
812
+ 'label' => __( 'None', $text_domain ),
813
+ 'value' => 'none'
814
+ )
815
+ );
816
+ $additional = '<input id="sby-clear-cache" class="button-secondary sbspf-button-action" data-sby-action="sby_delete_wp_posts" data-sby-confirm="'.esc_attr( 'This will permanently delete all YouTube posts from the wp_posts table and the related data in the postmeta table. Existing feeds will only have 15 or fewer videos available initially. Continue?', $text_domain ).'" style="margin-top: 1px;" type="submit" value="'.esc_attr( 'Clear YouTube Posts', $text_domain ).'">';
817
+ $args = array(
818
+ 'name' => 'storage_process',
819
+ 'default' => '',
820
+ 'section' => 'sbspf_advanced',
821
+ 'callback' => 'select',
822
+ 'title' => __( 'Local storage process', $text_domain ),
823
+ 'options' => $select_options,
824
+ 'additional' => $additional,
825
+ 'tooltip_info' => __( 'To preserve your feeds and videos even if the YouTube API is unavailable, a record of each video is added to the wp_posts table in the WordPress database. Please note that changing this setting to "none" will limit the number of posts available in the feed to 15 or less.', $text_domain )
826
+ );
827
+ $this->add_settings_field( $args );
828
+
829
+ $args = array(
830
+ 'name' => 'cronclear',
831
+ 'section' => 'sbspf_advanced',
832
+ 'callback' => 'checkbox',
833
+ 'title' => __( 'Cron Clear Cache', $text_domain ),
834
+ 'default' => false,
835
+ 'tooltip_info' => __( 'If your YouTube feed is not updating, your WordPress installation may have a rare issue with clearing temporary data in your database. Enable this setting to use WordPress cron to clear your feed caches.', $text_domain )
836
+ );
837
+ $this->add_settings_field( $args );
838
+
839
+ $args = array(
840
+ 'name' => 'ajaxtheme',
841
+ 'section' => 'sbspf_advanced',
842
+ 'callback' => 'checkbox',
843
+ 'title' => __( 'Are you using an AJAX theme?', $text_domain ),
844
+ 'default' => false,
845
+ 'tooltip_info' => __( 'When navigating your site, if your theme uses Ajax to load content into your pages (meaning your page doesn\'t refresh) then check this setting. If you\'re not sure then it\'s best to leave this setting unchecked while checking with your theme author, otherwise checking it may cause a problem.', $text_domain )
846
+ );
847
+ $this->add_settings_field( $args );
848
+
849
+ $args = array(
850
+ 'name' => 'customtemplates',
851
+ 'section' => 'sbspf_advanced',
852
+ 'callback' => 'checkbox',
853
+ 'title' => __( 'Enable Custom Templates', $text_domain ),
854
+ 'default' => false,
855
+ 'tooltip_info' => __( 'The default HTML for the feed can be replaced with custom templates added to your theme\'s folder. Enable this setting to use these templates. See <a href="https://smashballoon.com/youtube-custom-templates/" target="_blank">this guide</a>', $text_domain )
856
+ );
857
+ $this->add_settings_field( $args );
858
+
859
+ $args = array(
860
+ 'name' => 'eagerload',
861
+ 'section' => 'sbspf_advanced',
862
+ 'callback' => 'checkbox',
863
+ 'title' => __( 'Load Iframes on Page Load', $text_domain ),
864
+ 'default' => false,
865
+ 'tooltip_info' => __( 'To optimize the performance of your site and feeds, the plugin loads iframes only after a visitor interacts with the feed. Enabling this setting will cause YouTube player iframes to load when the page loads. Some features may work differently when this is enabled.', $text_domain )
866
+ );
867
+ $this->add_settings_field( $args );
868
+
869
+ $args = array(
870
+ 'name' => 'enqueue_js_in_head',
871
+ 'section' => 'sbspf_advanced',
872
+ 'callback' => 'checkbox',
873
+ 'title' => __( 'Enqueue JS file in head', $text_domain ),
874
+ 'default' => false,
875
+ 'tooltip_info' => __( 'Check this box if you\'d like to enqueue the JavaScript file for the plugin in the head instead of the footer.', $text_domain )
876
+ );
877
+ $this->add_settings_field( $args );
878
+
879
+ }
880
+
881
+ public function cache( $args ) {
882
+ $social_network = $this->vars->social_network();
883
+ $type_selected = isset( $this->settings['caching_type'] ) ? $this->settings['caching_type'] : 'page';
884
+ $caching_time = isset( $this->settings['caching_time'] ) ? $this->settings['caching_time'] : 1;
885
+ $cache_time_unit_selected = isset( $this->settings['cache_time_unit'] ) ? $this->settings['cache_time_unit'] : 'hours';
886
+
887
+ $cache_cron_interval_selected = isset( $this->settings['cache_cron_interval'] ) ? $this->settings['cache_cron_interval'] : '';
888
+ $cache_cron_time = isset( $this->settings['cache_cron_time'] ) ? $this->settings['cache_cron_time'] : '';
889
+ $cache_cron_am_pm = isset( $this->settings['cache_cron_am_pm'] ) ? $this->settings['cache_cron_am_pm'] : '';
890
+
891
+ ?>
892
+ <div class="sbspf_cache_settings_wrap">
893
+ <div class="sbspf_row">
894
+ <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" class="sbspf_caching_type_input" id="sbspf_caching_type_page" value="page"<?php if ( $type_selected === 'page' ) echo ' checked'?>>
895
+ <label class="sbspf_radio_label" for="sbspf_caching_type_page"><?php _e ( 'When the page loads', $this->vars->text_domain() ); ?></label>
896
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);" style="position: relative; top: 2px;"><?php echo $this->default_tooltip_text() ?></a>
897
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __( "Your %s data is temporarily cached by the plugin in your WordPress database. There are two ways that you can set the plugin to check for new data:<br><br>
898
+ <b>1. When the page loads</b><br>Selecting this option means that when the cache expires then the plugin will check %s for new posts the next time that the feed is loaded. You can choose how long this data should be cached for with a minimum time of 15 minutes. If you set the time to 60 minutes then the plugin will clear the cached data after that length of time, and the next time the page is viewed it will check for new data. <b>Tip:</b> If you're experiencing an issue with the plugin not updating automatically then try enabling the setting labeled <b>'Force cache to clear on interval'</b> which is located on the 'Customize' tab.<br><br>
899
+ <b>2. In the background</b><br>Selecting this option means that the plugin will check for new data in the background so that the feed is updated behind the scenes. You can select at what time and how often the plugin should check for new data using the settings below. <b>Please note</b> that the plugin will initially check for data from Instagram when the page first loads, but then after that will check in the background on the schedule selected - unless the cache is cleared.", $this->vars->text_domain() ), $social_network, $social_network ); ?>
900
+ </p>
901
+ </div>
902
+ <div class="sbspf_row sbspf-caching-page-options" style="display: none;">
903
+ <?php _e ( 'Every', $this->vars->text_domain() ); ?>:
904
+ <input name="<?php echo $this->option_name.'[caching_time]'; ?>" type="text" value="<?php echo esc_attr( $caching_time ); ?>" size="4">
905
+ <select name="<?php echo $this->option_name.'[cache_time_unit]'; ?>">
906
+ <option value="minutes"<?php if ( $cache_time_unit_selected === 'minutes' ) echo ' selected'?>><?php _e ( 'Minutes', $this->vars->text_domain() ); ?></option>
907
+ <option value="hours"<?php if ( $cache_time_unit_selected === 'hours' ) echo ' selected'?>><?php _e ( 'Hours', $this->vars->text_domain() ); ?></option>
908
+ <option value="days"<?php if ( $cache_time_unit_selected === 'days' ) echo ' selected'?>><?php _e ( 'Days', $this->vars->text_domain() ); ?></option>
909
+ </select>
910
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php _e ( 'What does this mean?', $this->vars->text_domain() ); ?></a>
911
+ <p class="sbspf_tooltip sbspf_more_info"><?php echo sprintf( __("Your %s posts are temporarily cached by the plugin in your WordPress database. You can choose how long the posts should be cached for. If you set the time to 1 hour then the plugin will clear the cache after that length of time and check %s for posts again.", $this->vars->text_domain() ), $social_network, $social_network ); ?></p>
912
+ </div>
913
+
914
+ <div class="sbspf_row">
915
+ <input type="radio" name="<?php echo $this->option_name.'[caching_type]'; ?>" id="sbspf_caching_type_cron" class="sbspf_caching_type_input" value="background" <?php if ( $type_selected === 'background' ) echo ' checked'?>>
916
+ <label class="sbspf_radio_label" for="sbspf_caching_type_cron"><?php _e ( 'In the background', $this->vars->text_domain() ); ?></label>
917
+ </div>
918
+ <div class="sbspf_row sbspf-caching-cron-options" style="display: block;">
919
+
920
+ <select name="<?php echo $this->option_name.'[cache_cron_interval]'; ?>" id="sbspf_cache_cron_interval">
921
+ <option value="30mins"<?php if ( $cache_cron_interval_selected === '30mins' ) echo ' selected'?>><?php _e ( 'Every 30 minutes', $this->vars->text_domain() ); ?></option>
922
+ <option value="1hour"<?php if ( $cache_cron_interval_selected === '1hour' ) echo ' selected'?>><?php _e ( 'Every hour', $this->vars->text_domain() ); ?></option>
923
+ <option value="12hours"<?php if ( $cache_cron_interval_selected === '12hours' ) echo ' selected'?>><?php _e ( 'Every 12 hours', $this->vars->text_domain() ); ?></option>
924
+ <option value="24hours"<?php if ( $cache_cron_interval_selected === '24hours' ) echo ' selected'?>><?php _e ( 'Every 24 hours', $this->vars->text_domain() ); ?></option>
925
+ </select>
926
+
927
+ <div id="sbspf-caching-time-settings" style="">
928
+ <?php _e ( 'at', $this->vars->text_domain() ); ?>
929
+ <select name="<?php echo $this->option_name.'[cache_cron_time]'; ?>" style="width: 80px">
930
+ <option value="1"<?php if ( (int)$cache_cron_time === 1 ) echo ' selected'?>>1:00</option>
931
+ <option value="2"<?php if ( (int)$cache_cron_time === 2 ) echo ' selected'?>>2:00</option>
932
+ <option value="3"<?php if ( (int)$cache_cron_time === 3 ) echo ' selected'?>>3:00</option>
933
+ <option value="4"<?php if ( (int)$cache_cron_time === 4 ) echo ' selected'?>>4:00</option>
934
+ <option value="5"<?php if ( (int)$cache_cron_time === 5 ) echo ' selected'?>>5:00</option>
935
+ <option value="6"<?php if ( (int)$cache_cron_time === 6 ) echo ' selected'?>>6:00</option>
936
+ <option value="7"<?php if ( (int)$cache_cron_time === 7 ) echo ' selected'?>>7:00</option>
937
+ <option value="8"<?php if ( (int)$cache_cron_time === 8 ) echo ' selected'?>>8:00</option>
938
+ <option value="9"<?php if ( (int)$cache_cron_time === 9 ) echo ' selected'?>>9:00</option>
939
+ <option value="10"<?php if ( (int)$cache_cron_time === 10 ) echo ' selected'?>>10:00</option>
940
+ <option value="11"<?php if ( (int)$cache_cron_time === 11 ) echo ' selected'?>>11:00</option>
941
+ <option value="0"<?php if ( (int)$cache_cron_time === 0 ) echo ' selected'?>>12:00</option>
942
+ </select>
943
+
944
+ <select name="<?php echo $this->option_name.'[cache_cron_am_pm]'; ?>" style="width: 50px">
945
+ <option value="am"<?php if ( $cache_cron_am_pm === 'am' ) echo ' selected'?>><?php _e ( 'AM', $this->vars->text_domain() ); ?></option>
946
+ <option value="pm"<?php if ( $cache_cron_am_pm === 'pm' ) echo ' selected'?>><?php _e ( 'PM', $this->vars->text_domain() ); ?></option>
947
+ </select>
948
+ </div>
949
+
950
+ <?php
951
+ if ( wp_next_scheduled( 'sbspf_feed_update' ) ) {
952
+ $time_format = get_option( 'time_format' );
953
+ if ( ! $time_format ) {
954
+ $time_format = 'g:i a';
955
+ }
956
+ //
957
+ $schedule = wp_get_schedule( 'sbspf_feed_update' );
958
+ if ( $schedule == '30mins' ) $schedule = __( 'every 30 minutes', $this->vars->text_domain() );
959
+ if ( $schedule == 'twicedaily' ) $schedule = __( 'every 12 hours', $this->vars->text_domain() );
960
+ $sbspf_next_cron_event = wp_next_scheduled( 'sbspf_feed_update' );
961
+ echo '<p class="sbspf-caching-sched-notice"><span><b>' . __( 'Next check', $this->vars->text_domain() ) . ': ' . date( $time_format, $sbspf_next_cron_event + sbspf_get_utc_offset() ) . ' (' . $schedule . ')</b> - ' . __( 'Note: Saving the settings on this page will clear the cache and reset this schedule', $this->vars->text_domain() ) . '</span></p>';
962
+ } else {
963
+ echo '<p style="font-size: 11px; color: #666;">' . __( 'Nothing currently scheduled', $this->vars->text_domain() ) . '</p>';
964
+ }
965
+ ?>
966
+ </div>
967
+ </div>
968
+ <?php
969
+ }
970
+
971
+ public function gdpr( $args ) {
972
+ $gdpr = ( isset( $this->settings['gdpr'] ) ) ? $this->settings['gdpr'] : 'auto';
973
+ $select_options = array(
974
+ array(
975
+ 'label' => __( 'Automatic', 'youtube-feed' ),
976
+ 'value' => 'auto'
977
+ ),
978
+ array(
979
+ 'label' => __( 'Yes', 'youtube-feed' ),
980
+ 'value' => 'yes'
981
+ ),
982
+ array(
983
+ 'label' => __( 'No', 'youtube-feed' ),
984
+ 'value' => 'no'
985
+ )
986
+ )
987
+ ?>
988
+ <?php
989
+ $gdpr_list = "<ul class='sby-list'>
990
+ <li>" . __('YouTube Player API will not be loaded.', 'youtube-feed') . "</li>
991
+ <li>" . __('Thumbnail images for videos will display instead of actual video.', 'youtube-feed') . "</li>
992
+ <li>" . __('To view videos, visitors will click on links to view the video on youtube.com.', 'youtube-feed') . "</li>
993
+ </ul>";
994
+ ?>
995
+ <div>
996
+ <select name="<?php echo $this->option_name.'[gdpr]'; ?>" id="sbspf_gdpr_setting">
997
+ <?php foreach ( $select_options as $select_option ) :
998
+ $selected = $select_option['value'] === $gdpr ? ' selected' : '';
999
+ ?>
1000
+ <option value="<?php echo esc_attr( $select_option['value'] ); ?>"<?php echo $selected; ?> ><?php echo esc_html( $select_option['label'] ); ?></option>
1001
+ <?php endforeach; ?>
1002
+ </select>
1003
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $this->default_tooltip_text(); ?></a>
1004
+ <div class="sbspf_tooltip sbspf_more_info gdpr_tooltip">
1005
+
1006
+ <p><span><?php _e("Yes", 'youtube-feed' ); ?>:</span> <?php _e("Enabling this setting prevents all videos and external code from loading on your website. To accommodate this, some features of the plugin will be disabled or limited.", 'youtube-feed' ); ?> <a href="JavaScript:void(0);" class="sbspf_show_gdpr_list"><?php _e( 'What will be limited?', 'youtube-feed' ); ?></a></p>
1007
+
1008
+ <?php echo "<div class='sbspf_gdpr_list'>" . $gdpr_list . '</div>'; ?>
1009
+
1010
+
1011
+ <p><span><?php _e("No", 'youtube-feed' ); ?>:</span> <?php _e("The plugin will still make some requests to display and play videos directly from YouTube.", 'youtube-feed' ); ?></p>
1012
+
1013
+
1014
+ <p><span><?php _e("Automatic", 'youtube-feed' ); ?>:</span> <?php echo sprintf( __( 'The plugin will only videos if consent has been given by one of these integrated %s', 'youtube-feed' ), '<a href="https://smashballoon.com/doc/gdpr-plugin-list/?youtube" target="_blank" rel="noopener">' . __( 'GDPR cookie plugins', 'youtube-feed' ) . '</a>' ); ?></p>
1015
+
1016
+ <p><?php echo sprintf( __( '%s to learn more about GDPR compliance in the Feeds for YouTube plugin.', 'youtube-feed' ), '<a href="https://smashballoon.com/doc/feeds-for-youtube-gdpr-compliance/?youtube" target="_blank" rel="noopener">'. __( 'Click here', 'youtube-feed' ).'</a>' ); ?></p>
1017
+ </div>
1018
+ </div>
1019
+
1020
+ <div id="sbspf_images_options" class="sbspf_box">
1021
+ <div class="sbspf_box_setting">
1022
+ <?php
1023
+ $checked = isset( $this->settings['disablecdn'] ) && $this->settings['disablecdn'] ? ' checked' : false;
1024
+ ?>
1025
+ <input name="<?php echo $this->option_name.'[disablecdn]'; ?>" id="sbspf_disablecdn" class="sbspf_single_checkbox" type="checkbox"<?php echo $checked; ?>>
1026
+ <label for="sbspf_disablecdn"><?php _e("Block CDN Images", 'youtube-feed' ); ?></label>
1027
+ <a class="sbspf_tooltip_link" href="JavaScript:void(0);"><?php echo $this->default_tooltip_text(); ?></a>
1028
+ <div class="sbspf_tooltip sbspf_more_info">
1029
+ <?php _e("Images in the feed come from YouTube's CDN. Enabling this setting will show a placeholder image until consent is given.", 'youtube-feed' ); ?>
1030
+ </div>
1031
+ </div>
1032
+ </div>
1033
+
1034
+ <?php if ( ! SBY_GDPR_Integrations::gdpr_tests_successful( isset( $_GET['retest'] ) ) ) :
1035
+ $errors = SBY_GDPR_Integrations::gdpr_tests_error_message();
1036
+ ?>
1037
+ <div class="sbspf_box sbspf_gdpr_error">
1038
+ <div class="sbspf_box_setting">
1039
+ <p>
1040
+ <strong><?php _e( 'Error:', 'youtube-feed' ); ?></strong> <?php _e("Due to a configuration issue on your web server, the GDPR setting is unable to be enabled. Please see below for more information.", 'youtube-feed' ); ?></p>
1041
+ <p>
1042
+ <?php echo $errors; ?>
1043
+ </p>
1044
+ </div>
1045
+ </div>
1046
+ <?php else: ?>
1047
+
1048
+ <div class="sbspf_gdpr_auto">
1049
+ <?php if ( SBY_GDPR_Integrations::gdpr_plugins_active() ) :
1050
+ $active_plugin = SBY_GDPR_Integrations::gdpr_plugins_active();
1051
+ ?>
1052
+ <div class="sbspf_gdpr_plugin_active">
1053
+ <div class="sbspf_active">
1054
+ <p>
1055
+ <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-check-circle fa-w-16 fa-2x"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z" class=""></path></svg>
1056
+ <b><?php echo sprintf( __( '%s detected', 'youtube-feed' ), $active_plugin ); ?></b>
1057
+ <br />
1058
+ <?php _e( 'Some Feeds for YouTube features will be limited for visitors to ensure GDPR compliance until they give consent.', 'youtube-feed' ); ?>
1059
+ <a href="JavaScript:void(0);" class="sbspf_show_gdpr_list"><?php _e( 'What will be limited?', 'youtube-feed' ); ?></a>
1060
+ </p>
1061
+ <?php echo "<div class='sbspf_gdpr_list'>" . $gdpr_list . '</div>'; ?>
1062
+ </div>
1063
+
1064
+ </div>
1065
+ <?php else: ?>
1066
+ <div class="sbspf_box">
1067
+ <div class="sbspf_box_setting">
1068
+ <p><?php _e( 'No GDPR consent plugin detected. Install a compatible <a href="https://smashballoon.com/doc/gdpr-plugin-list/?youtube">GDPR consent plugin</a>, or manually enable the setting above to display a GDPR compliant version of the feed to all visitors.', 'youtube-feed' ); ?></p>
1069
+ </div>
1070
+ </div>
1071
+ <?php endif; ?>
1072
+ </div>
1073
+
1074
+ <div class="sbspf_box sbspf_gdpr_yes">
1075
+ <div class="sbspf_box_setting">
1076
+ <p><?php _e( "No requests will be made to third-party websites. To accommodate this, some features of the plugin will be limited:", 'youtube-feed' ); ?></p>
1077
+ <?php echo $gdpr_list; ?>
1078
+ </div>
1079
+ </div>
1080
+
1081
+ <div class="sbspf_box sbspf_gdpr_no">
1082
+ <div class="sbspf_box_setting">
1083
+ <p><?php _e( "The plugin will function as normal and load images and videos directly from Twitter.", 'youtube-feed' ); ?></p>
1084
+ </div>
1085
+ </div>
1086
+
1087
+ <?php endif;
1088
+ }
1089
+
1090
+ public function get_connected_accounts() {
1091
+ global $sby_settings;
1092
+
1093
+ if ( isset( $sby_settings['connected_accounts'] ) ) {
1094
+ return $sby_settings['connected_accounts'];
1095
+ }
1096
+ return array();
1097
+ }
1098
+
1099
+ public function access_token_listener() {
1100
+ if ( isset( $_GET['page'] ) && $_GET['page'] === SBY_SLUG && isset( $_GET['sby_access_token'] ) ) {
1101
+ sby_attempt_connection();
1102
+ }
1103
+ }
1104
+
1105
+ public static function connect_account( $args ) {
1106
+ sby_update_or_connect_account( $args );
1107
+ }
1108
+ }
inc/admin/class-sby-new-user.php CHANGED
@@ -1,400 +1,401 @@
1
- <?php
2
- /**
3
- * SBY_New_User.
4
- *
5
- * @since 2.18
6
- */
7
-
8
- // Exit if accessed directly
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class SBY_New_User extends SBY_Notifications {
14
-
15
- /**
16
- * Source of notifications content.
17
- *
18
- * @since 2.18
19
- *
20
- * @var string
21
- */
22
- const SOURCE_URL = 'http://plugin.smashballoon.com/newuser.json';
23
-
24
- /**
25
- * @var string
26
- */
27
- const OPTION_NAME = 'sby_newuser_notifications';
28
-
29
- /**
30
- * Register hooks.
31
- *
32
- * @since 2.18
33
- */
34
- public function hooks() {
35
- add_action( 'admin_notices', array( $this, 'output' ), 8 );
36
-
37
- add_action( 'admin_init', array( $this, 'dismiss' ) );
38
- }
39
-
40
- public function option_name() {
41
- return self::OPTION_NAME;
42
- }
43
-
44
- public function source_url() {
45
- return self::SOURCE_URL;
46
- }
47
-
48
- /**
49
- * Verify notification data before it is saved.
50
- *
51
- * @param array $notifications Array of notifications items to verify.
52
- *
53
- * @return array
54
- *
55
- * @since 2.18
56
- */
57
- public function verify( $notifications ) {
58
- $data = array();
59
-
60
- if ( ! is_array( $notifications ) || empty( $notifications ) ) {
61
- return $data;
62
- }
63
-
64
- $option = $this->get_option();
65
-
66
- foreach ( $notifications as $key => $notification ) {
67
-
68
- // The message should never be empty, if they are, ignore.
69
- if ( empty( $notification['content'] ) ) {
70
- continue;
71
- }
72
-
73
- // Ignore if notification has already been dismissed.
74
- if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
75
- continue;
76
- }
77
-
78
- $data[ $key ] = $notification;
79
- }
80
-
81
- return $data;
82
- }
83
-
84
- /**
85
- * Verify saved notification data for active notifications.
86
- *
87
- * @since 2.18
88
- *
89
- * @param array $notifications Array of notifications items to verify.
90
- *
91
- * @return array
92
- */
93
- public function verify_active( $notifications ) {
94
- if ( ! is_array( $notifications ) || empty( $notifications ) ) {
95
- return array();
96
- }
97
-
98
- $sby_statuses_option = get_option( 'sby_statuses', array() );
99
- $current_time = sby_get_current_time();
100
-
101
- // rating notice logic
102
- $sby_rating_notice_option = get_option( 'sby_rating_notice', false );
103
- $sby_rating_notice_waiting = get_transient( 'feeds_for_youtube_rating_notice_waiting' );
104
- $should_show_rating_notice = ($sby_rating_notice_waiting !== 'waiting' && $sby_rating_notice_option !== 'dismissed');
105
-
106
- // new user discount logic
107
- $in_new_user_month_range = true;
108
- $should_show_new_user_discount = false;
109
- $has_been_one_month_since_rating_dismissal = isset( $sby_statuses_option['rating_notice_dismissed'] ) ? ((int)$sby_statuses_option['rating_notice_dismissed'] + ((int)$notifications['review']['wait'] * DAY_IN_SECONDS)) < $current_time + 1: true;
110
-
111
- if ( isset( $sby_statuses_option['first_install'] ) && $sby_statuses_option['first_install'] === 'from_update' ) {
112
- global $current_user;
113
- $user_id = $current_user->ID;
114
- $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sby_ignore_new_user_sale_notice' );
115
- $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
116
- if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
117
- $should_show_new_user_discount = true;
118
- }
119
- } elseif ( $in_new_user_month_range && $has_been_one_month_since_rating_dismissal && $sby_rating_notice_waiting !== 'waiting' ) {
120
- global $current_user;
121
- $user_id = $current_user->ID;
122
- $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sby_ignore_new_user_sale_notice' );
123
- $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
124
-
125
- if ( $ignore_new_user_sale_notice_meta !== 'always'
126
- && isset( $sby_statuses_option['first_install'] )
127
- && $current_time > (int)$sby_statuses_option['first_install'] + ((int)$notifications['discount']['wait'] * DAY_IN_SECONDS) ) {
128
- $should_show_new_user_discount = true;
129
- }
130
- }
131
-
132
- if ( isset( $notifications['review'] ) && $should_show_rating_notice ) {
133
- return array( $notifications['review'] );
134
- } elseif ( isset( $notifications['discount'] ) && $should_show_new_user_discount ) {
135
- return array( $notifications['discount'] );
136
- }
137
-
138
- return array();
139
- }
140
-
141
- /**
142
- * Get notification data.
143
- *
144
- * @since 2.18
145
- *
146
- * @return array
147
- */
148
- public function get() {
149
- if ( ! $this->has_access() ) {
150
- return array();
151
- }
152
-
153
- $option = $this->get_option();
154
-
155
- // Only update if does not exist.
156
- if ( empty( $option['update'] ) ) {
157
- $this->update();
158
- }
159
-
160
- $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : array();
161
- $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : array();
162
-
163
- return array_merge( $events, $feed );
164
- }
165
-
166
- /**
167
- * Add a manual notification event.
168
- *
169
- * @since 2.18
170
- *
171
- * @param array $notification Notification data.
172
- */
173
- public function add( $notification ) {
174
- if ( empty( $notification['id'] ) ) {
175
- return;
176
- }
177
-
178
- $option = $this->get_option();
179
-
180
- if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
181
- return;
182
- }
183
-
184
- foreach ( $option['events'] as $item ) {
185
- if ( $item['id'] === $notification['id'] ) {
186
- return;
187
- }
188
- }
189
-
190
- $notification = $this->verify( array( $notification ) );
191
-
192
- update_option(
193
- $this->option_name(),
194
- array(
195
- 'update' => $option['update'],
196
- 'feed' => $option['feed'],
197
- 'events' => array_merge( $notification, $option['events'] ),
198
- 'dismissed' => $option['dismissed'],
199
- )
200
- );
201
- }
202
-
203
- /**
204
- * Update notification data from feed.
205
- *
206
- * @since 2.18
207
- */
208
- public function update() {
209
- $feed = $this->fetch_feed();
210
- $option = $this->get_option();
211
-
212
- update_option(
213
- $this->option_name(),
214
- array(
215
- 'update' => time(),
216
- 'feed' => $feed,
217
- 'events' => $option['events'],
218
- 'dismissed' => $option['dismissed'],
219
- )
220
- );
221
- }
222
-
223
- /**
224
- * Do not enqueue anything extra.
225
- *
226
- * @since 2.18
227
- */
228
- public function enqueues() {
229
-
230
- }
231
-
232
- /**
233
- * Output notifications on Form Overview admin area.
234
- *
235
- * @since 2.18
236
- */
237
- public function output() {
238
- // If the Instagram Feed plugin is active, notices only shown on SBY Settings pages
239
- if ( function_exists( 'sb_instagram_activate' )
240
- && ! function_exists( 'sb_instagram_feed_pro_init' ) ) {
241
- return;
242
- }
243
-
244
- if ( function_exists( 'cff_check_for_db_updates' ) ) {
245
- return;
246
- }
247
-
248
- if ( function_exists( 'ctf_check_for_db_updates' ) ) {
249
- return;
250
- }
251
-
252
- $notifications = $this->get();
253
-
254
- if ( empty( $notifications ) ) {
255
- return;
256
- }
257
-
258
- // new user notices included in regular settings page notifications so this
259
- // checks to see if user is one of those pages
260
- if ( ! empty( $_GET['page'] )
261
- && strpos( $_GET['page'], 'youtube-feed' ) !== false ) {
262
- return;
263
- }
264
-
265
- $content_allowed_tags = array(
266
- 'em' => array(),
267
- 'strong' => array(),
268
- 'span' => array(
269
- 'style' => array(),
270
- ),
271
- 'a' => array(
272
- 'href' => array(),
273
- 'target' => array(),
274
- 'rel' => array(),
275
- ),
276
- );
277
- $image_overlay = '';
278
-
279
- foreach ( $notifications as $notification ) {
280
- $type = sanitize_text_field( $notification['id'] );
281
- $img_src = SBY_PLUGIN_URL . 'img/' . sanitize_text_field( $notification['image'] );
282
- $content = '';
283
- if ( ! empty( $notification['content'] ) ) {
284
- $content = wp_kses( $this->replace_merge_fields( $notification['content'], $notification ), $content_allowed_tags );
285
- }
286
- $buttons = array();
287
- if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
288
- foreach ( $notification['btns'] as $btn_type => $btn ) {
289
- if ( ! is_array( $btn['url'] ) ) {
290
- $buttons[ $btn_type ]['url'] = $this->replace_merge_fields( $btn['url'], $notification );
291
- } elseif ( is_array( $btn['url'] ) ) {
292
- $buttons[ $btn_type ]['url'] = add_query_arg( $btn['url'] );
293
- }
294
-
295
- $buttons[ $btn_type ]['attr'] = '';
296
- if ( ! empty( $btn['attr'] ) ) {
297
- $buttons[ $btn_type ]['attr'] = ' target="_blank" rel="noopener noreferrer"';
298
- }
299
-
300
- $buttons[ $btn_type ]['class'] = '';
301
- if ( ! empty( $btn['class'] ) ) {
302
- $buttons[ $btn_type ]['class'] = ' ' . $btn['class'];
303
- }
304
-
305
- $buttons[ $btn_type ]['text'] = '';
306
- if ( ! empty( $btn['text'] ) ) {
307
- $buttons[ $btn_type ]['text'] = wp_kses( $btn['text'], $content_allowed_tags );
308
- }
309
- }
310
- }
311
- if ( isset( $notification['image_overlay'] ) ) {
312
- $image_overlay = '<div class="img-overlay">'. esc_html( $notification['image_overlay'] ).'</div>';
313
- }
314
- }
315
- ?>
316
-
317
- <div class="sby_notice sby_<?php echo esc_attr( $type ); ?>_notice">
318
- <div class="sby_thumb">
319
- <img src="<?php echo esc_url( $img_src ); ?>" alt="notice">
320
- <?php echo $image_overlay; ?>
321
- </div>
322
- <div class="sby-notice-text">
323
- <p style="padding-top: 4px;"><?php echo $content; ?></p>
324
- <p class="links">
325
- <?php foreach ( $buttons as $button ) : ?>
326
- <a class="<?php echo esc_attr( $button['class'] ); ?>" href="<?php echo esc_attr( $button['url'] ); ?>"<?php echo $button['attr']; ?>><?php echo $button['text']; ?></a>
327
- <?php endforeach; ?>
328
- </p>
329
- </div>
330
- <a class="sby_notice_close" href="<?php echo add_query_arg( array( 'sby_dismiss' => $type ) ); ?>"><i class="fa fa-close"></i></a>
331
- </div>
332
- <?php
333
- }
334
-
335
- /**
336
- * Hide messages permanently or some can be dismissed temporarily
337
- *
338
- * @since 2.18
339
- */
340
- public function dismiss() {
341
- global $current_user;
342
- $user_id = $current_user->ID;
343
- $sby_statuses_option = get_option( 'sby_statuses', array() );
344
-
345
- if ( isset( $_GET['sby_ignore_rating_notice_nag'] ) ) {
346
- if ( (int)$_GET['sby_ignore_rating_notice_nag'] === 1 ) {
347
- update_option( 'sby_rating_notice', 'dismissed', false );
348
- $sby_statuses_option['rating_notice_dismissed'] = sby_get_current_time();
349
- update_option( 'sby_statuses', $sby_statuses_option, false );
350
-
351
- } elseif ( $_GET['sby_ignore_rating_notice_nag'] === 'later' ) {
352
- set_transient( 'feeds_for_youtube_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
353
- update_option( 'sby_rating_notice', 'pending', false );
354
- }
355
- }
356
-
357
- if ( isset( $_GET['sby_ignore_new_user_sale_notice'] ) ) {
358
- $response = sanitize_text_field( $_GET['sby_ignore_new_user_sale_notice'] );
359
- if ( $response === 'always' ) {
360
- update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
361
-
362
- $current_month_number = (int)date('n', sby_get_current_time() );
363
- $not_early_in_the_year = ($current_month_number > 5);
364
-
365
- if ( $not_early_in_the_year ) {
366
- update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
367
- }
368
-
369
- }
370
- }
371
-
372
- if ( isset( $_GET['sby_ignore_bfcm_sale_notice'] ) ) {
373
- $response = sanitize_text_field( $_GET['sby_ignore_bfcm_sale_notice'] );
374
- if ( $response === 'always' ) {
375
- update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', 'always' );
376
- } elseif ( $response === date( 'Y', sby_get_current_time() ) ) {
377
- update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
378
- }
379
- update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
380
- }
381
-
382
- if ( isset( $_GET['sby_dismiss'] ) ) {
383
- if ( $_GET['sby_dismiss'] === 'review' ) {
384
- update_option( 'sby_rating_notice', 'dismissed', false );
385
- $sby_statuses_option['rating_notice_dismissed'] = sby_get_current_time();
386
- update_option( 'sby_statuses', $sby_statuses_option, false );
387
- } elseif ( $_GET['sby_dismiss'] === 'discount' ) {
388
- update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
389
-
390
- $current_month_number = (int)date('n', sby_get_current_time() );
391
- $not_early_in_the_year = ($current_month_number > 5);
392
-
393
- if ( $not_early_in_the_year ) {
394
- update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
395
- }
396
- }
397
- update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
398
- }
399
- }
400
- }
 
1
+ <?php
2
+ /**
3
+ * SBY_New_User.
4
+ *
5
+ * @since 2.18
6
+ */
7
+
8
+ // Exit if accessed directly
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class SBY_New_User extends SBY_Notifications {
14
+
15
+ /**
16
+ * Source of notifications content.
17
+ *
18
+ * @since 2.18
19
+ *
20
+ * @var string
21
+ */
22
+ const SOURCE_URL = 'http://plugin.smashballoon.com/newuser.json';
23
+
24
+ /**
25
+ * @var string
26
+ */
27
+ const OPTION_NAME = 'sby_newuser_notifications';
28
+
29
+ /**
30
+ * Register hooks.
31
+ *
32
+ * @since 2.18
33
+ */
34
+ public function hooks() {
35
+ add_action( 'admin_notices', array( $this, 'output' ), 8 );
36
+
37
+ add_action( 'admin_init', array( $this, 'dismiss' ) );
38
+ }
39
+
40
+ public function option_name() {
41
+ return self::OPTION_NAME;
42
+ }
43
+
44
+ public function source_url() {
45
+ return self::SOURCE_URL;
46
+ }
47
+
48
+ /**
49
+ * Verify notification data before it is saved.
50
+ *
51
+ * @param array $notifications Array of notifications items to verify.
52
+ *
53
+ * @return array
54
+ *
55
+ * @since 2.18
56
+ */
57
+ public function verify( $notifications ) {
58
+ $data = array();
59
+
60
+ if ( ! is_array( $notifications ) || empty( $notifications ) ) {
61
+ return $data;
62
+ }
63
+
64
+ $option = $this->get_option();
65
+
66
+ foreach ( $notifications as $key => $notification ) {
67
+
68
+ // The message should never be empty, if they are, ignore.
69
+ if ( empty( $notification['content'] ) ) {
70
+ continue;
71
+ }
72
+
73
+ // Ignore if notification has already been dismissed.
74
+ if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
75
+ continue;
76
+ }
77
+
78
+ $data[ $key ] = $notification;
79
+ }
80
+
81
+ return $data;
82
+ }
83
+
84
+ /**
85
+ * Verify saved notification data for active notifications.
86
+ *
87
+ * @since 2.18
88
+ *
89
+ * @param array $notifications Array of notifications items to verify.
90
+ *
91
+ * @return array
92
+ */
93
+ public function verify_active( $notifications ) {
94
+ if ( ! is_array( $notifications ) || empty( $notifications ) ) {
95
+ return array();
96
+ }
97
+
98
+ $sby_statuses_option = get_option( 'sby_statuses', array() );
99
+ $current_time = sby_get_current_time();
100
+
101
+ // rating notice logic
102
+ $sby_rating_notice_option = get_option( 'sby_rating_notice', false );
103
+ $sby_rating_notice_waiting = get_transient( 'feeds_for_youtube_rating_notice_waiting' );
104
+ $should_show_rating_notice = ($sby_rating_notice_waiting !== 'waiting' && $sby_rating_notice_option !== 'dismissed');
105
+
106
+ // new user discount logic
107
+ $in_new_user_month_range = true;
108
+ $should_show_new_user_discount = false;
109
+ $has_been_one_month_since_rating_dismissal = isset( $sby_statuses_option['rating_notice_dismissed'] ) ? ((int)$sby_statuses_option['rating_notice_dismissed'] + ((int)$notifications['review']['wait'] * DAY_IN_SECONDS)) < $current_time + 1: true;
110
+
111
+ if ( isset( $sby_statuses_option['first_install'] ) && $sby_statuses_option['first_install'] === 'from_update' ) {
112
+ global $current_user;
113
+ $user_id = $current_user->ID;
114
+ $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sby_ignore_new_user_sale_notice' );
115
+ $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
116
+ if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
117
+ $should_show_new_user_discount = true;
118
+ }
119
+ } elseif ( $in_new_user_month_range && $has_been_one_month_since_rating_dismissal && $sby_rating_notice_waiting !== 'waiting' ) {
120
+ global $current_user;
121
+ $user_id = $current_user->ID;
122
+ $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'sby_ignore_new_user_sale_notice' );
123
+ $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
124
+
125
+ if ( $ignore_new_user_sale_notice_meta !== 'always'
126
+ && isset( $sby_statuses_option['first_install'] )
127
+ && $current_time > (int)$sby_statuses_option['first_install'] + ((int)$notifications['discount']['wait'] * DAY_IN_SECONDS) ) {
128
+ $should_show_new_user_discount = true;
129
+ }
130
+ }
131
+
132
+ if ( isset( $notifications['review'] ) && $should_show_rating_notice ) {
133
+ return array( $notifications['review'] );
134
+ } elseif ( isset( $notifications['discount'] ) && $should_show_new_user_discount ) {
135
+ return array( $notifications['discount'] );
136
+ }
137
+
138
+ return array();
139
+ }
140
+
141
+ /**
142
+ * Get notification data.
143
+ *
144
+ * @since 2.18
145
+ *
146
+ * @return array
147
+ */
148
+ public function get() {
149
+ if ( ! $this->has_access() ) {
150
+ return array();
151
+ }
152
+
153
+ $option = $this->get_option();
154
+
155
+ // Only update if does not exist.
156
+ if ( empty( $option['update'] ) ) {
157
+ $this->update();
158
+ }
159
+
160
+ $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : array();
161
+ $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : array();
162
+
163
+ return array_merge( $events, $feed );
164
+ }
165
+
166
+ /**
167
+ * Add a manual notification event.
168
+ *
169
+ * @since 2.18
170
+ *
171
+ * @param array $notification Notification data.
172
+ */
173
+ public function add( $notification ) {
174
+ if ( empty( $notification['id'] ) ) {
175
+ return;
176
+ }
177
+
178
+ $option = $this->get_option();
179
+
180
+ if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
181
+ return;
182
+ }
183
+
184
+ foreach ( $option['events'] as $item ) {
185
+ if ( $item['id'] === $notification['id'] ) {
186
+ return;
187
+ }
188
+ }
189
+
190
+ $notification = $this->verify( array( $notification ) );
191
+
192
+ update_option(
193
+ $this->option_name(),
194
+ array(
195
+ 'update' => $option['update'],
196
+ 'feed' => $option['feed'],
197
+ 'events' => array_merge( $notification, $option['events'] ),
198
+ 'dismissed' => $option['dismissed'],
199
+ )
200
+ );
201
+ }
202
+
203
+ /**
204
+ * Update notification data from feed.
205
+ *
206
+ * @since 2.18
207
+ */
208
+ public function update() {
209
+ $feed = $this->fetch_feed();
210
+ $option = $this->get_option();
211
+
212
+ update_option(
213
+ $this->option_name(),
214
+ array(
215
+ 'update' => time(),
216
+ 'feed' => $feed,
217
+ 'events' => $option['events'],
218
+ 'dismissed' => $option['dismissed'],
219
+ )
220
+ );
221
+ }
222
+
223
+ /**
224
+ * Do not enqueue anything extra.
225
+ *
226
+ * @since 2.18
227
+ */
228
+ public function enqueues() {
229
+
230
+ }
231
+
232
+ /**
233
+ * Output notifications on Form Overview admin area.
234
+ *
235
+ * @since 2.18
236
+ */
237
+ public function output() {
238
+ // If the Instagram Feed plugin is active, notices only shown on SBY Settings pages
239
+ if ( function_exists( 'sb_instagram_activate' )
240
+ && ! function_exists( 'sb_instagram_feed_pro_init' ) ) {
241
+ return;
242
+ }
243
+
244
+ if ( function_exists( 'cff_check_for_db_updates' ) ) {
245
+ return;
246
+ }
247
+
248
+ if ( function_exists( 'ctf_check_for_db_updates' ) ) {
249
+ return;
250
+ }
251
+
252
+ $notifications = $this->get();
253
+
254
+ if ( empty( $notifications ) ) {
255
+ return;
256
+ }
257
+
258
+ // new user notices included in regular settings page notifications so this
259
+ // checks to see if user is one of those pages
260
+ if ( ! empty( $_GET['page'] )
261
+ && strpos( $_GET['page'], 'youtube-feed' ) !== false ) {
262
+ return;
263
+ }
264
+
265
+ $content_allowed_tags = array(
266
+ 'em' => array(),
267
+ 'strong' => array(),
268
+ 'span' => array(
269
+ 'style' => array(),
270
+ ),
271
+ 'a' => array(
272
+ 'href' => array(),
273
+ 'target' => array(),
274
+ 'rel' => array(),
275
+ ),
276
+ );
277
+ $image_overlay = '';
278
+
279
+ foreach ( $notifications as $notification ) {
280
+ $type = sanitize_text_field( $notification['id'] );
281
+ $close_href = add_query_arg( array( 'sby_dismiss' => $type ) );
282
+ $img_src = SBY_PLUGIN_URL . 'img/' . sanitize_text_field( $notification['image'] );
283
+ $content = '';
284
+ if ( ! empty( $notification['content'] ) ) {
285
+ $content = wp_kses( $this->replace_merge_fields( $notification['content'], $notification ), $content_allowed_tags );
286
+ }
287
+ $buttons = array();
288
+ if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
289
+ foreach ( $notification['btns'] as $btn_type => $btn ) {
290
+ if ( ! is_array( $btn['url'] ) ) {
291
+ $buttons[ $btn_type ]['url'] = $this->replace_merge_fields( $btn['url'], $notification );
292
+ } elseif ( is_array( $btn['url'] ) ) {
293
+ $buttons[ $btn_type ]['url'] = add_query_arg( $btn['url'] );
294
+ }
295
+
296
+ $buttons[ $btn_type ]['attr'] = '';
297
+ if ( ! empty( $btn['attr'] ) ) {
298
+ $buttons[ $btn_type ]['attr'] = ' target="_blank" rel="noopener noreferrer"';
299
+ }
300
+
301
+ $buttons[ $btn_type ]['class'] = '';
302
+ if ( ! empty( $btn['class'] ) ) {
303
+ $buttons[ $btn_type ]['class'] = ' ' . $btn['class'];
304
+ }
305
+
306
+ $buttons[ $btn_type ]['text'] = '';
307
+ if ( ! empty( $btn['text'] ) ) {
308
+ $buttons[ $btn_type ]['text'] = wp_kses( $btn['text'], $content_allowed_tags );
309
+ }
310
+ }
311
+ }
312
+ if ( isset( $notification['image_overlay'] ) ) {
313
+ $image_overlay = '<div class="img-overlay">'. esc_html( $notification['image_overlay'] ).'</div>';
314
+ }
315
+ }
316
+ ?>
317
+
318
+ <div class="sby_notice sby_<?php echo esc_attr( $type ); ?>_notice">
319
+ <div class="sby_thumb">
320
+ <img src="<?php echo esc_url( $img_src ); ?>" alt="notice">
321
+ <?php echo $image_overlay; ?>
322
+ </div>
323
+ <div class="sby-notice-text">
324
+ <p style="padding-top: 4px;"><?php echo $content; ?></p>
325
+ <p class="links">
326
+ <?php foreach ( $buttons as $button ) : ?>
327
+ <a class="<?php echo esc_attr( $button['class'] ); ?>" href="<?php echo esc_attr( $button['url'] ); ?>"<?php echo $button['attr']; ?>><?php echo $button['text']; ?></a>
328
+ <?php endforeach; ?>
329
+ </p>
330
+ </div>
331
+ <a class="sby_notice_close" href="<?php echo esc_attr( $close_href ); ?>"><i class="fa fa-close"></i></a>
332
+ </div>
333
+ <?php
334
+ }
335
+
336
+ /**
337
+ * Hide messages permanently or some can be dismissed temporarily
338
+ *
339
+ * @since 2.18
340
+ */
341
+ public function dismiss() {
342
+ global $current_user;
343
+ $user_id = $current_user->ID;
344
+ $sby_statuses_option = get_option( 'sby_statuses', array() );
345
+
346
+ if ( isset( $_GET['sby_ignore_rating_notice_nag'] ) ) {
347
+ if ( (int)$_GET['sby_ignore_rating_notice_nag'] === 1 ) {
348
+ update_option( 'sby_rating_notice', 'dismissed', false );
349
+ $sby_statuses_option['rating_notice_dismissed'] = sby_get_current_time();
350
+ update_option( 'sby_statuses', $sby_statuses_option, false );
351
+
352
+ } elseif ( $_GET['sby_ignore_rating_notice_nag'] === 'later' ) {
353
+ set_transient( 'feeds_for_youtube_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
354
+ update_option( 'sby_rating_notice', 'pending', false );
355
+ }
356
+ }
357
+
358
+ if ( isset( $_GET['sby_ignore_new_user_sale_notice'] ) ) {
359
+ $response = sanitize_text_field( $_GET['sby_ignore_new_user_sale_notice'] );
360
+ if ( $response === 'always' ) {
361
+ update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
362
+
363
+ $current_month_number = (int)date('n', sby_get_current_time() );
364
+ $not_early_in_the_year = ($current_month_number > 5);
365
+
366
+ if ( $not_early_in_the_year ) {
367
+ update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
368
+ }
369
+
370
+ }
371
+ }
372
+
373
+ if ( isset( $_GET['sby_ignore_bfcm_sale_notice'] ) ) {
374
+ $response = sanitize_text_field( $_GET['sby_ignore_bfcm_sale_notice'] );
375
+ if ( $response === 'always' ) {
376
+ update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', 'always' );
377
+ } elseif ( $response === date( 'Y', sby_get_current_time() ) ) {
378
+ update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
379
+ }
380
+ update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
381
+ }
382
+
383
+ if ( isset( $_GET['sby_dismiss'] ) ) {
384
+ if ( $_GET['sby_dismiss'] === 'review' ) {
385
+ update_option( 'sby_rating_notice', 'dismissed', false );
386
+ $sby_statuses_option['rating_notice_dismissed'] = sby_get_current_time();
387
+ update_option( 'sby_statuses', $sby_statuses_option, false );
388
+ } elseif ( $_GET['sby_dismiss'] === 'discount' ) {
389
+ update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
390
+
391
+ $current_month_number = (int)date('n', sby_get_current_time() );
392
+ $not_early_in_the_year = ($current_month_number > 5);
393
+
394
+ if ( $not_early_in_the_year ) {
395
+ update_user_meta( $user_id, 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
396
+ }
397
+ }
398
+ update_user_meta( $user_id, 'sby_ignore_new_user_sale_notice', 'always' );
399
+ }
400
+ }
401
+ }
inc/admin/class-sby-notifications.php CHANGED
@@ -1,582 +1,582 @@
1
- <?php
2
- /**
3
- * SBY_Notifications.
4
- *
5
- * @since 1.7/1.11
6
- */
7
-
8
- // Exit if accessed directly
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class SBY_Notifications {
14
-
15
- /**
16
- * Source of notifications content.
17
- *
18
- * @var string
19
- */
20
- const SOURCE_URL = 'http://plugin.smashballoon.com/notifications.json';
21
-
22
- /**
23
- * @var string
24
- */
25
- const OPTION_NAME = 'sby_notifications';
26
-
27
- /**
28
- * JSON data contains notices for all plugins. This is used
29
- * to select messages only meant for this plugin
30
- *
31
- * @var string
32
- */
33
- const PLUGIN = 'youtube';
34
-
35
- /**
36
- * Option value.
37
- *
38
- * @since 1.7/1.11
39
- *
40
- * @var bool|array
41
- */
42
- public $option = false;
43
-
44
- /**
45
- * Initialize class.
46
- *
47
- * @since 1.7/1.11
48
- */
49
- public function init() {
50
- $this->hooks();
51
- }
52
-
53
- /**
54
- * Use this function to get the option name to allow
55
- * inheritance for the New_User class
56
- *
57
- * @return string
58
- */
59
- public function option_name() {
60
- return self::OPTION_NAME;
61
- }
62
-
63
- /**
64
- * Use this function to get the source URL to allow
65
- * inheritance for the New_User class
66
- *
67
- * @return string
68
- */
69
- public function source_url() {
70
- return self::SOURCE_URL;
71
- }
72
-
73
- /**
74
- * Register hooks.
75
- *
76
- * @since 1.7/1.11
77
- */
78
- public function hooks() {
79
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
80
-
81
- add_action( 'sby_admin_overview_before_title', array( $this, 'output' ) );
82
-
83
- // on cron. Once a week?
84
- add_action( 'sby_notification_update', array( $this, 'update' ) );
85
-
86
- add_action( 'wp_ajax_sby_dashboard_notification_dismiss', array( $this, 'dismiss' ) );
87
- }
88
-
89
-
90
- /**
91
- * Check if user has access and is enabled.
92
- *
93
- * @since 1.7/1.11
94
- *
95
- * @return bool
96
- */
97
- public function has_access() {
98
- $access = false;
99
-
100
- if ( current_user_can( 'manage_options' ) ) {
101
- $access = true;
102
- }
103
-
104
- return apply_filters( 'sby_admin_notifications_has_access', $access );
105
- }
106
-
107
- /**
108
- * Get option value.
109
- *
110
- * @since 1.7/1.11
111
- *
112
- * @param bool $cache Reference property cache if available.
113
- *
114
- * @return array
115
- */
116
- public function get_option( $cache = true ) {
117
- if ( $this->option && $cache ) {
118
- return $this->option;
119
- }
120
-
121
- $option = get_option( $this->option_name(), array() );
122
-
123
- $this->option = array(
124
- 'update' => ! empty( $option['update'] ) ? $option['update'] : 0,
125
- 'events' => ! empty( $option['events'] ) ? $option['events'] : array(),
126
- 'feed' => ! empty( $option['feed'] ) ? $option['feed'] : array(),
127
- 'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : array(),
128
- );
129
-
130
- return $this->option;
131
- }
132
-
133
- /**
134
- * Fetch notifications from feed.
135
- *
136
- * @since 1.7/1.11
137
- *
138
- * @return array
139
- */
140
- public function fetch_feed() {
141
- $res = wp_remote_get( $this->source_url() );
142
-
143
- if ( is_wp_error( $res ) ) {
144
- return array();
145
- }
146
-
147
- $body = wp_remote_retrieve_body( $res );
148
-
149
- if ( empty( $body ) ) {
150
- return array();
151
- }
152
-
153
- $body = str_replace( array( 'sbi_', 'sbi-' ), array( 'sby_', 'sby-' ), $body );
154
-
155
- return $this->verify( json_decode( $body, true ) );
156
- }
157
-
158
- /**
159
- * Verify notification data before it is saved.
160
- *
161
- * @since 1.7/1.11
162
- *
163
- * @param array $notifications Array of notifications items to verify.
164
- *
165
- * @return array
166
- */
167
- public function verify( $notifications ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
168
- $data = array();
169
-
170
- if ( ! is_array( $notifications ) || empty( $notifications ) ) {
171
- return $data;
172
- }
173
-
174
- $option = $this->get_option();
175
-
176
- foreach ( $notifications as $notification ) {
177
-
178
- // The message and license should never be empty, if they are, ignore.
179
- if ( empty( $notification['content'] ) || empty( $notification['type'] ) ) {
180
- continue;
181
- }
182
-
183
- // Ignore if license type does not match.
184
- $license = sby_is_pro_version() ? 'pro' : 'free';
185
-
186
- if ( ! in_array( $license, $notification['type'], true ) ) {
187
- continue;
188
- }
189
-
190
- // Ignore if expired.
191
- if ( ! empty( $notification['end'] ) && sby_get_current_time() > strtotime( $notification['end'] ) ) {
192
- continue;
193
- }
194
-
195
- // Ignore if notification has already been dismissed.
196
- if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
197
- continue;
198
- }
199
-
200
- // TODO: Ignore if notification existed before installing SBY.
201
- // Prevents bombarding the user with notifications after activation.
202
- $activated = false;
203
- if ( ! empty( $activated )
204
- && ! empty( $notification['start'] )
205
- && $activated > strtotime( $notification['start'] ) ) {
206
- continue;
207
- }
208
-
209
- $data[] = $notification;
210
- }
211
-
212
- return $data;
213
- }
214
-
215
- /**
216
- * Verify saved notification data for active notifications.
217
- *
218
- * @since 1.7/1.11
219
- *
220
- * @param array $notifications Array of notifications items to verify.
221
- *
222
- * @return array
223
- */
224
- public function verify_active( $notifications ) {
225
- if ( ! is_array( $notifications ) || empty( $notifications ) ) {
226
- return array();
227
- }
228
-
229
- // Remove notfications that are not active.
230
- foreach ( $notifications as $key => $notification ) {
231
- if ( ( ! empty( $notification['start'] ) && sby_get_current_time() < strtotime( $notification['start'] ) )
232
- || ( ! empty( $notification['end'] ) && sby_get_current_time() > strtotime( $notification['end'] ) ) ) {
233
- unset( $notifications[ $key ] );
234
- }
235
- }
236
-
237
- return $notifications;
238
- }
239
-
240
- /**
241
- * Get notification data.
242
- *
243
- * @since 1.7/1.11
244
- *
245
- * @return array
246
- */
247
- public function get() {
248
- if ( ! $this->has_access() ) {
249
- return array();
250
- }
251
-
252
- $option = $this->get_option();
253
-
254
- // Update notifications using async task.
255
- if ( empty( $option['update'] ) || sby_get_current_time() > $option['update'] + DAY_IN_SECONDS ) {
256
- $this->update();
257
- }
258
-
259
- $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : array();
260
- $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : array();
261
-
262
- // If there is a new user notification, add it to the beginning of the notification list
263
- $sby_newuser = new SBY_New_User();
264
- $newuser_notifications = $sby_newuser->get();
265
-
266
- if ( ! empty( $newuser_notifications ) ) {
267
- $events = array_merge( $newuser_notifications, $events );
268
- }
269
-
270
- return array_merge( $events, $feed );
271
- }
272
-
273
- /**
274
- * Get notification count.
275
- *
276
- * @since 1.7/1.11
277
- *
278
- * @return int
279
- */
280
- public function get_count() {
281
- return count( $this->get() );
282
- }
283
-
284
- /**
285
- * Add a manual notification event.
286
- *
287
- * @since 1.7/1.11
288
- *
289
- * @param array $notification Notification data.
290
- */
291
- public function add( $notification ) {
292
- if ( empty( $notification['id'] ) ) {
293
- return;
294
- }
295
-
296
- $option = $this->get_option();
297
-
298
- if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
299
- return;
300
- }
301
-
302
- foreach ( $option['events'] as $item ) {
303
- if ( $item['id'] === $notification['id'] ) {
304
- return;
305
- }
306
- }
307
-
308
- $notification = $this->verify( array( $notification ) );
309
-
310
- update_option(
311
- 'sby_notifications',
312
- array(
313
- 'update' => $option['update'],
314
- 'feed' => $option['feed'],
315
- 'events' => array_merge( $notification, $option['events'] ),
316
- 'dismissed' => $option['dismissed'],
317
- )
318
- );
319
- }
320
-
321
- /**
322
- * Update notification data from feed.
323
- *
324
- * @since 1.7/1.11
325
- */
326
- public function update() {
327
- $feed = $this->fetch_feed();
328
- $option = $this->get_option();
329
-
330
- update_option(
331
- 'sby_notifications',
332
- array(
333
- 'update' => sby_get_current_time(),
334
- 'feed' => $feed,
335
- 'events' => $option['events'],
336
- 'dismissed' => $option['dismissed'],
337
- )
338
- );
339
- }
340
-
341
- /**
342
- * Admin area Form Overview enqueues.
343
- *
344
- * @since 1.7/1.11
345
- */
346
- public function enqueues() {
347
- if ( ! $this->has_access() ) {
348
- return;
349
- }
350
-
351
- $notifications = $this->get();
352
-
353
- if ( empty( $notifications ) ) {
354
- return;
355
- }
356
-
357
- $min = '';
358
-
359
- wp_enqueue_style(
360
- 'sby-admin-notifications',
361
- SBY_PLUGIN_URL . "css/admin-notifications{$min}.css",
362
- array(),
363
- SBYVER
364
- );
365
-
366
- wp_enqueue_script(
367
- 'sby-admin-notifications',
368
- SBY_PLUGIN_URL . "js/admin-notifications{$min}.js",
369
- array( 'jquery' ),
370
- SBYVER,
371
- true
372
- );
373
-
374
- wp_localize_script( 'sby-admin-notifications', 'sby_admin', array(
375
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
376
- 'nonce' => wp_create_nonce( 'sby-admin' )
377
- )
378
- );
379
- }
380
-
381
- /**
382
- * Fields from the remote source contain placeholders to allow
383
- * some messages to be used for multiple plugins.
384
- *
385
- * @param $content string
386
- * @param $notification array
387
- *
388
- * @return string
389
- *
390
- * @since 1.7/1.11
391
- */
392
- public function replace_merge_fields( $content, $notification ) {
393
- $merge_fields = array(
394
- '{plugin}' => 'Feeds for YouTube',
395
- '{amount}' => isset( $notification['amount'] ) ? $notification['amount'] : '',
396
- '{platform}' => 'YouTube',
397
- '{lowerplatform}' => 'youtube',
398
- '{review-url}' => 'https://wordpress.org/support/plugin/feeds-for-youtube/reviews/',
399
- '{slug}' => 'youtube-feed',
400
- '{campaign}' => 'youtube-free'
401
- );
402
-
403
- if ( sby_is_pro_version() ) {
404
- $merge_fields['{campaign}'] = 'youtube-pro';
405
- $merge_fields['{plugin}'] = 'Feeds for YouTube Pro';
406
- }
407
-
408
- foreach ( $merge_fields as $find => $replace ) {
409
- $content = str_replace( $find, $replace, $content );
410
- }
411
-
412
- return $content;
413
- }
414
-
415
- /**
416
- * Output notifications on Feeds for YouTube admin area.
417
- *
418
- * @since 1.7/1.11
419
- */
420
- public function output() {
421
- $notifications = $this->get();
422
-
423
- if ( empty( $notifications ) ) {
424
- return;
425
- }
426
-
427
- $notifications_html = '';
428
- $current_class = ' current';
429
- $content_allowed_tags = array(
430
- 'em' => array(),
431
- 'strong' => array(),
432
- 'span' => array(
433
- 'style' => array(),
434
- ),
435
- 'a' => array(
436
- 'href' => array(),
437
- 'target' => array(),
438
- 'rel' => array(),
439
- ),
440
- );
441
-
442
- foreach ( $notifications as $notification ) {
443
-
444
- // Buttons HTML.
445
- $buttons_html = '';
446
- if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
447
- foreach ( $notification['btns'] as $btn_type => $btn ) {
448
- if ( is_array( $btn['url'] ) ) {
449
- $btn['url'] = add_query_arg( $btn['url'] );
450
- }
451
- if ( ! empty( $btn['attr'] ) ) {
452
- $btn['target'] = '_blank';
453
- }
454
- $buttons_html .= sprintf(
455
- '<a href="%1$s" class="button button-%2$s"%3$s>%4$s</a>',
456
- ! empty( $btn['url'] ) ? esc_url( $this->replace_merge_fields( $btn['url'], $notification ) ) : '',
457
- $btn_type === 'primary' ? 'primary' : 'secondary',
458
- ! empty( $btn['target'] ) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '',
459
- ! empty( $btn['text'] ) ? sanitize_text_field( $btn['text'] ) : ''
460
- );
461
- }
462
- $buttons_html = ! empty( $buttons_html ) ? '<div class="buttons">' . $buttons_html . '</div>' : '';
463
- }
464
-
465
- if ( empty( $notification['image'] ) ) {
466
- $image_html = '<div class="bell">';
467
-
468
- $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" width="42" height="48" viewBox="0 0 42 48"><defs><style>.a{fill:#777;}.b{fill:#ca4a1f;}</style></defs><path class="a" d="M23-79a6.005,6.005,0,0,1-6-6h10.06a12.066,12.066,0,0,0,1.791,1.308,6.021,6.021,0,0,1-2.077,3.352A6.008,6.008,0,0,1,23-79Zm1.605-9H5.009a2.955,2.955,0,0,1-2.173-.923A3.088,3.088,0,0,1,2-91a2.919,2.919,0,0,1,.807-2.036c.111-.12.229-.243.351-.371a14.936,14.936,0,0,0,3.126-4.409A23.283,23.283,0,0,0,8.007-107.5a14.846,14.846,0,0,1,.906-5.145,14.5,14.5,0,0,1,2.509-4.324A15.279,15.279,0,0,1,20-122.046V-124a3,3,0,0,1,3-3,3,3,0,0,1,3,3v1.954a15.28,15.28,0,0,1,8.58,5.078,14.5,14.5,0,0,1,2.509,4.324,14.846,14.846,0,0,1,.906,5.145c0,.645.016,1.281.047,1.888A12.036,12.036,0,0,0,35-106a11.921,11.921,0,0,0-8.485,3.515A11.923,11.923,0,0,0,23-94a12,12,0,0,0,1.6,6Z" transform="translate(-2 127)"/><circle class="b" cx="9" cy="9" r="9" transform="translate(24 24)"/></svg>';
469
- $image_html .= '</div>';
470
- } else {
471
- if ( $notification['image'] === 'balloon'
472
- || $notification['id'] === 'review'
473
- || $notification['id'] === 'discount') {
474
- $image_html = '<div class="bell">';
475
-
476
- $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1438 1878" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2">';
477
- $image_html .= ' <path d="M671.51004 492.9884C539.9423 433.8663 402.90125 345.5722 274.97656 304.47286c45.45163 108.39592 83.81332 223.88017 123.51 338.03105C319.308 702.00293 226.8217 748.19258 138.46278 798.51607c75.1914 74.32371 181.67968 117.34651 266.52444 182.01607-67.96124 83.86195-201.48527 171.01801-234.02107 247.01998 140.6922-17.6268 304.63688-46.21031 435.53794-52.00418 28.76427 144.58328 43.5987 303.09763 84.50756 435.53713 60.92033-175.26574 116.0014-356.37317 188.51594-520.0451 111.90644 46.2857 248.29012 102.72607 357.52902 130.01188-76.64636-107.5347-146.59346-221.76948-214.5166-338.02903 100.51162-72.83876 202.1718-144.52451 299.02538-221.02092-136.89514-12.61229-278.73428-20.28827-422.53618-25.99865-22.85288-148.33212-16.84826-325.51604-52.005-461.53983-53.19327 111.4882-115.96694 213.39155-175.51418 318.52497m65.00513 1228.60735c-18.0795 77.37586 41.4876 109.11326 32.50298 156.01215-58.8141-20.268-103.0576-30.67962-182.01567-19.50203 2.47018-60.37036 56.76662-68.90959 45.50432-143.0108C-208.90184 1619.4318-210.59186 99.02478 626.00572 5.44992c1046.0409-117.00405 1078.86445 1689.2596 110.50945 1716.14582" fill="#e34f0e"/>';
478
- $image_html .= ' <path d="M847.02422 174.46342c35.15674 136.02379 29.15212 313.20771 52.0046 461.53578 143.8023 5.71443 285.63982 13.38636 422.53658 26.0027-96.85317 76.4964-198.51497 148.18216-299.02579 221.0189 67.92355 116.26239 137.87024 230.49432 214.51864 338.03024-109.24093-27.28662-245.62461-83.72577-357.53106-130.01269-72.51454 163.67274-127.5956 344.78017-188.51553 520.0459-40.90926-132.4395-55.74329-290.95384-84.50796-435.53712-130.90066 5.79549-294.84493 34.37738-435.53754 52.00418 32.5358-76.00075 166.05902-163.156 234.02026-247.02038-84.84516-64.67037-191.33222-107.69074-266.52363-182.01486 88.35892-50.32349 180.8436-96.51314 260.02295-156.0162-39.69708-114.14683-78.05674-229.63108-123.50878-338.027C402.89923 345.5722 539.9423 433.86629 671.51004 492.98839c59.54684-105.13342 122.3209-207.03677 175.51418-318.52497" fill="#fff"/>';
479
- $image_html .= '</svg>';
480
- } else {
481
- $image_html = '<div class="thumb">';
482
- $img_src = SBY_PLUGIN_URL . 'img/' . sanitize_text_field( $notification['image'] );
483
- $image_html .= '<img src="'.esc_url( $img_src ).'" alt="notice">';
484
-
485
- if ( isset( $notification['image_overlay'] ) ) {
486
- $image_html .= '<div class="img-overlay">'. esc_html( str_replace( '%', '%%', $notification['image_overlay'] ) ).'</div>';
487
- }
488
- }
489
-
490
- $image_html .= '</div>';
491
-
492
- }
493
-
494
- // Notification HTML.
495
- $notifications_html .= sprintf(
496
- '<div class="message%5$s" data-message-id="%4$s">' . $image_html . '
497
- <h3 class="title">%1$s</h3>
498
- <p class="content">%2$s</p>
499
- %3$s
500
- </div>',
501
- ! empty( $notification['title'] ) ? $this->replace_merge_fields( sanitize_text_field( $notification['title'] ), $notification ) : '',
502
- ! empty( $notification['content'] ) ? wp_kses( $this->replace_merge_fields( $notification['content'], $notification ), $content_allowed_tags ) : '',
503
- $buttons_html,
504
- ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
505
- $current_class
506
- );
507
-
508
- // Only first notification is current.
509
- $current_class = '';
510
- }
511
- ?>
512
-
513
- <div id="sby-notifications">
514
- <a class="dismiss" title="<?php echo esc_attr__( 'Dismiss this message', 'feeds-for-youtube' ); ?>"><i class="fa fa-times-circle" aria-hidden="true"></i></a>
515
-
516
- <div class="navigation">
517
- <a class="prev disabled" title="<?php echo esc_attr__( 'Previous message', 'feeds-for-youtube' ); ?>"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-left" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-left fa-w-10"><path fill="currentColor" d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z" class=""></path></svg></a>
518
- <a class="next disabled" title="<?php echo esc_attr__( 'Next message', 'feeds-for-youtube' ); ?>"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-right" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-right fa-w-10"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" class=""></path></svg></a>
519
- </div>
520
-
521
- <div class="messages">
522
- <?php echo $notifications_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
523
- </div>
524
- </div>
525
- <?php
526
- }
527
-
528
- /**
529
- * Dismiss notification via AJAX. If it's a new user message, also dismiss it
530
- * on all admin pages.
531
- *
532
- * @since 1.7/1.11
533
- */
534
- public function dismiss() {
535
- // Run a security check.
536
- check_ajax_referer( 'sby-admin', 'nonce' );
537
-
538
- // Check for access and required param.
539
- if ( ! $this->has_access() || empty( $_POST['id'] ) ) {
540
- wp_send_json_error();
541
- }
542
-
543
- $id = sanitize_text_field( wp_unslash( $_POST['id'] ) );
544
-
545
- if ( $id === 'review' ) {
546
- $sby_statuses_option = get_option( 'sby_statuses', array() );
547
-
548
- update_option( 'sby_rating_notice', 'dismissed', false );
549
- $sby_statuses_option['rating_notice_dismissed'] = sby_get_current_time();
550
- update_option( 'sby_statuses', $sby_statuses_option, false );
551
- } elseif ( $id === 'discount' ) {
552
- update_user_meta( get_current_user_id(), 'sby_ignore_new_user_sale_notice', 'always' );
553
-
554
- $current_month_number = (int)date('n', sby_get_current_time() );
555
- $not_early_in_the_year = ($current_month_number > 5);
556
-
557
- if ( $not_early_in_the_year ) {
558
- update_user_meta( get_current_user_id(), 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
559
- }
560
- }
561
-
562
- $option = $this->get_option();
563
- $type = is_numeric( $id ) ? 'feed' : 'events';
564
-
565
- $option['dismissed'][] = $id;
566
- $option['dismissed'] = array_unique( $option['dismissed'] );
567
-
568
- // Remove notification.
569
- if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) {
570
- foreach ( $option[ $type ] as $key => $notification ) {
571
- if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons
572
- unset( $option[ $type ][ $key ] );
573
- break;
574
- }
575
- }
576
- }
577
-
578
- update_option( 'sby_notifications', $option );
579
-
580
- wp_send_json_success();
581
- }
582
- }
1
+ <?php
2
+ /**
3
+ * SBY_Notifications.
4
+ *
5
+ * @since 1.7/1.11
6
+ */
7
+
8
+ // Exit if accessed directly
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class SBY_Notifications {
14
+
15
+ /**
16
+ * Source of notifications content.
17
+ *
18
+ * @var string
19
+ */
20
+ const SOURCE_URL = 'http://plugin.smashballoon.com/notifications.json';
21
+
22
+ /**
23
+ * @var string
24
+ */
25
+ const OPTION_NAME = 'sby_notifications';
26
+
27
+ /**
28
+ * JSON data contains notices for all plugins. This is used
29
+ * to select messages only meant for this plugin
30
+ *
31
+ * @var string
32
+ */
33
+ const PLUGIN = 'youtube';
34
+
35
+ /**
36
+ * Option value.
37
+ *
38
+ * @since 1.7/1.11
39
+ *
40
+ * @var bool|array
41
+ */
42
+ public $option = false;
43
+
44
+ /**
45
+ * Initialize class.
46
+ *
47
+ * @since 1.7/1.11
48
+ */
49
+ public function init() {
50
+ $this->hooks();
51
+ }
52
+
53
+ /**
54
+ * Use this function to get the option name to allow
55
+ * inheritance for the New_User class
56
+ *
57
+ * @return string
58
+ */
59
+ public function option_name() {
60
+ return self::OPTION_NAME;
61
+ }
62
+
63
+ /**
64
+ * Use this function to get the source URL to allow
65
+ * inheritance for the New_User class
66
+ *
67
+ * @return string
68
+ */
69
+ public function source_url() {
70
+ return self::SOURCE_URL;
71
+ }
72
+
73
+ /**
74
+ * Register hooks.
75
+ *
76
+ * @since 1.7/1.11
77
+ */
78
+ public function hooks() {
79
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
80
+
81
+ add_action( 'sby_admin_overview_before_title', array( $this, 'output' ) );
82
+
83
+ // on cron. Once a week?
84
+ add_action( 'sby_notification_update', array( $this, 'update' ) );
85
+
86
+ add_action( 'wp_ajax_sby_dashboard_notification_dismiss', array( $this, 'dismiss' ) );
87
+ }
88
+
89
+
90
+ /**
91
+ * Check if user has access and is enabled.
92
+ *
93
+ * @since 1.7/1.11
94
+ *
95
+ * @return bool
96
+ */
97
+ public function has_access() {
98
+ $access = false;
99
+
100
+ if ( current_user_can( 'manage_options' ) ) {
101
+ $access = true;
102
+ }
103
+
104
+ return apply_filters( 'sby_admin_notifications_has_access', $access );
105
+ }
106
+
107
+ /**
108
+ * Get option value.
109
+ *
110
+ * @since 1.7/1.11
111
+ *
112
+ * @param bool $cache Reference property cache if available.
113
+ *
114
+ * @return array
115
+ */
116
+ public function get_option( $cache = true ) {
117
+ if ( $this->option && $cache ) {
118
+ return $this->option;
119
+ }
120
+
121
+ $option = get_option( $this->option_name(), array() );
122
+
123
+ $this->option = array(
124
+ 'update' => ! empty( $option['update'] ) ? $option['update'] : 0,
125
+ 'events' => ! empty( $option['events'] ) ? $option['events'] : array(),
126
+ 'feed' => ! empty( $option['feed'] ) ? $option['feed'] : array(),
127
+ 'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : array(),
128
+ );
129
+
130
+ return $this->option;
131
+ }
132
+
133
+ /**
134
+ * Fetch notifications from feed.
135
+ *
136
+ * @since 1.7/1.11
137
+ *
138
+ * @return array
139
+ */
140
+ public function fetch_feed() {
141
+ $res = wp_remote_get( $this->source_url() );
142
+
143
+ if ( is_wp_error( $res ) ) {
144
+ return array();
145
+ }
146
+
147
+ $body = wp_remote_retrieve_body( $res );
148
+
149
+ if ( empty( $body ) ) {
150
+ return array();
151
+ }
152
+
153
+ $body = str_replace( array( 'sbi_', 'sbi-' ), array( 'sby_', 'sby-' ), $body );
154
+
155
+ return $this->verify( json_decode( $body, true ) );
156
+ }
157
+
158
+ /**
159
+ * Verify notification data before it is saved.
160
+ *
161
+ * @since 1.7/1.11
162
+ *
163
+ * @param array $notifications Array of notifications items to verify.
164
+ *
165
+ * @return array
166
+ */
167
+ public function verify( $notifications ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
168
+ $data = array();
169
+
170
+ if ( ! is_array( $notifications ) || empty( $notifications ) ) {
171
+ return $data;
172
+ }
173
+
174
+ $option = $this->get_option();
175
+
176
+ foreach ( $notifications as $notification ) {
177
+
178
+ // The message and license should never be empty, if they are, ignore.
179
+ if ( empty( $notification['content'] ) || empty( $notification['type'] ) ) {
180
+ continue;
181
+ }
182
+
183
+ // Ignore if license type does not match.
184
+ $license = sby_is_pro_version() ? 'pro' : 'free';
185
+
186
+ if ( ! in_array( $license, $notification['type'], true ) ) {
187
+ continue;
188
+ }
189
+
190
+ // Ignore if expired.
191
+ if ( ! empty( $notification['end'] ) && sby_get_current_time() > strtotime( $notification['end'] ) ) {
192
+ continue;
193
+ }
194
+
195
+ // Ignore if notification has already been dismissed.
196
+ if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
197
+ continue;
198
+ }
199
+
200
+ // TODO: Ignore if notification existed before installing SBY.
201
+ // Prevents bombarding the user with notifications after activation.
202
+ $activated = false;
203
+ if ( ! empty( $activated )
204
+ && ! empty( $notification['start'] )
205
+ && $activated > strtotime( $notification['start'] ) ) {
206
+ continue;
207
+ }
208
+
209
+ $data[] = $notification;
210
+ }
211
+
212
+ return $data;
213
+ }
214
+
215
+ /**
216
+ * Verify saved notification data for active notifications.
217
+ *
218
+ * @since 1.7/1.11
219
+ *
220
+ * @param array $notifications Array of notifications items to verify.
221
+ *
222
+ * @return array
223
+ */
224
+ public function verify_active( $notifications ) {
225
+ if ( ! is_array( $notifications ) || empty( $notifications ) ) {
226
+ return array();
227
+ }
228
+
229
+ // Remove notfications that are not active.
230
+ foreach ( $notifications as $key => $notification ) {
231
+ if ( ( ! empty( $notification['start'] ) && sby_get_current_time() < strtotime( $notification['start'] ) )
232
+ || ( ! empty( $notification['end'] ) && sby_get_current_time() > strtotime( $notification['end'] ) ) ) {
233
+ unset( $notifications[ $key ] );
234
+ }
235
+ }
236
+
237
+ return $notifications;
238
+ }
239
+
240
+ /**
241
+ * Get notification data.
242
+ *
243
+ * @since 1.7/1.11
244
+ *
245
+ * @return array
246
+ */
247
+ public function get() {
248
+ if ( ! $this->has_access() ) {
249
+ return array();
250
+ }
251
+
252
+ $option = $this->get_option();
253
+
254
+ // Update notifications using async task.
255
+ if ( empty( $option['update'] ) || sby_get_current_time() > $option['update'] + DAY_IN_SECONDS ) {
256
+ $this->update();
257
+ }
258
+
259
+ $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : array();
260
+ $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : array();
261
+
262
+ // If there is a new user notification, add it to the beginning of the notification list
263
+ $sby_newuser = new SBY_New_User();
264
+ $newuser_notifications = $sby_newuser->get();
265
+
266
+ if ( ! empty( $newuser_notifications ) ) {
267
+ $events = array_merge( $newuser_notifications, $events );
268
+ }
269
+
270
+ return array_merge( $events, $feed );
271
+ }
272
+
273
+ /**
274
+ * Get notification count.
275
+ *
276
+ * @since 1.7/1.11
277
+ *
278
+ * @return int
279
+ */
280
+ public function get_count() {
281
+ return count( $this->get() );
282
+ }
283
+
284
+ /**
285
+ * Add a manual notification event.
286
+ *
287
+ * @since 1.7/1.11
288
+ *
289
+ * @param array $notification Notification data.
290
+ */
291
+ public function add( $notification ) {
292
+ if ( empty( $notification['id'] ) ) {
293
+ return;
294
+ }
295
+
296
+ $option = $this->get_option();
297
+
298
+ if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
299
+ return;
300
+ }
301
+
302
+ foreach ( $option['events'] as $item ) {
303
+ if ( $item['id'] === $notification['id'] ) {
304
+ return;
305
+ }
306
+ }
307
+
308
+ $notification = $this->verify( array( $notification ) );
309
+
310
+ update_option(
311
+ 'sby_notifications',
312
+ array(
313
+ 'update' => $option['update'],
314
+ 'feed' => $option['feed'],
315
+ 'events' => array_merge( $notification, $option['events'] ),
316
+ 'dismissed' => $option['dismissed'],
317
+ )
318
+ );
319
+ }
320
+
321
+ /**
322
+ * Update notification data from feed.
323
+ *
324
+ * @since 1.7/1.11
325
+ */
326
+ public function update() {
327
+ $feed = $this->fetch_feed();
328
+ $option = $this->get_option();
329
+
330
+ update_option(
331
+ 'sby_notifications',
332
+ array(
333
+ 'update' => sby_get_current_time(),
334
+ 'feed' => $feed,
335
+ 'events' => $option['events'],
336
+ 'dismissed' => $option['dismissed'],
337
+ )
338
+ );
339
+ }
340
+
341
+ /**
342
+ * Admin area Form Overview enqueues.
343
+ *
344
+ * @since 1.7/1.11
345
+ */
346
+ public function enqueues() {
347
+ if ( ! $this->has_access() ) {
348
+ return;
349
+ }
350
+
351
+ $notifications = $this->get();
352
+
353
+ if ( empty( $notifications ) ) {
354
+ return;
355
+ }
356
+
357
+ $min = '';
358
+
359
+ wp_enqueue_style(
360
+ 'sby-admin-notifications',
361
+ SBY_PLUGIN_URL . "css/admin-notifications{$min}.css",
362
+ array(),
363
+ SBYVER
364
+ );
365
+
366
+ wp_enqueue_script(
367
+ 'sby-admin-notifications',
368
+ SBY_PLUGIN_URL . "js/admin-notifications{$min}.js",
369
+ array( 'jquery' ),
370
+ SBYVER,
371
+ true
372
+ );
373
+
374
+ wp_localize_script( 'sby-admin-notifications', 'sby_admin', array(
375
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
376
+ 'nonce' => wp_create_nonce( 'sby-admin' )
377
+ )
378
+ );
379
+ }
380
+
381
+ /**
382
+ * Fields from the remote source contain placeholders to allow
383
+ * some messages to be used for multiple plugins.
384
+ *
385
+ * @param $content string
386
+ * @param $notification array
387
+ *
388
+ * @return string
389
+ *
390
+ * @since 1.7/1.11
391
+ */
392
+ public function replace_merge_fields( $content, $notification ) {
393
+ $merge_fields = array(
394
+ '{plugin}' => 'Feeds for YouTube',
395
+ '{amount}' => isset( $notification['amount'] ) ? $notification['amount'] : '',
396
+ '{platform}' => 'YouTube',
397
+ '{lowerplatform}' => 'youtube',
398
+ '{review-url}' => 'https://wordpress.org/support/plugin/feeds-for-youtube/reviews/',
399
+ '{slug}' => 'youtube-feed',
400
+ '{campaign}' => 'youtube-free'
401
+ );
402
+
403
+ if ( sby_is_pro_version() ) {
404
+ $merge_fields['{campaign}'] = 'youtube-pro';
405
+ $merge_fields['{plugin}'] = 'Feeds for YouTube Pro';
406
+ }
407
+
408
+ foreach ( $merge_fields as $find => $replace ) {
409
+ $content = str_replace( $find, $replace, $content );
410
+ }
411
+
412
+ return $content;
413
+ }
414
+
415
+ /**
416
+ * Output notifications on Feeds for YouTube admin area.
417
+ *
418
+ * @since 1.7/1.11
419
+ */
420
+ public function output() {
421
+ $notifications = $this->get();
422
+
423
+ if ( empty( $notifications ) ) {
424
+ return;
425
+ }
426
+
427
+ $notifications_html = '';
428
+ $current_class = ' current';
429
+ $content_allowed_tags = array(
430
+ 'em' => array(),
431
+ 'strong' => array(),
432
+ 'span' => array(
433
+ 'style' => array(),
434
+ ),
435
+ 'a' => array(
436
+ 'href' => array(),
437
+ 'target' => array(),
438
+ 'rel' => array(),
439
+ ),
440
+ );
441
+
442
+ foreach ( $notifications as $notification ) {
443
+
444
+ // Buttons HTML.
445
+ $buttons_html = '';
446
+ if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
447
+ foreach ( $notification['btns'] as $btn_type => $btn ) {
448
+ if ( is_array( $btn['url'] ) ) {
449
+ $btn['url'] = add_query_arg( $btn['url'] );
450
+ }
451
+ if ( ! empty( $btn['attr'] ) ) {
452
+ $btn['target'] = '_blank';
453
+ }
454
+ $buttons_html .= sprintf(
455
+ '<a href="%1$s" class="button button-%2$s"%3$s>%4$s</a>',
456
+ ! empty( $btn['url'] ) ? esc_url( $this->replace_merge_fields( $btn['url'], $notification ) ) : '',
457
+ $btn_type === 'primary' ? 'primary' : 'secondary',
458
+ ! empty( $btn['target'] ) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '',
459
+ ! empty( $btn['text'] ) ? sanitize_text_field( $btn['text'] ) : ''
460
+ );
461
+ }
462
+ $buttons_html = ! empty( $buttons_html ) ? '<div class="buttons">' . $buttons_html . '</div>' : '';
463
+ }
464
+
465
+ if ( empty( $notification['image'] ) ) {
466
+ $image_html = '<div class="bell">';
467
+
468
+ $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" width="42" height="48" viewBox="0 0 42 48"><defs><style>.a{fill:#777;}.b{fill:#ca4a1f;}</style></defs><path class="a" d="M23-79a6.005,6.005,0,0,1-6-6h10.06a12.066,12.066,0,0,0,1.791,1.308,6.021,6.021,0,0,1-2.077,3.352A6.008,6.008,0,0,1,23-79Zm1.605-9H5.009a2.955,2.955,0,0,1-2.173-.923A3.088,3.088,0,0,1,2-91a2.919,2.919,0,0,1,.807-2.036c.111-.12.229-.243.351-.371a14.936,14.936,0,0,0,3.126-4.409A23.283,23.283,0,0,0,8.007-107.5a14.846,14.846,0,0,1,.906-5.145,14.5,14.5,0,0,1,2.509-4.324A15.279,15.279,0,0,1,20-122.046V-124a3,3,0,0,1,3-3,3,3,0,0,1,3,3v1.954a15.28,15.28,0,0,1,8.58,5.078,14.5,14.5,0,0,1,2.509,4.324,14.846,14.846,0,0,1,.906,5.145c0,.645.016,1.281.047,1.888A12.036,12.036,0,0,0,35-106a11.921,11.921,0,0,0-8.485,3.515A11.923,11.923,0,0,0,23-94a12,12,0,0,0,1.6,6Z" transform="translate(-2 127)"/><circle class="b" cx="9" cy="9" r="9" transform="translate(24 24)"/></svg>';
469
+ $image_html .= '</div>';
470
+ } else {
471
+ if ( $notification['image'] === 'balloon'
472
+ || $notification['id'] === 'review'
473
+ || $notification['id'] === 'discount') {
474
+ $image_html = '<div class="bell">';
475
+
476
+ $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1438 1878" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2">';
477
+ $image_html .= ' <path d="M671.51004 492.9884C539.9423 433.8663 402.90125 345.5722 274.97656 304.47286c45.45163 108.39592 83.81332 223.88017 123.51 338.03105C319.308 702.00293 226.8217 748.19258 138.46278 798.51607c75.1914 74.32371 181.67968 117.34651 266.52444 182.01607-67.96124 83.86195-201.48527 171.01801-234.02107 247.01998 140.6922-17.6268 304.63688-46.21031 435.53794-52.00418 28.76427 144.58328 43.5987 303.09763 84.50756 435.53713 60.92033-175.26574 116.0014-356.37317 188.51594-520.0451 111.90644 46.2857 248.29012 102.72607 357.52902 130.01188-76.64636-107.5347-146.59346-221.76948-214.5166-338.02903 100.51162-72.83876 202.1718-144.52451 299.02538-221.02092-136.89514-12.61229-278.73428-20.28827-422.53618-25.99865-22.85288-148.33212-16.84826-325.51604-52.005-461.53983-53.19327 111.4882-115.96694 213.39155-175.51418 318.52497m65.00513 1228.60735c-18.0795 77.37586 41.4876 109.11326 32.50298 156.01215-58.8141-20.268-103.0576-30.67962-182.01567-19.50203 2.47018-60.37036 56.76662-68.90959 45.50432-143.0108C-208.90184 1619.4318-210.59186 99.02478 626.00572 5.44992c1046.0409-117.00405 1078.86445 1689.2596 110.50945 1716.14582" fill="#e34f0e"/>';
478
+ $image_html .= ' <path d="M847.02422 174.46342c35.15674 136.02379 29.15212 313.20771 52.0046 461.53578 143.8023 5.71443 285.63982 13.38636 422.53658 26.0027-96.85317 76.4964-198.51497 148.18216-299.02579 221.0189 67.92355 116.26239 137.87024 230.49432 214.51864 338.03024-109.24093-27.28662-245.62461-83.72577-357.53106-130.01269-72.51454 163.67274-127.5956 344.78017-188.51553 520.0459-40.90926-132.4395-55.74329-290.95384-84.50796-435.53712-130.90066 5.79549-294.84493 34.37738-435.53754 52.00418 32.5358-76.00075 166.05902-163.156 234.02026-247.02038-84.84516-64.67037-191.33222-107.69074-266.52363-182.01486 88.35892-50.32349 180.8436-96.51314 260.02295-156.0162-39.69708-114.14683-78.05674-229.63108-123.50878-338.027C402.89923 345.5722 539.9423 433.86629 671.51004 492.98839c59.54684-105.13342 122.3209-207.03677 175.51418-318.52497" fill="#fff"/>';
479
+ $image_html .= '</svg>';
480
+ } else {
481
+ $image_html = '<div class="thumb">';
482
+ $img_src = SBY_PLUGIN_URL . 'img/' . sanitize_text_field( $notification['image'] );
483
+ $image_html .= '<img src="'.esc_url( $img_src ).'" alt="notice">';
484
+
485
+ if ( isset( $notification['image_overlay'] ) ) {
486
+ $image_html .= '<div class="img-overlay">'. esc_html( str_replace( '%', '%%', $notification['image_overlay'] ) ).'</div>';
487
+ }
488
+ }
489
+
490
+ $image_html .= '</div>';
491
+
492
+ }
493
+
494
+ // Notification HTML.
495
+ $notifications_html .= sprintf(
496
+ '<div class="message%5$s" data-message-id="%4$s">' . $image_html . '
497
+ <h3 class="title">%1$s</h3>
498
+ <p class="content">%2$s</p>
499
+ %3$s
500
+ </div>',
501
+ ! empty( $notification['title'] ) ? $this->replace_merge_fields( sanitize_text_field( $notification['title'] ), $notification ) : '',
502
+ ! empty( $notification['content'] ) ? wp_kses( $this->replace_merge_fields( $notification['content'], $notification ), $content_allowed_tags ) : '',
503
+ $buttons_html,
504
+ ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
505
+ $current_class
506
+ );
507
+
508
+ // Only first notification is current.
509
+ $current_class = '';
510
+ }
511
+ ?>
512
+
513
+ <div id="sby-notifications">
514
+ <a class="dismiss" title="<?php echo esc_attr__( 'Dismiss this message', 'feeds-for-youtube' ); ?>"><i class="fa fa-times-circle" aria-hidden="true"></i></a>
515
+
516
+ <div class="navigation">
517
+ <a class="prev disabled" title="<?php echo esc_attr__( 'Previous message', 'feeds-for-youtube' ); ?>"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-left" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-left fa-w-10"><path fill="currentColor" d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z" class=""></path></svg></a>
518
+ <a class="next disabled" title="<?php echo esc_attr__( 'Next message', 'feeds-for-youtube' ); ?>"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-right" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-right fa-w-10"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" class=""></path></svg></a>
519
+ </div>
520
+
521
+ <div class="messages">
522
+ <?php echo $notifications_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
523
+ </div>
524
+ </div>
525
+ <?php
526
+ }
527
+
528
+ /**
529
+ * Dismiss notification via AJAX. If it's a new user message, also dismiss it
530
+ * on all admin pages.
531
+ *
532
+ * @since 1.7/1.11
533
+ */
534
+ public function dismiss() {
535
+ // Run a security check.
536
+ check_ajax_referer( 'sby-admin', 'nonce' );
537
+
538
+ // Check for access and required param.
539
+ if ( ! $this->has_access() || empty( $_POST['id'] ) ) {
540
+ wp_send_json_error();
541
+ }
542
+
543
+ $id = sanitize_text_field( wp_unslash( $_POST['id'] ) );
544
+
545
+ if ( $id === 'review' ) {
546
+ $sby_statuses_option = get_option( 'sby_statuses', array() );
547
+
548
+ update_option( 'sby_rating_notice', 'dismissed', false );
549
+ $sby_statuses_option['rating_notice_dismissed'] = sby_get_current_time();
550
+ update_option( 'sby_statuses', $sby_statuses_option, false );
551
+ } elseif ( $id === 'discount' ) {
552
+ update_user_meta( get_current_user_id(), 'sby_ignore_new_user_sale_notice', 'always' );
553
+
554
+ $current_month_number = (int)date('n', sby_get_current_time() );
555
+ $not_early_in_the_year = ($current_month_number > 5);
556
+
557
+ if ( $not_early_in_the_year ) {
558
+ update_user_meta( get_current_user_id(), 'sby_ignore_bfcm_sale_notice', date( 'Y', sby_get_current_time() ) );
559
+ }
560
+ }
561
+
562
+ $option = $this->get_option();
563
+ $type = is_numeric( $id ) ? 'feed' : 'events';
564
+
565
+ $option['dismissed'][] = $id;
566
+ $option['dismissed'] = array_unique( $option['dismissed'] );
567
+
568
+ // Remove notification.
569
+ if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) {
570
+ foreach ( $option[ $type ] as $key => $notification ) {
571
+ if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons
572
+ unset( $option[ $type ][ $key ] );
573
+ break;
574
+ }
575
+ }
576
+ }
577
+
578
+ update_option( 'sby_notifications', $option );
579
+
580
+ wp_send_json_success();
581
+ }
582
+ }
inc/admin/templates/allfeeds.php CHANGED
@@ -1,86 +1,86 @@
1
- <?php
2
- /**
3
- * Custom Feeds for Twitter Feed Locator Summary Template
4
- * Creates the HTML for the feed locator summary
5
- *
6
- * @version 1.14 Custom Feeds for Twitter Pro by Smash Balloon
7
- *
8
- */
9
- // Don't load directly
10
- if ( ! defined( 'ABSPATH' ) ) {
11
- die( '-1' );
12
- }
13
- $locator_summary = SBY_Feed_Locator::summary();
14
- $database_settings = sby_get_database_settings();
15
- ?>
16
- <div class="sby-feed-locator-summary-wrap">
17
- <h3><?php esc_html_e( 'Feed Finder Summary', 'feeds-for-youtube' ); ?></h3>
18
- <p><?php esc_html_e( 'The table below shows a record of all feeds found on your site. A feed may not show up here immediately after being created.', 'feeds-for-youtube' ); ?></p>
19
- <?php
20
- if ( ! empty( $locator_summary ) ) : ?>
21
-
22
- <?php foreach ( $locator_summary as $locator_section ) :
23
- if ( ! empty( $locator_section['results'] ) ) : ?>
24
- <div class="sby-single-location">
25
- <h4><?php echo esc_html( $locator_section['label'] ); ?></h4>
26
- <table class="widefat striped">
27
- <thead>
28
- <tr>
29
- <th><?php esc_html_e( 'Type', 'feeds-for-youtube' ); ?></th>
30
- <th><?php esc_html_e( 'Sources', 'feeds-for-youtube' ); ?></th>
31
- <th><?php esc_html_e( 'Shortcode', 'feeds-for-youtube' ); ?></th>
32
- <th><?php esc_html_e( 'Location', 'feeds-for-youtube' ); ?></th>
33
- </tr>
34
- </thead>
35
- <tbody>
36
-
37
- <?php foreach ( $locator_section['results'] as $result ) :
38
- $shortcode_atts = json_decode( $result['shortcode_atts'], true );
39
- $shortcode_atts = is_array( $shortcode_atts ) ? $shortcode_atts : array();
40
-
41
- if ( class_exists( 'SBY_Settings_Pro' ) ) {
42
- $settings_obj = new SBY_Settings_Pro( $shortcode_atts, $database_settings );
43
- } else {
44
- $settings_obj = new SBY_Settings( $shortcode_atts, $database_settings );
45
- }
46
- $settings = $settings_obj->get_settings();
47
- $settings_obj->set_feed_type_and_terms();
48
- $display_terms = $settings_obj->feed_type_and_terms_display();
49
- $comma_separated = implode(', ', $display_terms );
50
- //$comma_separated = implode(', ', array() );
51
- $display = $comma_separated;
52
- if ( strlen( $comma_separated ) > 31 ) {
53
- $display = '<span class="sby-condensed-wrap">' . substr( $comma_separated, 0, 30 ) . '<a class="sby-locator-more" href="JavaScript:void(0);">...</a></span>';
54
- $comma_separated = '<span class="sby-full-wrap">' . esc_html( $comma_separated ) . '</span>';
55
- } else {
56
- $comma_separated = '';
57
- }
58
- $type = isset( $settings['type'] ) ? $settings['type'] : 'user';
59
- $full_shortcode_string = '[youtube-feed';
60
- foreach ( $shortcode_atts as $key => $value ) {
61
- $full_shortcode_string .= ' ' . esc_html( $key ) . '="' . esc_html( $value ) . '"';
62
- }
63
- $full_shortcode_string .= ']';
64
- ?>
65
- <tr>
66
- <td><?php echo esc_html( $type ); ?></td>
67
- <td><?php echo $display . $comma_separated; ?></td>
68
- <td>
69
- <span class="sby-condensed-wrap"><a class="sby-locator-more" href="JavaScript:void(0);"><?php esc_html_e( 'Show', 'feeds-for-youtube' ); ?></a></span>
70
- <span class="sby-full-wrap"><?php echo $full_shortcode_string; ?></span>
71
- </td>
72
- <td><a href="<?php echo esc_url( get_the_permalink( $result['post_id'] ) ); ?>" target="_blank" rel="noopener"><?php echo esc_html( get_the_title( $result['post_id'] ) ); ?></a></td>
73
- </tr>
74
- <?php endforeach; ?>
75
-
76
-
77
- </tbody>
78
- </table>
79
- </div>
80
-
81
- <?php endif;
82
- endforeach;
83
- else: ?>
84
- <p><?php esc_html_e( 'Locations of your feeds are currently being detected. You\'ll see more information posted here soon!', 'feeds-for-youtube' ); ?></p>
85
- <?php endif; ?>
86
  </div>
1
+ <?php
2
+ /**
3
+ * Custom Feeds for Twitter Feed Locator Summary Template
4
+ * Creates the HTML for the feed locator summary
5
+ *
6
+ * @version 1.14 Custom Feeds for Twitter Pro by Smash Balloon
7
+ *
8
+ */
9
+ // Don't load directly
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ die( '-1' );
12
+ }
13
+ $locator_summary = SBY_Feed_Locator::summary();
14
+ $database_settings = sby_get_database_settings();
15
+ ?>
16
+ <div class="sby-feed-locator-summary-wrap">
17
+ <h3><?php esc_html_e( 'Feed Finder Summary', 'feeds-for-youtube' ); ?></h3>
18
+ <p><?php esc_html_e( 'The table below shows a record of all feeds found on your site. A feed may not show up here immediately after being created.', 'feeds-for-youtube' ); ?></p>
19
+ <?php
20
+ if ( ! empty( $locator_summary ) ) : ?>
21
+
22
+ <?php foreach ( $locator_summary as $locator_section ) :
23
+ if ( ! empty( $locator_section['results'] ) ) : ?>
24
+ <div class="sby-single-location">
25
+ <h4><?php echo esc_html( $locator_section['label'] ); ?></h4>
26
+ <table class="widefat striped">
27
+ <thead>
28
+ <tr>
29
+ <th><?php esc_html_e( 'Type', 'feeds-for-youtube' ); ?></th>
30
+ <th><?php esc_html_e( 'Sources', 'feeds-for-youtube' ); ?></th>
31
+ <th><?php esc_html_e( 'Shortcode', 'feeds-for-youtube' ); ?></th>
32
+ <th><?php esc_html_e( 'Location', 'feeds-for-youtube' ); ?></th>
33
+ </tr>
34
+ </thead>
35
+ <tbody>
36
+
37
+ <?php foreach ( $locator_section['results'] as $result ) :
38
+ $shortcode_atts = json_decode( $result['shortcode_atts'], true );
39
+ $shortcode_atts = is_array( $shortcode_atts ) ? $shortcode_atts : array();
40
+
41
+ if ( class_exists( 'SBY_Settings_Pro' ) ) {
42
+ $settings_obj = new SBY_Settings_Pro( $shortcode_atts, $database_settings );
43
+ } else {
44
+ $settings_obj = new SBY_Settings( $shortcode_atts, $database_settings );
45
+ }
46
+ $settings = $settings_obj->get_settings();
47
+ $settings_obj->set_feed_type_and_terms();
48
+ $display_terms = $settings_obj->feed_type_and_terms_display();
49
+ $comma_separated = implode(', ', $display_terms );
50
+ //$comma_separated = implode(', ', array() );
51
+ $display = $comma_separated;
52
+ if ( strlen( $comma_separated ) > 31 ) {
53
+ $display = '<span class="sby-condensed-wrap">' . esc_html( substr( $comma_separated, 0, 30 ) ) . '<a class="sby-locator-more" href="JavaScript:void(0);">...</a></span>';
54
+ $comma_separated = '<span class="sby-full-wrap">' . esc_html( $comma_separated ) . '</span>';
55
+ } else {
56
+ $comma_separated = '';
57
+ }
58
+ $type = isset( $settings['type'] ) ? $settings['type'] : 'user';
59
+ $full_shortcode_string = '[youtube-feed';
60
+ foreach ( $shortcode_atts as $key => $value ) {
61
+ $full_shortcode_string .= ' ' . esc_html( $key ) . '="' . esc_html( $value ) . '"';
62
+ }
63
+ $full_shortcode_string .= ']';
64
+ ?>
65
+ <tr>
66
+ <td><?php echo esc_html( $type ); ?></td>
67
+ <td><?php echo $display . $comma_separated; ?></td>
68
+ <td>
69
+ <span class="sby-condensed-wrap"><a class="sby-locator-more" href="JavaScript:void(0);"><?php esc_html_e( 'Show', 'feeds-for-youtube' ); ?></a></span>
70
+ <span class="sby-full-wrap"><?php echo $full_shortcode_string; ?></span>
71
+ </td>
72
+ <td><a href="<?php echo esc_url( get_the_permalink( $result['post_id'] ) ); ?>" target="_blank" rel="noopener"><?php echo esc_html( get_the_title( $result['post_id'] ) ); ?></a></td>
73
+ </tr>
74
+ <?php endforeach; ?>
75
+
76
+
77
+ </tbody>
78
+ </table>
79
+ </div>
80
+
81
+ <?php endif;
82
+ endforeach;
83
+ else: ?>
84
+ <p><?php esc_html_e( 'Locations of your feeds are currently being detected. You\'ll see more information posted here soon!', 'feeds-for-youtube' ); ?></p>
85
+ <?php endif; ?>
86
  </div>
inc/admin/templates/configure.php CHANGED
@@ -1,42 +1,42 @@
1
- <h3><?php _e( 'Configure', $text_domain ); ?></h3>
2
- <div id="sbspf_config">
3
- <?php
4
- $notice_not_dismissed = sby_notice_not_dismissed( 'sby_connect_warning_notice' );
5
- $warning_data_att = $notice_not_dismissed ? ' data-show-warning="1"' : '';
6
- ?>
7
- <a href="<?php echo $oauth_processor_url . admin_url( 'admin.php?page=' . esc_attr( $slug ) ); ?>" id="sbspf_get_token"<?php echo $warning_data_att; ?>><?php echo sby_icon( $slug, 'sbspf_small_svg' ); ?> <?php echo sprintf( __( 'Connect to %s to Create a Feed', $text_domain ), $social_network ); ?></a>
8
- <a class="sbspf_not_working" href="https://smashballoon.com/<?php echo esc_attr( $slug ); ?>/token/" target="_blank"><?php _e( "Button not working?", $text_domain ); ?></a>
9
- </div>
10
-
11
- <form method="post" action="">
12
- <?php
13
- $settings = $this->settings;
14
- $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
15
- ?>
16
- <table class="form-table sbspf_own_credentials_wrap" role="presentation">
17
- <tbody>
18
- <tr>
19
- <th scope="row">
20
- <label for="sby_app_id"><?php _e( "API Key", $text_domain ); ?></label>
21
- <p class="sbspf_aside sbspf_red"><?php _e( "Recommended", $text_domain ); ?></p>
22
- </th>
23
- <td>
24
- <input name="<?php echo $this->get_option_name(); ?>[api_key]" id="sby_api_key" type="text" value="<?php echo esc_attr( $api_key ); ?>" size="64" minlength="15" maxlength="200" />
25
- <p class="sbspf_aside"><?php echo __( 'Entering an API key is <strong>optional</strong> but recommended. It allows the plugin to fetch older videos and prevents potential disruption in your feed. It only takes a few minutes: <a href="https://smashballoon.com/youtube-api-key/" target="_blank" rel="noopener">Get my API key.</a>', $text_domain ); ?></p>
26
- </td>
27
- </tr>
28
-
29
- </tbody>
30
- </table>
31
- <?php $this->hidden_fields_for_tab( 'configure' ); ?>
32
- <?php include_once $this->get_path( 'connected-accounts' ); ?>
33
-
34
- <?php foreach ( $this->get_sections( 'configure' ) as $section ) : ?>
35
-
36
- <?php do_settings_sections( $section['id'] ); // matches the section name ?>
37
- <?php if ( $section['save_after'] ) : ?>
38
- <p class="submit"><input class="button-primary" type="submit" name="save" value="<?php esc_attr_e( 'Save Changes' ); ?>" /></p>
39
- <?php endif; ?>
40
- <hr>
41
- <?php endforeach; ?>
42
  </form>
1
+ <h3><?php _e( 'Configure', $text_domain ); ?></h3>
2
+ <div id="sbspf_config">
3
+ <?php
4
+ $notice_not_dismissed = sby_notice_not_dismissed( 'sby_connect_warning_notice' );
5
+ $warning_data_att = $notice_not_dismissed ? ' data-show-warning="1"' : '';
6
+ ?>
7
+ <a href="<?php echo $oauth_processor_url . admin_url( 'admin.php?page=' . esc_attr( $slug ) ); ?>" id="sbspf_get_token"<?php echo $warning_data_att; ?>><?php echo sby_icon( $slug, 'sbspf_small_svg' ); ?> <?php echo sprintf( __( 'Connect to %s to Create a Feed', $text_domain ), $social_network ); ?></a>
8
+ <a class="sbspf_not_working" href="https://smashballoon.com/<?php echo esc_attr( $slug ); ?>/token/" target="_blank"><?php _e( "Button not working?", $text_domain ); ?></a>
9
+ </div>
10
+
11
+ <form method="post" action="">
12
+ <?php
13
+ $settings = $this->settings;
14
+ $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
15
+ ?>
16
+ <table class="form-table sbspf_own_credentials_wrap" role="presentation">
17
+ <tbody>
18
+ <tr>
19
+ <th scope="row">
20
+ <label for="sby_app_id"><?php _e( "API Key", $text_domain ); ?></label>
21
+ <p class="sbspf_aside sbspf_red"><?php _e( "Recommended", $text_domain ); ?></p>
22
+ </th>
23
+ <td>
24
+ <input name="<?php echo $this->get_option_name(); ?>[api_key]" id="sby_api_key" type="text" value="<?php echo esc_attr( $api_key ); ?>" size="64" minlength="15" maxlength="200" />
25
+ <p class="sbspf_aside"><?php echo __( 'Entering an API key is <strong>optional</strong> but recommended. It allows the plugin to fetch older videos and prevents potential disruption in your feed. It only takes a few minutes: <a href="https://smashballoon.com/youtube-api-key/" target="_blank" rel="noopener">Get my API key.</a>', $text_domain ); ?></p>
26
+ </td>
27
+ </tr>
28
+
29
+ </tbody>
30
+ </table>
31
+ <?php $this->hidden_fields_for_tab( 'configure' ); ?>
32
+ <?php include_once $this->get_path( 'connected-accounts' ); ?>
33
+
34
+ <?php foreach ( $this->get_sections( 'configure' ) as $section ) : ?>
35
+
36
+ <?php do_settings_sections( $section['id'] ); // matches the section name ?>
37
+ <?php if ( $section['save_after'] ) : ?>
38
+ <p class="submit"><input class="button-primary" type="submit" name="save" value="<?php esc_attr_e( 'Save Changes' ); ?>" /></p>
39
+ <?php endif; ?>
40
+ <hr>
41
+ <?php endforeach; ?>
42
  </form>
inc/admin/templates/connected-accounts.php CHANGED
@@ -1,41 +1,41 @@
1
- <?php
2
- $connected_accounts = $this->get_connected_accounts();
3
- $connected_channels = array();
4
- ?>
5
- <table class="form-table sbspf_connected-accounts-wrap" role="presentation">
6
- <tbody>
7
- <tr>
8
- <th scope="row">
9
- <label><?php echo sprintf( __( '%s Accounts', $text_domain ), $social_network ); ?></label>
10
- <span style="font-weight:normal; font-style:italic; font-size: 12px; display: block;"><?php echo sprintf( __( 'Use the button above to connect %s account', $text_domain ), $sn_with_a_an ); ?></span>
11
- </th>
12
- <td class="sbspf_connected_accounts_wrap">
13
- <?php if ( empty( $connected_accounts ) ) : ?>
14
- <p class="sbspf_no_accounts"><?php echo sprintf( __( 'No %s accounts connected. Click the button above to connect an account.', $text_domain ), $social_network ); ?></p><br />
15
- <?php else: ?>
16
- <?php foreach ( $connected_accounts as $account ) :
17
- $username = $account['username'] ? $account['username'] : $account['channel_id'];
18
- if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['sbspf_favor_local'] ) && $options['sbspf_favor_local' ] === 'on' ) {
19
- $upload = wp_upload_dir();
20
- $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
21
- $profile_picture = '<img class="sbspf_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
22
- } else {
23
- $profile_picture = $account['profile_picture'] ? '<img class="sbspf_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
24
- }
25
- $is_invalid_class = ! $account['is_valid'] ? ' sbspf_account_invalid' : '';
26
- $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
27
- $use_tagged = isset( $account['use_tagged'] ) && $account['use_tagged'] == '1';
28
-
29
- include $this->get_path( 'single-connected-account' );
30
- ?>
31
- <?php endforeach; ?>
32
- <?php endif; ?>
33
- <a href="JavaScript:void(0);" class="sbspf_manually_connect button-secondary"><?php _e( 'Manually Connect a Primary Account', $text_domain ); ?></a>
34
- <div class="sbspf_manually_connect_wrap">
35
- <input name="sbspf_manual_at" id="sbspf_manual_at" type="text" value="" style="margin-top: 4px; padding: 5px 9px; margin-left: 0px;" size="64" minlength="15" maxlength="200" placeholder="<?php _e('Enter a valid Access Token', $text_domain );?>" />
36
- <p class="sbspf_submit" style="display: inline-block;"><input type="sbspf_submit" name="submit" id="sbspf_manual_submit" class="button button-primary" style="text-align: center; padding: 0;" value="<?php _e('Connect This Account', $text_domain );?>"></p>
37
- </div>
38
- </td>
39
- </tr>
40
- </tbody>
41
  </table>
1
+ <?php
2
+ $connected_accounts = $this->get_connected_accounts();
3
+ $connected_channels = array();
4
+ ?>
5
+ <table class="form-table sbspf_connected-accounts-wrap" role="presentation">
6
+ <tbody>
7
+ <tr>
8
+ <th scope="row">
9
+ <label><?php echo sprintf( __( '%s Accounts', $text_domain ), $social_network ); ?></label>
10
+ <span style="font-weight:normal; font-style:italic; font-size: 12px; display: block;"><?php echo sprintf( __( 'Use the button above to connect %s account', $text_domain ), $sn_with_a_an ); ?></span>
11
+ </th>
12
+ <td class="sbspf_connected_accounts_wrap">
13
+ <?php if ( empty( $connected_accounts ) ) : ?>
14
+ <p class="sbspf_no_accounts"><?php echo sprintf( __( 'No %s accounts connected. Click the button above to connect an account.', $text_domain ), $social_network ); ?></p><br />
15
+ <?php else: ?>
16
+ <?php foreach ( $connected_accounts as $account ) :
17
+ $username = $account['username'] ? $account['username'] : $account['channel_id'];
18
+ if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['sbspf_favor_local'] ) && $options['sbspf_favor_local' ] === 'on' ) {
19
+ $upload = wp_upload_dir();
20
+ $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBI_UPLOADS_NAME );
21
+ $profile_picture = '<img class="sbspf_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
22
+ } else {
23
+ $profile_picture = $account['profile_picture'] ? '<img class="sbspf_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
24
+ }
25
+ $is_invalid_class = ! $account['is_valid'] ? ' sbspf_account_invalid' : '';
26
+ $account_type = isset( $account['type'] ) ? $account['type'] : 'personal';
27
+ $use_tagged = isset( $account['use_tagged'] ) && $account['use_tagged'] == '1';
28
+
29
+ include $this->get_path( 'single-connected-account' );
30
+ ?>
31
+ <?php endforeach; ?>
32
+ <?php endif; ?>
33
+ <a href="JavaScript:void(0);" class="sbspf_manually_connect button-secondary"><?php _e( 'Manually Connect a Primary Account', $text_domain ); ?></a>
34
+ <div class="sbspf_manually_connect_wrap">
35
+ <input name="sbspf_manual_at" id="sbspf_manual_at" type="text" value="" style="margin-top: 4px; padding: 5px 9px; margin-left: 0px;" size="64" minlength="15" maxlength="200" placeholder="<?php _e('Enter a valid Access Token', $text_domain );?>" />
36
+ <p class="sbspf_submit" style="display: inline-block;"><input type="sbspf_submit" name="submit" id="sbspf_manual_submit" class="button button-primary" style="text-align: center; padding: 0;" value="<?php _e('Connect This Account', $text_domain );?>"></p>
37
+ </div>
38
+ </td>
39
+ </tr>
40
+ </tbody>
41
  </table>
inc/admin/templates/customize.php CHANGED
@@ -1,33 +1,33 @@
1
- <p class="sbspf-contents-links" id="general">
2
- <span>Quick links: </span>
3
- <a href="#layout"><?php _e( 'Layout', $text_domain ); ?></a>
4
- <a href="#header"><?php _e( 'Header', $text_domain ); ?></a>
5
- <a href="#loadmore"><?php _e( 'Buttons', $text_domain ); ?></a>
6
- <a href="#gdpr"><?php _e( 'GDPR', $text_domain ); ?></a>
7
- <a href="#advanced"><?php _e( 'Advanced', $text_domain ); ?></a>
8
-
9
- </p>
10
- <form method="post" action="">
11
- <?php $this->hidden_fields_for_tab( 'customize' ); ?>
12
-
13
- <?php foreach ( $this->get_sections( 'customize' ) as $section ) :
14
- if ( $section['pro'] ) : ?>
15
- <div class="sbspf_pro_section">
16
- <p style="padding-bottom: 18px;" class="sbspf_pro_reveal">
17
- <a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank"><?php echo esc_html( $section['pro'] ); ?></a><br>
18
- <a href="javascript:void(0);" class="button button-secondary sbspf-show-pro"><b>+</b> <?php _e( 'Show Pro Options', $text_domain ); ?></a>
19
- </p>
20
- <?php endif; ?>
21
- <span id="<?php echo str_replace( 'sbspf_', '', $section['id'] ); ?>"></span>
22
-
23
- <?php
24
- do_settings_sections( $section['id'] ); // matches the section name
25
- if ( $section['pro'] ) {
26
- echo '</div>';
27
- }
28
- if ( $section['save_after'] ) : ?>
29
- <p class="submit"><input class="button-primary" type="submit" name="save" value="<?php esc_attr_e( 'Save Changes' ); ?>" /></p>
30
- <?php endif; ?>
31
- <hr>
32
- <?php endforeach; ?>
33
- </form>
1
+ <p class="sbspf-contents-links" id="general">
2
+ <span>Quick links: </span>
3
+ <a href="#layout"><?php _e( 'Layout', $text_domain ); ?></a>
4
+ <a href="#header"><?php _e( 'Header', $text_domain ); ?></a>
5
+ <a href="#loadmore"><?php _e( 'Buttons', $text_domain ); ?></a>
6
+ <a href="#gdpr"><?php _e( 'GDPR', $text_domain ); ?></a>
7
+ <a href="#advanced"><?php _e( 'Advanced', $text_domain ); ?></a>
8
+
9
+ </p>
10
+ <form method="post" action="">
11
+ <?php $this->hidden_fields_for_tab( 'customize' ); ?>
12
+
13
+ <?php foreach ( $this->get_sections( 'customize' ) as $section ) :
14
+ if ( $section['pro'] ) : ?>
15
+ <div class="sbspf_pro_section">
16
+ <p style="padding-bottom: 18px;" class="sbspf_pro_reveal">
17
+ <a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank"><?php echo esc_html( $section['pro'] ); ?></a><br>
18
+ <a href="javascript:void(0);" class="button button-secondary sbspf-show-pro"><b>+</b> <?php _e( 'Show Pro Options', $text_domain ); ?></a>
19
+ </p>
20
+ <?php endif; ?>
21
+ <span id="<?php echo str_replace( 'sbspf_', '', $section['id'] ); ?>"></span>
22
+
23
+ <?php
24
+ do_settings_sections( $section['id'] ); // matches the section name
25
+ if ( $section['pro'] ) {
26
+ echo '</div>';
27
+ }
28
+ if ( $section['save_after'] ) : ?>
29
+ <p class="submit"><input class="button-primary" type="submit" name="save" value="<?php esc_attr_e( 'Save Changes' ); ?>" /></p>
30
+ <?php endif; ?>
31
+ <hr>
32
+ <?php endforeach; ?>
33
+ </form>
inc/admin/templates/display.php CHANGED
@@ -1,42 +1,42 @@
1
- <h3><?php _e( 'Display your Feed', $text_domain ); ?></h3>
2
- <p><?php _e( "Copy and paste the following shortcode directly into the page, post or widget where you'd like the feed to show up:", $text_domain ); ?></p>
3
- <input type="text" value="[<?php echo $slug; ?>]" size="20" readonly="readonly" style="text-align: center;" onclick="this.focus();this.select()" title="<?php _e( 'To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain ); ?>" />
4
-
5
- <h3 style="padding-top: 10px;"><?php _e( 'Multiple Feeds', $text_domain ); ?></h3>
6
- <p><?php _e( "If you'd like to display multiple feeds then you can set different settings directly in the shortcode like so:", $text_domain ); ?>
7
- </br><code>[<?php echo $slug; ?> channel=gopro num=9]</code></p>
8
- <p><?php _e( "You can display as many different feeds as you like, on either the same page or on different pages, by just using the shortcode options below. For example:", $text_domain ); ?><br />
9
- <code>[<?php echo $slug; ?>]</code><br />
10
- <code>[<?php echo $slug; ?> channel="ANOTHER_CHANNEL"]</code><br />
11
- <code>[<?php echo $slug; ?> num=4 showheader=false]</code>
12
- </p>
13
- <p><?php _e( "See the table below for a full list of available shortcode options:", $text_domain ); ?></p>
14
- <p><span class="sbspf_table_key"></span><?php _e( "Pro version only", $text_domain ); ?></p>
15
- <table class="sbspf_shortcode_table">
16
- <tbody>
17
- <tr valign="top">
18
- <th scope="row"><?php _e( 'Shortcode option', $text_domain ); ?></th>
19
- <th scope="row"><?php _e( 'Description', $text_domain ); ?></th>
20
- <th scope="row"><?php _e( 'Example', $text_domain ); ?></th>
21
- </tr>
22
-
23
- <?php foreach ( $this->display_your_feed_sections as $display_your_feed_section ) : ?>
24
- <tr class="sbspf_table_header"><td colspan=3><?php echo $display_your_feed_section['label'] ?></td></tr>
25
- <?php foreach ( $display_your_feed_section['settings'] as $setting ) :
26
- $pro_only_class = '';
27
- if ( in_array( $setting['key'], $this->pro_only, true ) ) {
28
- $pro_only_class = ' class="sbspf_pro_only"';
29
- }
30
- ?>
31
- <tr<?php echo $pro_only_class; ?>>
32
- <td><?php echo $setting['key']; ?></td>
33
- <td><?php echo $setting['description']; ?></td>
34
- <td><code>[<?php echo $slug; ?> <?php echo $setting['key']; ?>="<?php echo str_replace('"', '', $setting['example'] ); ?>"]</code></td>
35
- </tr>
36
- <?php endforeach; ?>
37
-
38
- <?php endforeach; ?>
39
-
40
- </tbody>
41
- </table>
42
- <p><?php echo sby_admin_icon( 'question-circle', 'sbspf_small_svg' ); ?>&nbsp; <?php _e('Need help?', $text_domain ); ?> <a href="?page=<?php echo esc_attr( $slug ); ?>&tab=support"><?php _e('Get Support', $text_domain ); ?></a></p>
1
+ <h3><?php _e( 'Display your Feed', $text_domain ); ?></h3>
2
+ <p><?php _e( "Copy and paste the following shortcode directly into the page, post or widget where you'd like the feed to show up:", $text_domain ); ?></p>
3
+ <input type="text" value="[<?php echo $slug; ?>]" size="20" readonly="readonly" style="text-align: center;" onclick="this.focus();this.select()" title="<?php _e( 'To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain ); ?>" />
4
+
5
+ <h3 style="padding-top: 10px;"><?php _e( 'Multiple Feeds', $text_domain ); ?></h3>
6
+ <p><?php _e( "If you'd like to display multiple feeds then you can set different settings directly in the shortcode like so:", $text_domain ); ?>
7
+ </br><code>[<?php echo $slug; ?> channel=gopro num=9]</code></p>
8
+ <p><?php _e( "You can display as many different feeds as you like, on either the same page or on different pages, by just using the shortcode options below. For example:", $text_domain ); ?><br />
9
+ <code>[<?php echo $slug; ?>]</code><br />
10
+ <code>[<?php echo $slug; ?> channel="ANOTHER_CHANNEL"]</code><br />
11
+ <code>[<?php echo $slug; ?> num=4 showheader=false]</code>
12
+ </p>
13
+ <p><?php _e( "See the table below for a full list of available shortcode options:", $text_domain ); ?></p>
14
+ <p><span class="sbspf_table_key"></span><?php _e( "Pro version only", $text_domain ); ?></p>
15
+ <table class="sbspf_shortcode_table">
16
+ <tbody>
17
+ <tr valign="top">
18
+ <th scope="row"><?php _e( 'Shortcode option', $text_domain ); ?></th>
19
+ <th scope="row"><?php _e( 'Description', $text_domain ); ?></th>
20
+ <th scope="row"><?php _e( 'Example', $text_domain ); ?></th>
21
+ </tr>
22
+
23
+ <?php foreach ( $this->display_your_feed_sections as $display_your_feed_section ) : ?>
24
+ <tr class="sbspf_table_header"><td colspan=3><?php echo $display_your_feed_section['label'] ?></td></tr>
25
+ <?php foreach ( $display_your_feed_section['settings'] as $setting ) :
26
+ $pro_only_class = '';
27
+ if ( in_array( $setting['key'], $this->pro_only, true ) ) {
28
+ $pro_only_class = ' class="sbspf_pro_only"';
29
+ }
30
+ ?>
31
+ <tr<?php echo $pro_only_class; ?>>
32
+ <td><?php echo $setting['key']; ?></td>
33
+ <td><?php echo $setting['description']; ?></td>
34
+ <td><code>[<?php echo $slug; ?> <?php echo $setting['key']; ?>="<?php echo str_replace('"', '', $setting['example'] ); ?>"]</code></td>
35
+ </tr>
36
+ <?php endforeach; ?>
37
+
38
+ <?php endforeach; ?>
39
+
40
+ </tbody>
41
+ </table>
42
+ <p><?php echo sby_admin_icon( 'question-circle', 'sbspf_small_svg' ); ?>&nbsp; <?php _e('Need help?', $text_domain ); ?> <a href="?page=<?php echo esc_attr( $slug ); ?>&tab=support"><?php _e('Get Support', $text_domain ); ?></a></p>
inc/admin/templates/main.php CHANGED
@@ -1,83 +1,83 @@
1
- <?php
2
- $vars = $this->get_vars();
3
- $text_domain = $vars->text_domain();
4
- $setup_url = $vars->setup_url();
5
- $oauth_processor_url = $vars->oauth_processor_url();
6
- $social_network = $vars->social_network();
7
- $sn_with_a_an = $vars->social_network( true );
8
- $plugin_version = $vars->version();
9
- $demo_url = $vars->demo_url();
10
- $pro_logo = $vars->pro_logo();
11
-
12
- if ( isset( $_POST[ $this->get_option_name() . '_validate' ] ) && $this->verify_post( $_POST ) ) {
13
- $tab = isset( $_POST[ $this->get_option_name() . '_tab_marker' ] ) ? sanitize_text_field( $_POST[ $this->get_option_name() . '_tab_marker' ] ) : 'main';
14
- $new_settings = $this->validate_options( $_POST[ $this->get_option_name() ], $tab );
15
- $this->update_options( $new_settings );
16
- ?>
17
- <div class="updated"><p><strong><?php _e('Settings saved.', $text_domain ); ?></strong></p></div>
18
-
19
- <?php
20
- }
21
- $plugin_name = $this->get_plugin_name();
22
- $active_tab = $this->get_active_tab();
23
- $slug = $this->get_slug();
24
- $tabs = $this->get_tabs();
25
- ?>
26
-
27
- <div id="sbspf_admin" class="wrap sbspf-admin sby_admin" data-sb-plugin="sbspf">
28
- <?php
29
- $lite_notice_dismissed = get_transient( 'youtube_feed_dismiss_lite' );
30
-
31
- if ( ! $lite_notice_dismissed ) :
32
- ?>
33
- <div id="sbspf-notice-bar" style="display:none">
34
- <span class="sbspf-notice-bar-message"><?php _e( 'You\'re using Feeds for YouTube Lite. To unlock more features consider <a href="https://smashballoon.com/youtube-feed/?utm_source=WordPress&utm_campaign=youtubeliteplugin&utm_medium=notice-bar" target="_blank" rel="noopener noreferrer">upgrading to Pro</a>.', $text_domain ); ?></span>
35
- <button type="button" class="dismiss" title="<?php _e( 'Dismiss this message.', $text_domain ); ?>" data-page="overview">
36
- </button>
37
- </div>
38
- <?php endif; ?>
39
-
40
- <?php do_action( 'sby_admin_overview_before_title' ); ?>
41
-
42
- <h1><?php echo esc_html( $plugin_name ); ?></h1>
43
-
44
- <!-- Display the tabs along with styling for the 'active' tab -->
45
- <h2 class="nav-tab-wrapper">
46
- <?php
47
- $i = 1;
48
- foreach ( $tabs as $tab ) :
49
- if ( ! isset( $tab['has_nav_tab'] ) ) :
50
- $title = isset( $tab['numbered_tab'] ) && ! $tab['numbered_tab'] ? __( $tab['title'], 'feeds-for-youtube' ) : $i . '. ' . __( $tab['title'], 'feeds-for-youtube' );
51
- ?>
52
- <a href="admin.php?page=<?php echo esc_attr( $slug ); ?>&tab=<?php echo esc_attr( $tab['slug'] ); ?>" class="nav-tab <?php if ( $active_tab === $tab['slug'] ){ echo 'nav-tab-active'; } ?>"><?php echo $title; ?></a>
53
- <?php
54
- $i ++;
55
- endif;
56
- endforeach; ?>
57
- </h2>
58
- <?php
59
- settings_errors();
60
-
61
- include $this->get_path( $active_tab );
62
-
63
- $next_step = $this->next_step();
64
- if ( ! empty( $next_step ) ) : ?>
65
- <p class="sbspf_footer_help">
66
- <?php echo sby_admin_icon( 'chevron-right', 'sbspf_small_svg' ) ; ?>&nbsp; <?php _e('Next Step', $text_domain ); ?>: <a href="?page=<?php echo esc_attr( $slug ); ?>&tab=<?php echo esc_attr( $next_step['next_tab'] ); ?>"><?php echo esc_html( __( $next_step['instructions'], 'feeds-for-youtube' ) ); ?></a>
67
- </p>
68
- <?php endif; ?>
69
-
70
- <p class="sbspf_footer_help"><?php echo sby_admin_icon( 'life-ring', 'sbspf_small_svg' ); ?>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="' . esc_url( $setup_url ) . '" target="_blank">setup directions</a>', $text_domain); ?></p>
71
-
72
- <div class="sbspf-quick-start">
73
- <h3><?php echo sby_admin_icon( 'rocket', 'sbspf_small_svg' ); ?>&nbsp; <?php _e( 'Display your feed', $text_domain); ?></h3>
74
- <p><?php _e( "Copy and paste this shortcode directly into the page, post or widget where you'd like to display the feed:", $text_domain ); ?>
75
- <input type="text" value="[<?php echo $slug; ?>]" size="18" readonly="readonly" style="text-align: center;" onclick="this.focus();this.select()" title="<?php _e( 'To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain ); ?>" /></p>
76
- <p><?php _e( "Find out how to display <a href='?page=".$slug."&tab=display'>multiple feeds</a>.", $text_domain ); ?></p>
77
- </div>
78
-
79
- <a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&utm_campaign=sby" target="_blank" class="sbspf-pro-notice"><img src="<?php echo SBY_PLUGIN_URL . 'img/pro.png' ?>" alt="Pro" /></a>
80
-
81
-
82
- </div>
83
  <div class="wp-clearfix"></div>
1
+ <?php
2
+ $vars = $this->get_vars();
3
+ $text_domain = $vars->text_domain();
4
+ $setup_url = $vars->setup_url();
5
+ $oauth_processor_url = $vars->oauth_processor_url();
6
+ $social_network = $vars->social_network();
7
+ $sn_with_a_an = $vars->social_network( true );
8
+ $plugin_version = $vars->version();
9
+ $demo_url = $vars->demo_url();
10
+ $pro_logo = $vars->pro_logo();
11
+
12
+ if ( isset( $_POST[ $this->get_option_name() . '_validate' ] ) && $this->verify_post( $_POST ) ) {
13
+ $tab = isset( $_POST[ $this->get_option_name() . '_tab_marker' ] ) ? sanitize_text_field( $_POST[ $this->get_option_name() . '_tab_marker' ] ) : 'main';
14
+ $new_settings = $this->validate_options( $_POST[ $this->get_option_name() ], $tab );
15
+ $this->update_options( $new_settings );
16
+ ?>
17
+ <div class="updated"><p><strong><?php _e('Settings saved.', $text_domain ); ?></strong></p></div>
18
+
19
+ <?php
20
+ }
21
+ $plugin_name = $this->get_plugin_name();
22
+ $active_tab = $this->get_active_tab();
23
+ $slug = $this->get_slug();
24
+ $tabs = $this->get_tabs();
25
+ ?>
26
+
27
+ <div id="sbspf_admin" class="wrap sbspf-admin sby_admin" data-sb-plugin="sbspf">
28
+ <?php
29
+ $lite_notice_dismissed = get_transient( 'youtube_feed_dismiss_lite' );
30
+
31
+ if ( ! $lite_notice_dismissed ) :
32
+ ?>
33
+ <div id="sbspf-notice-bar" style="display:none">
34
+ <span class="sbspf-notice-bar-message"><?php _e( 'You\'re using Feeds for YouTube Lite. To unlock more features consider <a href="https://smashballoon.com/youtube-feed/?utm_source=WordPress&utm_campaign=youtubeliteplugin&utm_medium=notice-bar" target="_blank" rel="noopener noreferrer">upgrading to Pro</a>.', $text_domain ); ?></span>
35
+ <button type="button" class="dismiss" title="<?php _e( 'Dismiss this message.', $text_domain ); ?>" data-page="overview">
36
+ </button>
37
+ </div>
38
+ <?php endif; ?>
39
+
40
+ <?php do_action( 'sby_admin_overview_before_title' ); ?>
41
+
42
+ <h1><?php echo esc_html( $plugin_name ); ?></h1>
43
+
44
+ <!-- Display the tabs along with styling for the 'active' tab -->
45
+ <h2 class="nav-tab-wrapper">
46
+ <?php
47
+ $i = 1;
48
+ foreach ( $tabs as $tab ) :
49
+ if ( ! isset( $tab['has_nav_tab'] ) ) :
50
+ $title = isset( $tab['numbered_tab'] ) && ! $tab['numbered_tab'] ? __( $tab['title'], 'feeds-for-youtube' ) : $i . '. ' . __( $tab['title'], 'feeds-for-youtube' );
51
+ ?>
52
+ <a href="admin.php?page=<?php echo esc_attr( $slug ); ?>&tab=<?php echo esc_attr( $tab['slug'] ); ?>" class="nav-tab <?php if ( $active_tab === $tab['slug'] ){ echo 'nav-tab-active'; } ?>"><?php echo $title; ?></a>
53
+ <?php
54
+ $i ++;
55
+ endif;
56
+ endforeach; ?>
57
+ </h2>
58
+ <?php
59
+ settings_errors();
60
+
61
+ include $this->get_path( $active_tab );
62
+
63
+ $next_step = $this->next_step();
64
+ if ( ! empty( $next_step ) ) : ?>
65
+ <p class="sbspf_footer_help">
66
+ <?php echo sby_admin_icon( 'chevron-right', 'sbspf_small_svg' ) ; ?>&nbsp; <?php _e('Next Step', $text_domain ); ?>: <a href="?page=<?php echo esc_attr( $slug ); ?>&tab=<?php echo esc_attr( $next_step['next_tab'] ); ?>"><?php echo esc_html( __( $next_step['instructions'], 'feeds-for-youtube' ) ); ?></a>
67
+ </p>
68
+ <?php endif; ?>
69
+
70
+ <p class="sbspf_footer_help"><?php echo sby_admin_icon( 'life-ring', 'sbspf_small_svg' ); ?>&nbsp; <?php _e('Need help setting up the plugin? Check out our <a href="' . esc_url( $setup_url ) . '" target="_blank">setup directions</a>', $text_domain); ?></p>
71
+
72
+ <div class="sbspf-quick-start">
73
+ <h3><?php echo sby_admin_icon( 'rocket', 'sbspf_small_svg' ); ?>&nbsp; <?php _e( 'Display your feed', $text_domain); ?></h3>
74
+ <p><?php _e( "Copy and paste this shortcode directly into the page, post or widget where you'd like to display the feed:", $text_domain ); ?>
75
+ <input type="text" value="[<?php echo $slug; ?>]" size="18" readonly="readonly" style="text-align: center;" onclick="this.focus();this.select()" title="<?php _e( 'To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain ); ?>" /></p>
76
+ <p><?php _e( "Find out how to display <a href='?page=".$slug."&tab=display'>multiple feeds</a>.", $text_domain ); ?></p>
77
+ </div>
78
+
79
+ <a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&utm_campaign=sby" target="_blank" class="sbspf-pro-notice"><img src="<?php echo SBY_PLUGIN_URL . 'img/pro.png' ?>" alt="Pro" /></a>
80
+
81
+
82
+ </div>
83
  <div class="wp-clearfix"></div>
inc/admin/templates/modal.php CHANGED
@@ -1,16 +1,16 @@
1
- <div id="sbspf_modal_overlay">
2
- <div class="sbspf_modal">
3
- <div class="sbspf_modal_message">
4
- <div class="sby_after_connection">
5
- <p class="heading"><?php _e ( 'You have successfully connected your account' ); ?></p>
6
- <p><?php _e ( 'You may receive an email from Google notifying you that our plugin has been granted read-access to your account.', $text_domain ); ?></p>
7
- <p class="sbspf_submit">
8
- <a href="JavaScript:void(0);" class="button button-secondary sbspf_dismiss_at_warning_button" data-action="sby_dismiss_at_warning_notice"><?php esc_html_e( 'Dismiss', $text_domain); ?></a>
9
- </p>
10
- <a href="JavaScript:void(0);" class="sbspf_modal_close sbspf_dismiss_at_warning_button" data-action="sby_dismiss_at_warning_notice"><i class="fa fa-times"></i></a>
11
-
12
- </div>
13
- </div>
14
-
15
- </div>
16
  </div>
1
+ <div id="sbspf_modal_overlay">
2
+ <div class="sbspf_modal">
3
+ <div class="sbspf_modal_message">
4
+ <div class="sby_after_connection">
5
+ <p class="heading"><?php _e ( 'You have successfully connected your account' ); ?></p>
6
+ <p><?php _e ( 'You may receive an email from Google notifying you that our plugin has been granted read-access to your account.', $text_domain ); ?></p>
7
+ <p class="sbspf_submit">
8
+ <a href="JavaScript:void(0);" class="button button-secondary sbspf_dismiss_at_warning_button" data-action="sby_dismiss_at_warning_notice"><?php esc_html_e( 'Dismiss', $text_domain); ?></a>
9
+ </p>
10
+ <a href="JavaScript:void(0);" class="sbspf_modal_close sbspf_dismiss_at_warning_button" data-action="sby_dismiss_at_warning_notice"><i class="fa fa-times"></i></a>
11
+
12
+ </div>
13
+ </div>
14
+
15
+ </div>
16
  </div>
inc/admin/templates/single-connected-account.php CHANGED
@@ -1,61 +1,61 @@
1
- <?php
2
- $just_updated = isset( $_GET['sby_access_token'] ) && $account['access_token'] === $_GET['sby_access_token'];
3
- $just_updated_class = $just_updated ? ' sbspf_just_updated' : '';
4
- ?>
5
-
6
- <div class="sbspf_connected_account<?php echo $just_updated_class; ?>" id="sbspf_connected_account_<?php esc_attr_e( $account['channel_id'] ); ?>" data-accesstoken="<?php esc_attr_e( $account['access_token'] ); ?>" data-userid="<?php esc_attr_e( $account['channel_id'] ); ?>" data-username="<?php esc_attr_e( $account['username'] ); ?>">
7
-
8
- <div class="sbspf_ca_alert">
9
- <span><?php _e( 'The Access Token for this account is expired or invalid. Click the button above to attempt to renew it.', $text_domain ) ?></span>
10
- </div>
11
- <?php if ( $just_updated ) : ?>
12
- <div class="sbspf_ca_alert sbspf_ca_updated">
13
- <span><?php _e( 'Successfully Connected', $text_domain ) ?></span>
14
- </div>
15
- <?php endif; ?>
16
- <div class="sbspf_ca_info">
17
-
18
- <div class="sbspf_ca_delete">
19
- <a href="JavaScript:void(0);" class="sbspf_delete_account"><?php echo sby_admin_icon( 'times', 'sbspf_small_svg' ) ; ?><span class="sbspf_remove_text"><?php _e( 'Remove', $text_domain ); ?></span></a>
20
- </div>
21
-
22
- <div class="sbspf_ca_username">
23
- <?php echo $profile_picture; ?>
24
- <?php if ( ! empty( $account['channel_id'] ) ) : ?>
25
- <strong><?php echo $username; ?><span><?php _e('Channel ID:', $text_domain ); ?><?php echo ' ' . $account['channel_id']; ?></span></strong>
26
- <?php else: ?>
27
- <strong><?php echo $username; ?><span><?php echo sprintf( __( '%sHow to create a channel%s', $text_domain ), '<a href="https://support.google.com/youtube/answer/1646861?hl=en" target="_blank" rel="noopener noreferrer">', '</a>' ); ?></span></strong>
28
- <?php endif; ?>
29
- </div>
30
-
31
- <div class="sbspf_ca_actions">
32
- <?php if ( ! empty( $account['channel_id'] ) ) : ?>
33
- <a class="sbspf_ca_token_shortcode button-secondary" href="JavaScript:void(0);"><?php echo sby_admin_icon( 'chevron-right', 'sbspf_small_svg' ) ; ?><?php _e( 'Add to another Feed', $text_domain ); ?></a>
34
- <?php endif; ?>
35
- <a class="sbspf_ca_show_token button-secondary" href="JavaScript:void(0);" title="<?php _e('Show access token and account info', $text_domain ); ?>"><?php echo sby_admin_icon( 'ellipsis', 'sbspf_small_svg' ) ; ?></a>
36
- </div>
37
-
38
- <div class="sbspf_ca_shortcode">
39
-
40
- <p><?php _e('Copy and paste this shortcode into your page or widget area', $text_domain ); ?>:<br>
41
- <?php if ( !empty( $account['username'] ) ) : ?>
42
- <code>[<?php echo $slug; ?> channel="<?php echo $account['channel_id']; ?>"]</code>
43
- <?php else : ?>
44
- <code>[<?php echo $slug; ?> accesstoken="<?php echo $account['access_token']; ?>"]</code>
45
- <?php endif; ?>
46
- </p>
47
-
48
- <p><?php _e('To add multiple channels in the same feed, simply separate them using commas', $text_domain); ?>:<br>
49
- <code>[<?php echo $slug; ?> channel="<?php echo $account['channel_id']; ?>, a_second_channel, a_third_channel"]</code>
50
-
51
- <p><?php echo sprintf( __('Click on the %s tab to learn more about shortcodes', $text_domain), '<a href="admin.php?page='. esc_attr( $slug ). '&tab=display" target="_blank">'. __( 'Display Your Feed', $text_domain ) . '</a>' ); ?></p>
52
- </div>
53
-
54
- <div class="sbspf_ca_accesstoken">
55
- <span class="sbspf_ca_token_label"><?php _e('Access Token', $text_domain);?>:</span><input type="text" class="sbspf_ca_token" value="<?php echo $account['access_token']; ?>" readonly="readonly" onclick="this.focus();this.select()" title="<?php _e('To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain);?>"><br>
56
- <span class="sbspf_ca_token_label"><?php _e('Channel ID', $text_domain);?>:</span><input type="text" class="sbspf_ca_user_id" value="<?php echo $account['channel_id']; ?>" readonly="readonly" onclick="this.focus();this.select()" title="<?php _e('To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain);?>"><br>
57
- </div>
58
-
59
- </div>
60
-
61
  </div>
1
+ <?php
2
+ $just_updated = isset( $_GET['sby_access_token'] ) && $account['access_token'] === $_GET['sby_access_token'];
3
+ $just_updated_class = $just_updated ? ' sbspf_just_updated' : '';
4
+ ?>
5
+
6
+ <div class="sbspf_connected_account<?php echo $just_updated_class; ?>" id="sbspf_connected_account_<?php esc_attr_e( $account['channel_id'] ); ?>" data-accesstoken="<?php esc_attr_e( $account['access_token'] ); ?>" data-userid="<?php esc_attr_e( $account['channel_id'] ); ?>" data-username="<?php esc_attr_e( $account['username'] ); ?>">
7
+
8
+ <div class="sbspf_ca_alert">
9
+ <span><?php _e( 'The Access Token for this account is expired or invalid. Click the button above to attempt to renew it.', $text_domain ) ?></span>
10
+ </div>
11
+ <?php if ( $just_updated ) : ?>
12
+ <div class="sbspf_ca_alert sbspf_ca_updated">
13
+ <span><?php _e( 'Successfully Connected', $text_domain ) ?></span>
14
+ </div>
15
+ <?php endif; ?>
16
+ <div class="sbspf_ca_info">
17
+
18
+ <div class="sbspf_ca_delete">
19
+ <a href="JavaScript:void(0);" class="sbspf_delete_account"><?php echo sby_admin_icon( 'times', 'sbspf_small_svg' ) ; ?><span class="sbspf_remove_text"><?php _e( 'Remove', $text_domain ); ?></span></a>
20
+ </div>
21
+
22
+ <div class="sbspf_ca_username">
23
+ <?php echo $profile_picture; ?>
24
+ <?php if ( ! empty( $account['channel_id'] ) ) : ?>
25
+ <strong><?php echo $username; ?><span><?php _e('Channel ID:', $text_domain ); ?><?php echo ' ' . $account['channel_id']; ?></span></strong>
26
+ <?php else: ?>
27
+ <strong><?php echo $username; ?><span><?php echo sprintf( __( '%sHow to create a channel%s', $text_domain ), '<a href="https://support.google.com/youtube/answer/1646861?hl=en" target="_blank" rel="noopener noreferrer">', '</a>' ); ?></span></strong>
28
+ <?php endif; ?>
29
+ </div>
30
+
31
+ <div class="sbspf_ca_actions">
32
+ <?php if ( ! empty( $account['channel_id'] ) ) : ?>
33
+ <a class="sbspf_ca_token_shortcode button-secondary" href="JavaScript:void(0);"><?php echo sby_admin_icon( 'chevron-right', 'sbspf_small_svg' ) ; ?><?php _e( 'Add to another Feed', $text_domain ); ?></a>
34
+ <?php endif; ?>
35
+ <a class="sbspf_ca_show_token button-secondary" href="JavaScript:void(0);" title="<?php _e('Show access token and account info', $text_domain ); ?>"><?php echo sby_admin_icon( 'ellipsis', 'sbspf_small_svg' ) ; ?></a>
36
+ </div>
37
+
38
+ <div class="sbspf_ca_shortcode">
39
+
40
+ <p><?php _e('Copy and paste this shortcode into your page or widget area', $text_domain ); ?>:<br>
41
+ <?php if ( !empty( $account['username'] ) ) : ?>
42
+ <code>[<?php echo $slug; ?> channel="<?php echo $account['channel_id']; ?>"]</code>
43
+ <?php else : ?>
44
+ <code>[<?php echo $slug; ?> accesstoken="<?php echo $account['access_token']; ?>"]</code>
45
+ <?php endif; ?>
46
+ </p>
47
+
48
+ <p><?php _e('To add multiple channels in the same feed, simply separate them using commas', $text_domain); ?>:<br>
49
+ <code>[<?php echo $slug; ?> channel="<?php echo $account['channel_id']; ?>, a_second_channel, a_third_channel"]</code>
50
+
51
+ <p><?php echo sprintf( __('Click on the %s tab to learn more about shortcodes', $text_domain), '<a href="admin.php?page='. esc_attr( $slug ). '&tab=display" target="_blank">'. __( 'Display Your Feed', $text_domain ) . '</a>' ); ?></p>
52
+ </div>
53
+
54
+ <div class="sbspf_ca_accesstoken">
55
+ <span class="sbspf_ca_token_label"><?php _e('Access Token', $text_domain);?>:</span><input type="text" class="sbspf_ca_token" value="<?php echo $account['access_token']; ?>" readonly="readonly" onclick="this.focus();this.select()" title="<?php _e('To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain);?>"><br>
56
+ <span class="sbspf_ca_token_label"><?php _e('Channel ID', $text_domain);?>:</span><input type="text" class="sbspf_ca_user_id" value="<?php echo $account['channel_id']; ?>" readonly="readonly" onclick="this.focus();this.select()" title="<?php _e('To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac).', $text_domain);?>"><br>
57
+ </div>
58
+
59
+ </div>
60
+
61
  </div>
inc/admin/templates/support.php CHANGED
@@ -1,149 +1,149 @@
1
- <h3><?php _e( 'Need help?', $text_domain ); ?></h3>
2
-
3
- <p><?php echo sby_admin_icon( 'life-ring', 'sbspf_small_svg' ); ?>&nbsp; <?php _e( 'Check out our ', $text_domain ); ?><a href="<?php echo esc_url( $setup_url ); ?>" target="_blank"><?php _e( 'setup directions', $text_domain ); ?></a> <?php _e( 'for a step-by-step guide on how to setup and use the plugin', $text_domain ); ?>.</p>
4
-
5
- <p><?php echo sby_admin_icon( 'envelope', 'sbspf_small_svg' ); ?>&nbsp; <?php _e( 'Have a problem? Submit a ', $text_domain ); ?><a href="<?php echo esc_url( SBY_SUPPORT_URL ); ?>" target="_blank"><?php _e( 'support ticket', $text_domain ); ?></a> <?php _e( 'on our website', $text_domain ); ?>. <?php _e( 'Please include your <b>System Info</b> below with all support requests.', $text_domain ); ?></p>
6
-
7
- <br />
8
- <h3><?php _e('System Info', $text_domain ); ?> &nbsp; <span style="color: #666; font-size: 11px; font-weight: normal;"><?php _e( 'Click the text below to select all', $text_domain ); ?></span></h3>
9
-
10
- <textarea readonly="readonly" onclick="this.focus();this.select()" title="To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac)." style="width: 70%; height: 500px; white-space: pre; font-family: Menlo,Monaco,monospace;">
11
- ## SITE/SERVER INFO: ##
12
- Plugin Version: <?php echo $plugin_name . ' v' . $plugin_version. "\n"; ?>
13
- Site URL: <?php echo site_url() . "\n"; ?>
14
- Home URL: <?php echo home_url() . "\n"; ?>
15
- WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
16
- PHP Version: <?php echo PHP_VERSION . "\n"; ?>
17
- Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
18
- PHP allow_url_fopen: <?php echo ini_get( 'allow_url_fopen' ) ? "Yes" . "\n" : "No" . "\n"; ?>
19
- PHP cURL: <?php echo is_callable('curl_init') ? "Yes" . "\n" : "No" . "\n"; ?>
20
- JSON: <?php echo function_exists("json_decode") ? "Yes" . "\n" : "No" . "\n" ?>
21
- SSL Stream: <?php echo in_array('https', stream_get_wrappers()) ? "Yes" . "\n" : "No" . "\n" //extension=php_openssl.dll in php.ini ?>
22
-
23
- ## ACTIVE PLUGINS: ##
24
- <?php
25
- $plugins = get_plugins();
26
- $active_plugins = get_option( 'active_plugins', array() );
27
-
28
- foreach ( $plugins as $plugin_path => $plugin ) {
29
- // If the plugin isn't active, don't show it.
30
- if ( in_array( $plugin_path, $active_plugins ) ) {
31
- echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
32
- }
33
- }
34
- ?>
35
-
36
- ## OPTIONS: ##
37
- <?php
38
- $options = get_option( $this->get_option_name(), array() );
39
- foreach ( $options as $key => $val ) {
40
- if ( $key !== 'connected_accounts' ) {
41
- if ( is_array( $val ) ) {
42
- foreach ( $val as $key2 => $val2 ) {
43
- if ( is_array( $val2 ) ) {
44
- foreach ( $val2 as $key3 => $val3 ) {
45
- $label = $key . ':';
46
- $value = isset( $val3 ) ? esc_attr( $val3 ) : 'unset';
47
- echo str_pad( $label, 24 ) . $value ."\n";
48
- }
49
- } else {
50
- $label = $key . ':';
51
- $value = isset( $val2 ) ? esc_attr( $val2 ) : 'unset';
52
- echo str_pad( $label, 24 ) . $value ."\n";
53
- }
54
- }
55
- } else {
56
- $label = $key . ':';
57
- $value = isset( $val ) ? esc_attr( $val ) : 'unset';
58
- echo str_pad( $label, 24 ) . $value ."\n";
59
- }
60
- }
61
- }
62
- ?>
63
-
64
- ## Connected Accounts: ##
65
- <?php
66
- foreach ( $options['connected_accounts'] as $account ) {
67
- foreach ( $account as $key2 => $val2 ) {
68
- if ( is_array( $val2 ) ) {
69
- foreach ( $val2 as $key3 => $val3 ) {
70
- $label = $key3 . ':';
71
- $value = isset( $val3 ) ? esc_attr( $val3 ) : 'unset';
72
- echo str_pad( $label, 24 ) . $value ."\n";
73
- }
74
- } else {
75
- $label = $key2 . ':';
76
- $value = isset( $val2 ) ? esc_attr( $val2 ) : 'unset';
77
- echo str_pad( $label, 24 ) . $value ."\n";
78
- }
79
- }
80
- }
81
- ?>
82
-
83
- ## Cron Events: ##
84
- <?php
85
- $cron = _get_cron_array();
86
- foreach ( $cron as $key => $data ) {
87
- $is_target = false;
88
- foreach ( $data as $key2 => $val ) {
89
- if ( strpos( $key2, 'sby' ) !== false ) {
90
- $is_target = true;
91
- echo $key2;
92
- echo "\n";
93
- }
94
- }
95
- if ( $is_target) {
96
- echo date( "Y-m-d H:i:s", $key );
97
- echo "\n";
98
- echo 'Next Scheduled: ' . ((int)$key - time())/60 . ' minutes';
99
- echo "\n\n";
100
- }
101
- }
102
- ?>
103
- ## Cron Cache Report: ##
104
- <?php $cron_report = get_option( 'sby_cron_report', array() );
105
- if ( ! empty( $cron_report ) ) {
106
- var_export( $cron_report );
107
- }
108
- echo "\n";
109
- ?>
110
-
111
- ## Location Summary: ##
112
- <?php
113
- $locator_summary = SBY_Feed_Locator::summary();
114
- $condensed_shortcode_atts = array( 'type', 'channel', 'id', 'live', 'search', 'playlist', 'layout', 'whitelist', 'includewords' );
115
-
116
- if ( ! empty( $locator_summary) ) {
117
-
118
- foreach ( $locator_summary as $locator_section ) {
119
- if ( ! empty( $locator_section['results'] ) ) {
120
- $first_five = array_slice( $locator_section['results'], 0, 5 );
121
- foreach ( $first_five as $result ) {
122
- $condensed_shortcode_string = '[youtube-feeds';
123
- $shortcode_atts = json_decode( $result['shortcode_atts'], true );
124
- $shortcode_atts = is_array( $shortcode_atts ) ? $shortcode_atts : array();
125
- foreach ( $shortcode_atts as $key => $value ) {
126
- if ( in_array( $key, $condensed_shortcode_atts, true ) ) {
127
- $condensed_shortcode_string .= ' ' . esc_html( $key ). '="' . esc_html( $value ) . '"';
128
- }
129
- }
130
- $condensed_shortcode_string .= ']';
131
- echo esc_url( get_the_permalink( $result['post_id'] ) ) . ' ' . $condensed_shortcode_string . "\n";
132
- }
133
-
134
- }
135
- }
136
- }?>
137
-
138
- ## Error Log: ##
139
- <?php
140
- global $sby_posts_manager;
141
- $errors = $sby_posts_manager->get_errors();
142
- if ( ! empty( $errors ) ) :
143
- foreach ( $errors as $type => $error ) :
144
- echo $type . ': ' . str_replace( array( '<p>', '<b>', '</p>', '</b>' ), ' ', $error[1] ) . "\n";
145
- endforeach;
146
- endif;
147
- ?>
148
-
149
  </textarea>
1
+ <h3><?php _e( 'Need help?', $text_domain ); ?></h3>
2
+
3
+ <p><?php echo sby_admin_icon( 'life-ring', 'sbspf_small_svg' ); ?>&nbsp; <?php _e( 'Check out our ', $text_domain ); ?><a href="<?php echo esc_url( $setup_url ); ?>" target="_blank"><?php _e( 'setup directions', $text_domain ); ?></a> <?php _e( 'for a step-by-step guide on how to setup and use the plugin', $text_domain ); ?>.</p>
4
+
5
+ <p><?php echo sby_admin_icon( 'envelope', 'sbspf_small_svg' ); ?>&nbsp; <?php _e( 'Have a problem? Submit a ', $text_domain ); ?><a href="<?php echo esc_url( SBY_SUPPORT_URL ); ?>" target="_blank"><?php _e( 'support ticket', $text_domain ); ?></a> <?php _e( 'on our website', $text_domain ); ?>. <?php _e( 'Please include your <b>System Info</b> below with all support requests.', $text_domain ); ?></p>
6
+
7
+ <br />
8
+ <h3><?php _e('System Info', $text_domain ); ?> &nbsp; <span style="color: #666; font-size: 11px; font-weight: normal;"><?php _e( 'Click the text below to select all', $text_domain ); ?></span></h3>
9
+
10
+ <textarea readonly="readonly" onclick="this.focus();this.select()" title="To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac)." style="width: 70%; height: 500px; white-space: pre; font-family: Menlo,Monaco,monospace;">
11
+ ## SITE/SERVER INFO: ##
12
+ Plugin Version: <?php echo $plugin_name . ' v' . $plugin_version. "\n"; ?>
13
+ Site URL: <?php echo site_url() . "\n"; ?>
14
+ Home URL: <?php echo home_url() . "\n"; ?>
15
+ WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
16
+ PHP Version: <?php echo PHP_VERSION . "\n"; ?>
17
+ Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
18
+ PHP allow_url_fopen: <?php echo ini_get( 'allow_url_fopen' ) ? "Yes" . "\n" : "No" . "\n"; ?>
19
+ PHP cURL: <?php echo is_callable('curl_init') ? "Yes" . "\n" : "No" . "\n"; ?>
20
+ JSON: <?php echo function_exists("json_decode") ? "Yes" . "\n" : "No" . "\n" ?>
21
+ SSL Stream: <?php echo in_array('https', stream_get_wrappers()) ? "Yes" . "\n" : "No" . "\n" //extension=php_openssl.dll in php.ini ?>
22
+
23
+ ## ACTIVE PLUGINS: ##
24
+ <?php
25
+ $plugins = get_plugins();
26
+ $active_plugins = get_option( 'active_plugins', array() );
27
+
28
+ foreach ( $plugins as $plugin_path => $plugin ) {
29
+ // If the plugin isn't active, don't show it.
30
+ if ( in_array( $plugin_path, $active_plugins ) ) {
31
+ echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
32
+ }
33
+ }
34
+ ?>
35
+
36
+ ## OPTIONS: ##
37
+ <?php
38
+ $options = get_option( $this->get_option_name(), array() );
39
+ foreach ( $options as $key => $val ) {
40
+ if ( $key !== 'connected_accounts' ) {
41
+ if ( is_array( $val ) ) {
42
+ foreach ( $val as $key2 => $val2 ) {
43
+ if ( is_array( $val2 ) ) {
44
+ foreach ( $val2 as $key3 => $val3 ) {
45
+ $label = $key . ':';
46
+ $value = isset( $val3 ) ? esc_attr( $val3 ) : 'unset';
47
+ echo str_pad( $label, 24 ) . $value ."\n";
48
+ }
49
+ } else {
50
+ $label = $key . ':';
51
+ $value = isset( $val2 ) ? esc_attr( $val2 ) : 'unset';
52
+ echo str_pad( $label, 24 ) . $value ."\n";
53
+ }
54
+ }
55
+ } else {
56
+ $label = $key . ':';
57
+ $value = isset( $val ) ? esc_attr( $val ) : 'unset';
58
+ echo str_pad( $label, 24 ) . $value ."\n";
59
+ }
60
+ }
61
+ }
62
+ ?>
63
+
64
+ ## Connected Accounts: ##
65
+ <?php
66
+ foreach ( $options['connected_accounts'] as $account ) {
67
+ foreach ( $account as $key2 => $val2 ) {
68
+ if ( is_array( $val2 ) ) {
69
+ foreach ( $val2 as $key3 => $val3 ) {
70
+ $label = $key3 . ':';
71
+ $value = isset( $val3 ) ? esc_attr( $val3 ) : 'unset';
72
+ echo str_pad( $label, 24 ) . $value ."\n";
73
+ }
74
+ } else {
75
+ $label = $key2 . ':';
76
+ $value = isset( $val2 ) ? esc_attr( $val2 ) : 'unset';
77
+ echo str_pad( $label, 24 ) . $value ."\n";
78
+ }
79
+ }
80
+ }
81
+ ?>
82
+
83
+ ## Cron Events: ##
84
+ <?php
85
+ $cron = _get_cron_array();
86
+ foreach ( $cron as $key => $data ) {
87
+ $is_target = false;
88
+ foreach ( $data as $key2 => $val ) {
89
+ if ( strpos( $key2, 'sby' ) !== false ) {
90
+ $is_target = true;
91
+ echo $key2;
92
+ echo "\n";
93
+ }
94
+ }
95
+ if ( $is_target) {
96
+ echo date( "Y-m-d H:i:s", $key );
97
+ echo "\n";
98
+ echo 'Next Scheduled: ' . ((int)$key - time())/60 . ' minutes';
99
+ echo "\n\n";
100
+ }
101
+ }
102
+ ?>
103
+ ## Cron Cache Report: ##
104
+ <?php $cron_report = get_option( 'sby_cron_report', array() );
105
+ if ( ! empty( $cron_report ) ) {
106
+ var_export( $cron_report );
107
+ }
108
+ echo "\n";
109
+ ?>
110
+
111
+ ## Location Summary: ##
112
+ <?php
113
+ $locator_summary = SBY_Feed_Locator::summary();
114
+ $condensed_shortcode_atts = array( 'type', 'channel', 'id', 'live', 'search', 'playlist', 'layout', 'whitelist', 'includewords' );
115
+
116
+ if ( ! empty( $locator_summary) ) {
117
+
118
+ foreach ( $locator_summary as $locator_section ) {
119
+ if ( ! empty( $locator_section['results'] ) ) {
120
+ $first_five = array_slice( $locator_section['results'], 0, 5 );
121
+ foreach ( $first_five as $result ) {
122
+ $condensed_shortcode_string = '[youtube-feeds';
123
+ $shortcode_atts = json_decode( $result['shortcode_atts'], true );
124
+ $shortcode_atts = is_array( $shortcode_atts ) ? $shortcode_atts : array();
125
+ foreach ( $shortcode_atts as $key => $value ) {
126
+ if ( in_array( $key, $condensed_shortcode_atts, true ) ) {
127
+ $condensed_shortcode_string .= ' ' . esc_html( $key ). '="' . esc_html( $value ) . '"';
128
+ }
129
+ }
130
+ $condensed_shortcode_string .= ']';
131
+ echo esc_url( get_the_permalink( $result['post_id'] ) ) . ' ' . $condensed_shortcode_string . "\n";
132
+ }
133
+
134
+ }
135
+ }
136
+ }?>
137
+
138
+ ## Error Log: ##
139
+ <?php
140
+ global $sby_posts_manager;
141
+ $errors = $sby_posts_manager->get_errors();
142
+ if ( ! empty( $errors ) ) :
143
+ foreach ( $errors as $type => $error ) :
144
+ echo $type . ': ' . str_replace( array( '<p>', '<b>', '</p>', '</b>' ), ' ', $error[1] ) . "\n";
145
+ endforeach;
146
+ endif;
147
+ ?>
148
+
149
  </textarea>
inc/blocks/class-sby-blocks.php CHANGED
@@ -1,149 +1,149 @@
1
- <?php
2
- /**
3
- * Instagram Feed block with live preview.
4
- *
5
- * @since 1.7.1
6
- */
7
- class SBY_Blocks {
8
-
9
- /**
10
- * Indicates if current integration is allowed to load.
11
- *
12
- * @since 1.8
13
- *
14
- * @return bool
15
- */
16
- public function allow_load() {
17
- return function_exists( 'register_block_type' );
18
- }
19
-
20
- /**
21
- * Loads an integration.
22
- *
23
- * @since 1.7.1
24
- */
25
- public function load() {
26
- $this->hooks();
27
- }
28
-
29
- /**
30
- * Integration hooks.
31
- *
32
- * @since 1.7.1
33
- */
34
- protected function hooks() {
35
- add_action( 'init', array( $this, 'register_block' ) );
36
- add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
37
- }
38
-
39
- /**
40
- * Register Instagram Feed Gutenberg block on the backend.
41
- *
42
- * @since 1.7.1
43
- */
44
- public function register_block() {
45
-
46
- wp_register_style(
47
- 'sby-blocks-styles',
48
- trailingslashit( SBY_PLUGIN_URL ) . 'css/sby-blocks.css',
49
- array( 'wp-edit-blocks' ),
50
- SBYVER
51
- );
52
-
53
- $attributes = array(
54
- 'shortcodeSettings' => array(
55
- 'type' => 'string',
56
- ),
57
- 'noNewChanges' => array(
58
- 'type' => 'boolean',
59
- ),
60
- 'executed' => array(
61
- 'type' => 'boolean',
62
- )
63
- );
64
-
65
- register_block_type(
66
- 'sby/sby-feed-block',
67
- array(
68
- 'attributes' => $attributes,
69
- 'render_callback' => array( $this, 'get_feed_html' ),
70
- )
71
- );
72
- }
73
-
74
- /**
75
- * Load Instagram Feed Gutenberg block scripts.
76
- *
77
- * @since 1.7.1
78
- */
79
- public function enqueue_block_editor_assets() {
80
- sby_scripts_enqueue( true );
81
-
82
- wp_enqueue_style( 'sby-blocks-styles' );
83
- wp_enqueue_script(
84
- 'sby-feed-block',
85
- trailingslashit( SBY_PLUGIN_URL ) . 'js/sby-blocks.js',
86
- array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
87
- SBYVER,
88
- true
89
- );
90
-
91
- $shortcodeSettings = '';
92
-
93
- $i18n = array(
94
- 'addSettings' => esc_html__( 'Add Settings', SBY_TEXT_DOMAIN ),
95
- 'shortcodeSettings' => esc_html__( 'Shortcode Settings', SBY_TEXT_DOMAIN ),
96
- 'example' => esc_html__( 'Example', SBY_TEXT_DOMAIN ),
97
- 'preview' => esc_html__( 'Apply Changes', SBY_TEXT_DOMAIN ),
98
-
99
- );
100
-
101
- wp_localize_script(
102
- 'sby-feed-block',
103
- 'sby_block_editor',
104
- array(
105
- 'wpnonce' => wp_create_nonce( 'sby-blocks' ),
106
- 'canShowFeed' => true,
107
- 'shortcodeSettings' => $shortcodeSettings,
108
- 'i18n' => $i18n,
109
- )
110
- );
111
- }
112
-
113
- /**
114
- * Get form HTML to display in a Instagram Feed Gutenberg block.
115
- *
116
- * @param array $attr Attributes passed by Instagram Feed Gutenberg block.
117
- *
118
- * @since 1.7.1
119
- *
120
- * @return string
121
- */
122
- public function get_feed_html( $attr ) {
123
-
124
- $return = '';
125
-
126
- $shortcode_settings = isset( $attr['shortcodeSettings'] ) ? $attr['shortcodeSettings'] : '';
127
-
128
- $shortcode_settings = str_replace(array( '[youtube-feed', ']' ), '', $shortcode_settings );
129
-
130
- $return .= do_shortcode( '[youtube-feed '.$shortcode_settings.']' );
131
-
132
- return $return;
133
-
134
- }
135
-
136
- /**
137
- * Checking if is Gutenberg REST API call.
138
- *
139
- * @since 1.7.1
140
- *
141
- * @return bool True if is Gutenberg REST API call.
142
- */
143
- public static function is_gb_editor() {
144
-
145
- // TODO: Find a better way to check if is GB editor API call.
146
- return defined( 'REST_REQUEST' ) && REST_REQUEST && ! empty( $_REQUEST['context'] ) && 'edit' === $_REQUEST['context']; // phpcs:ignore
147
- }
148
-
149
- }
1
+ <?php
2
+ /**
3
+ * Instagram Feed block with live preview.
4
+ *
5
+ * @since 1.7.1
6
+ */
7
+ class SBY_Blocks {
8
+
9
+ /**
10
+ * Indicates if current integration is allowed to load.
11
+ *
12
+ * @since 1.8
13
+ *
14
+ * @return bool
15
+ */
16
+ public function allow_load() {
17
+ return function_exists( 'register_block_type' );
18
+ }
19
+
20
+ /**
21
+ * Loads an integration.
22
+ *
23
+ * @since 1.7.1
24
+ */
25
+ public function load() {
26
+ $this->hooks();
27
+ }
28
+
29
+ /**
30
+ * Integration hooks.
31
+ *
32
+ * @since 1.7.1
33
+ */
34
+ protected function hooks() {
35
+ add_action( 'init', array( $this, 'register_block' ) );
36
+ add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
37
+ }
38
+
39
+ /**
40
+ * Register Instagram Feed Gutenberg block on the backend.
41
+ *
42
+ * @since 1.7.1
43
+ */
44
+ public function register_block() {
45
+
46
+ wp_register_style(
47
+ 'sby-blocks-styles',
48
+ trailingslashit( SBY_PLUGIN_URL ) . 'css/sby-blocks.css',
49
+ array( 'wp-edit-blocks' ),
50
+ SBYVER
51
+ );
52
+
53
+ $attributes = array(
54
+ 'shortcodeSettings' => array(
55
+ 'type' => 'string',
56
+ ),
57
+ 'noNewChanges' => array(
58
+ 'type' => 'boolean',
59
+ ),
60
+ 'executed' => array(
61
+ 'type' => 'boolean',
62
+ )
63
+ );
64
+
65
+ register_block_type(
66
+ 'sby/sby-feed-block',
67
+ array(
68
+ 'attributes' => $attributes,
69
+ 'render_callback' => array( $this, 'get_feed_html' ),
70
+ )
71
+ );
72
+ }
73
+
74
+ /**
75
+ * Load Instagram Feed Gutenberg block scripts.
76
+ *
77
+ * @since 1.7.1
78
+ */
79
+ public function enqueue_block_editor_assets() {
80
+ sby_scripts_enqueue( true );
81
+
82
+ wp_enqueue_style( 'sby-blocks-styles' );
83
+ wp_enqueue_script(
84
+ 'sby-feed-block',
85
+ trailingslashit( SBY_PLUGIN_URL ) . 'js/sby-blocks.js',
86
+ array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
87
+ SBYVER,
88
+ true
89
+ );
90
+
91
+ $shortcodeSettings = '';
92
+
93
+ $i18n = array(
94
+ 'addSettings' => esc_html__( 'Add Settings', SBY_TEXT_DOMAIN ),
95
+ 'shortcodeSettings' => esc_html__( 'Shortcode Settings', SBY_TEXT_DOMAIN ),
96
+ 'example' => esc_html__( 'Example', SBY_TEXT_DOMAIN ),
97
+ 'preview' => esc_html__( 'Apply Changes', SBY_TEXT_DOMAIN ),
98
+
99
+ );
100
+
101
+ wp_localize_script(
102
+ 'sby-feed-block',
103
+ 'sby_block_editor',
104
+ array(
105
+ 'wpnonce' => wp_create_nonce( 'sby-blocks' ),
106
+ 'canShowFeed' => true,
107
+ 'shortcodeSettings' => $shortcodeSettings,
108
+ 'i18n' => $i18n,
109
+ )
110
+ );
111
+ }
112
+
113
+ /**
114
+ * Get form HTML to display in a Instagram Feed Gutenberg block.
115
+ *
116
+ * @param array $attr Attributes passed by Instagram Feed Gutenberg block.
117
+ *
118
+ * @since 1.7.1
119
+ *
120
+ * @return string
121
+ */
122
+ public function get_feed_html( $attr ) {
123
+
124
+ $return = '';
125
+
126
+ $shortcode_settings = isset( $attr['shortcodeSettings'] ) ? $attr['shortcodeSettings'] : '';
127
+
128
+ $shortcode_settings = str_replace(array( '[youtube-feed', ']' ), '', $shortcode_settings );
129
+
130
+ $return .= do_shortcode( '[youtube-feed '.$shortcode_settings.']' );
131
+
132
+ return $return;
133
+
134
+ }
135
+
136
+ /**
137
+ * Checking if is Gutenberg REST API call.
138
+ *
139
+ * @since 1.7.1
140
+ *
141
+ * @return bool True if is Gutenberg REST API call.
142
+ */
143
+ public static function is_gb_editor() {
144
+
145
+ // TODO: Find a better way to check if is GB editor API call.
146
+ return defined( 'REST_REQUEST' ) && REST_REQUEST && ! empty( $_REQUEST['context'] ) && 'edit' === $_REQUEST['context']; // phpcs:ignore
147
+ }
148
+
149
+ }
inc/class-sby-api-connect.php CHANGED
@@ -1,195 +1,195 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SBY_API_Connect
7
- {
8
- /**
9
- * @var string
10
- */
11
- private $url;
12
-
13
- /**
14
- * @var object
15
- */
16
- protected $response;
17
-
18
- public function __construct( $connected_account_or_url, $endpoint = '', $params = array() ) {
19
- if ( is_array( $connected_account_or_url ) && isset( $connected_account_or_url['access_token'] ) ) {
20
- $this->set_url( $connected_account_or_url, $endpoint, $params );
21
- } elseif ( is_array( $connected_account_or_url ) ) {
22
- $this->set_url( $connected_account_or_url, $endpoint, $params );
23
- } elseif ( strpos( $connected_account_or_url, 'https' ) !== false ) {
24
- $this->url = $connected_account_or_url;
25
- } else {
26
- $this->url = '';
27
- }
28
- }
29
-
30
- public function get_data() {
31
- if (!is_wp_error($this->response) && !empty($this->response['data'])) {
32
- return $this->response['data'];
33
- } else {
34
- return $this->response;
35
- }
36
- }
37
-
38
- public function get_wp_error() {
39
- if ( $this->is_wp_error() ) {
40
- return array( 'response' => $this->response, 'url' => $this->url );
41
- } else {
42
- return false;
43
- }
44
- }
45
-
46
- public function get_next_page( $params = false ) {
47
- if ( ! empty( $this->response['nextPageToken'] ) ) {
48
- return $this->response['nextPageToken'];
49
- } else {
50
- return '';
51
- }
52
- }
53
-
54
- public function set_url_from_args( $url ) {
55
- $this->url = $url;
56
- }
57
-
58
- public function get_url() {
59
- return $this->url;
60
- }
61
-
62
- public function is_wp_error() {
63
- return is_wp_error( $this->response );
64
- }
65
-
66
-
67
- public function is_youtube_error() {
68
- return (is_wp_error( $this->response ) || isset( $this->response['error'] ));
69
- }
70
-
71
- public function connect() {
72
- $args = array(
73
- 'timeout' => 60,
74
- 'sslverify' => false
75
- );
76
- $response = wp_remote_get( esc_url_raw( $this->url ), $args );
77
-
78
- if ( ! is_wp_error( $response ) ) {
79
- // certain ways of representing the html for double quotes causes errors so replaced here.
80
- $response = json_decode( str_replace( '%22', '&rdquo;', $response['body'] ), true );
81
- }
82
-
83
- $this->response = $response;
84
- }
85
-
86
- public static function handle_youtube_error( $response, $error_connected_account, $request_type = '' ) {
87
- //
88
- if ( isset( $response['error'] ) ) {
89
- if ( isset( $response['error']['errors'][0]['reason'] ) && $response['error']['errors'][0]['message'] === 'Invalid Credentials' ) {
90
- $error_message = '<p><b>' . __( 'Reconnect to YouTube to show this feed.', 'custom-facebook-feed' ) . '</b></p>';
91
- $error_message .= '<p>' . __( 'To create a new feed, first connect to YouTube using the "Connect to YouTube to Create a Feed" button on the settings page and connect any account.', SBY_TEXT_DOMAIN ) . '</p>';
92
-
93
- if ( current_user_can( 'manage_youtube_feed_options' ) ) {
94
- $error_message .= '<a href="' . admin_url( 'admin.php?page=youtube-feed' ) . '" target="blank" rel="noopener nofollow">' . __( 'Reconnect in the YouTube Feed Settings Area' ) . '</a>';
95
- }
96
- global $sby_posts_manager;
97
-
98
- $sby_posts_manager->add_frontend_error( 'accesstoken', $error_message );
99
- $sby_posts_manager->add_error( 'accesstoken', array( 'Trying to connect a new account', $error_message ) );
100
-
101
- return false;
102
- } elseif ( isset( $response['error']['errors'][0]['reason'] ) ) {
103
- $error = $response['error']['errors'][0]['message'];
104
-
105
- $error_message = '<p><b>'. sprintf( __( 'Error %s: %s.', 'instagram-feed' ), $response['error']['code'], $error ) .'</b></p>';
106
- $error_message .= '<p>Domain code: ' . $response['error']['errors'][0]['domain'];
107
- $error_message .= '<br>Reason code: ' . $response['error']['errors'][0]['reason'];
108
- if ( current_user_can( 'manage_youtube_feed_options' ) ) {
109
- if ( isset( $response['error']['errors'][0]['extendedHelp'] ) ) {
110
- $error_message .= '<br>Extended Help Link: ' . $response['error']['errors'][0]['extendedHelp'];
111
- }
112
- $error_message .= '</p>';
113
-
114
- $error_message .= '<a href="https://smashballoon.com/youtube-feed/docs/errors/" target="blank" rel="noopener nofollow">' . __( 'Directions on how to resolve this issue' ) . '</a>';
115
- } else {
116
- $error_message .= '</p>';
117
- }
118
-
119
- global $sby_posts_manager;
120
-
121
- $sby_posts_manager->add_frontend_error( 'api', $error_message );
122
- $sby_posts_manager->add_error( 'api', array( 'Error connecting', $error_message ) );
123
-
124
- $sby_posts_manager->add_api_request_delay( 300 );
125
- }
126
- }
127
- }
128
-
129
- public static function handle_wp_remote_get_error( $response ) {
130
- $message = sprintf( __( 'Error connecting to %s.', SBY_TEXT_DOMAIN ), $response['url'] ). ' ';
131
- if ( isset( $response['response'] ) && isset( $response['response']->errors ) ) {
132
- foreach ( $response['response']->errors as $key => $item ) {
133
- $message .= ' '.$key . ' - ' . $item[0] . ' |';
134
- }
135
- }
136
-
137
- global $sby_posts_manager;
138
-
139
- $sby_posts_manager->add_api_request_delay( 300 );
140
-
141
- $sby_posts_manager->add_error( 'connection', array( 'Error connecting', $message ) );
142
- }
143
-
144
- protected function set_url( $connected_account, $endpoint_slug, $params ) {
145
- $num = ! empty( $params['num'] ) && isset( $connected_account['api_key'] ) ? (int)$params['num'] : 50;
146
-
147
- if ( $endpoint_slug === 'tokeninfo' ) {
148
- $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' . $connected_account['access_token'];
149
- } elseif ( $endpoint_slug === 'channels' ) {
150
- $channel_param = 'mine=true';
151
- if ( isset( $params['channel_name'] ) ) {
152
- $channel_param = 'forUsername=' . $params['channel_name'];
153
- } elseif ( isset( $params['channel_id'] ) ) {
154
- $channel_param = 'id=' . $params['channel_id'];
155
- }
156
-
157
- $access_credentials = isset( $connected_account['api_key'] ) ? 'key=' . $connected_account['api_key'] : 'access_token=' . $connected_account['access_token'];
158
-
159
- $url = 'https://www.googleapis.com/youtube/v3/channels?part=id,snippet,contentDetails&'.$channel_param.'&' . $access_credentials;
160
- } elseif ( $endpoint_slug === 'playlistItems' ) {
161
- $access_credentials = isset( $connected_account['api_key'] ) ? 'key=' . $connected_account['api_key'] : 'access_token=' . $connected_account['access_token'];
162
- $next_page = '';
163
- if ( isset( $params['nextPageToken'] ) ) {
164
- $next_page = '&pageToken=' . $params['nextPageToken'];
165
- }
166
-
167
- $url = 'https://www.googleapis.com/youtube/v3/playlistItems?part=id,snippet&maxResults='.$num.'&playlistId='.$params['playlist_id'].'&' . $access_credentials . $next_page;
168
- } else {
169
- $channel_param = 'mine=true';
170
- if ( isset( $params['username'] ) ) {
171
- $channel_param = 'forUsername=' . $params['username'];
172
- } elseif ( isset( $params['channel_id'] ) ) {
173
- $channel_param = 'id=' . $params['channel_id'];
174
- }
175
- $access_credentials = isset( $connected_account['api_key'] ) ? 'key=' . $connected_account['api_key'] : 'access_token=' . $connected_account['access_token'];
176
-
177
- $url = 'https://www.googleapis.com/youtube/v3/channels?part=id,snippet&'.$channel_param.'&' . $access_credentials;
178
- }
179
-
180
- $this->set_url_from_args( $url );
181
- }
182
-
183
- public static function refresh_token( $client_id, $refresh_token, $client_secret ) {
184
- $response = wp_remote_post( 'https://www.googleapis.com/oauth2/v4/token/?client_id=' . $client_id . '&client_secret=' . $client_secret . '&refresh_token='. $refresh_token . '&grant_type=refresh_token' );
185
-
186
- if ( $response['response']['code'] === 200 ) {
187
- $return = json_decode( $response['body'], true );
188
- } else {
189
- $return = array();
190
- }
191
-
192
- return $return;
193
- }
194
-
195
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SBY_API_Connect
7
+ {
8
+ /**
9
+ * @var string
10
+ */
11
+ private $url;
12
+
13
+ /**
14
+ * @var object
15
+ */
16
+ protected $response;
17
+
18
+ public function __construct( $connected_account_or_url, $endpoint = '', $params = array() ) {
19
+ if ( is_array( $connected_account_or_url ) && isset( $connected_account_or_url['access_token'] ) ) {
20
+ $this->set_url( $connected_account_or_url, $endpoint, $params );
21
+ } elseif ( is_array( $connected_account_or_url ) ) {
22
+ $this->set_url( $connected_account_or_url, $endpoint, $params );
23
+ } elseif ( strpos( $connected_account_or_url, 'https' ) !== false ) {
24
+ $this->url = $connected_account_or_url;
25
+ } else {
26
+ $this->url = '';
27
+ }
28
+ }
29
+
30
+ public function get_data() {
31
+ if (!is_wp_error($this->response) && !empty($this->response['data'])) {
32
+ return $this->response['data'];
33
+ } else {
34
+ return $this->response;
35
+ }
36
+ }
37
+
38
+ public function get_wp_error() {
39
+ if ( $this->is_wp_error() ) {
40
+ return array( 'response' => $this->response, 'url' => $this->url );
41
+ } else {
42
+ return false;
43
+ }
44
+ }
45
+
46
+ public function get_next_page( $params = false ) {
47
+ if ( ! empty( $this->response['nextPageToken'] ) ) {
48
+ return $this->response['nextPageToken'];
49
+ } else {
50
+ return '';
51
+ }
52
+ }
53
+
54
+ public function set_url_from_args( $url ) {
55
+ $this->url = $url;
56
+ }
57
+
58
+ public function get_url() {
59
+ return $this->url;
60
+ }
61
+
62
+ public function is_wp_error() {
63
+ return is_wp_error( $this->response );
64
+ }
65
+
66
+
67
+ public function is_youtube_error() {
68
+ return (is_wp_error( $this->response ) || isset( $this->response['error'] ));
69
+ }
70
+
71
+ public function connect() {
72
+ $args = array(
73
+ 'timeout' => 60,
74
+ 'sslverify' => false
75
+ );
76
+ $response = wp_remote_get( esc_url_raw( $this->url ), $args );
77
+
78
+ if ( ! is_wp_error( $response ) ) {
79
+ // certain ways of representing the html for double quotes causes errors so replaced here.
80
+ $response = json_decode( str_replace( '%22', '&rdquo;', $response['body'] ), true );
81
+ }
82
+
83
+ $this->response = $response;
84
+ }
85
+
86
+ public static function handle_youtube_error( $response, $error_connected_account, $request_type = '' ) {
87
+ //
88
+ if ( isset( $response['error'] ) ) {
89
+ if ( isset( $response['error']['errors'][0]['reason'] ) && $response['error']['errors'][0]['message'] === 'Invalid Credentials' ) {
90
+ $error_message = '<p><b>' . __( 'Reconnect to YouTube to show this feed.', 'custom-facebook-feed' ) . '</b></p>';
91
+ $error_message .= '<p>' . __( 'To create a new feed, first connect to YouTube using the "Connect to YouTube to Create a Feed" button on the settings page and connect any account.', SBY_TEXT_DOMAIN ) . '</p>';
92
+
93
+ if ( current_user_can( 'manage_youtube_feed_options' ) ) {
94
+ $error_message .= '<a href="' . admin_url( 'admin.php?page=youtube-feed' ) . '" target="blank" rel="noopener nofollow">' . __( 'Reconnect in the YouTube Feed Settings Area' ) . '</a>';
95
+ }
96
+ global $sby_posts_manager;
97
+
98
+ $sby_posts_manager->add_frontend_error( 'accesstoken', $error_message );
99
+ $sby_posts_manager->add_error( 'accesstoken', array( 'Trying to connect a new account', $error_message ) );
100
+
101
+ return false;
102
+ } elseif ( isset( $response['error']['errors'][0]['reason'] ) ) {
103
+ $error = $response['error']['errors'][0]['message'];
104
+
105
+ $error_message = '<p><b>'. sprintf( __( 'Error %s: %s.', 'instagram-feed' ), $response['error']['code'], $error ) .'</b></p>';
106
+ $error_message .= '<p>Domain code: ' . $response['error']['errors'][0]['domain'];
107
+ $error_message .= '<br>Reason code: ' . $response['error']['errors'][0]['reason'];
108
+ if ( current_user_can( 'manage_youtube_feed_options' ) ) {
109
+ if ( isset( $response['error']['errors'][0]['extendedHelp'] ) ) {
110
+ $error_message .= '<br>Extended Help Link: ' . $response['error']['errors'][0]['extendedHelp'];
111
+ }
112
+ $error_message .= '</p>';
113
+
114
+ $error_message .= '<a href="https://smashballoon.com/youtube-feed/docs/errors/" target="blank" rel="noopener nofollow">' . __( 'Directions on how to resolve this issue' ) . '</a>';
115
+ } else {
116
+ $error_message .= '</p>';
117
+ }
118
+
119
+ global $sby_posts_manager;
120
+
121
+ $sby_posts_manager->add_frontend_error( 'api', $error_message );
122
+ $sby_posts_manager->add_error( 'api', array( 'Error connecting', $error_message ) );
123
+
124
+ $sby_posts_manager->add_api_request_delay( 300 );
125
+ }
126
+ }
127
+ }
128
+
129
+ public static function handle_wp_remote_get_error( $response ) {
130
+ $message = sprintf( __( 'Error connecting to %s.', SBY_TEXT_DOMAIN ), $response['url'] ). ' ';
131
+ if ( isset( $response['response'] ) && isset( $response['response']->errors ) ) {
132
+ foreach ( $response['response']->errors as $key => $item ) {
133
+ $message .= ' '.$key . ' - ' . $item[0] . ' |';
134
+ }
135
+ }
136
+
137
+ global $sby_posts_manager;
138
+
139
+ $sby_posts_manager->add_api_request_delay( 300 );
140
+
141
+ $sby_posts_manager->add_error( 'connection', array( 'Error connecting', $message ) );
142
+ }
143
+
144
+ protected function set_url( $connected_account, $endpoint_slug, $params ) {
145
+ $num = ! empty( $params['num'] ) && isset( $connected_account['api_key'] ) ? (int)$params['num'] : 50;
146
+
147
+ if ( $endpoint_slug === 'tokeninfo' ) {
148
+ $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' . $connected_account['access_token'];
149
+ } elseif ( $endpoint_slug === 'channels' ) {
150
+ $channel_param = 'mine=true';
151
+ if ( isset( $params['channel_name'] ) ) {
152
+ $channel_param = 'forUsername=' . $params['channel_name'];
153
+ } elseif ( isset( $params['channel_id'] ) ) {
154
+ $channel_param = 'id=' . $params['channel_id'];
155
+ }
156
+
157
+ $access_credentials = isset( $connected_account['api_key'] ) ? 'key=' . $connected_account['api_key'] : 'access_token=' . $connected_account['access_token'];
158
+
159
+ $url = 'https://www.googleapis.com/youtube/v3/channels?part=id,snippet,contentDetails&'.$channel_param.'&' . $access_credentials;
160
+ } elseif ( $endpoint_slug === 'playlistItems' ) {
161
+ $access_credentials = isset( $connected_account['api_key'] ) ? 'key=' . $connected_account['api_key'] : 'access_token=' . $connected_account['access_token'];
162
+ $next_page = '';
163
+ if ( isset( $params['nextPageToken'] ) ) {
164
+ $next_page = '&pageToken=' . $params['nextPageToken'];
165
+ }
166
+
167
+ $url = 'https://www.googleapis.com/youtube/v3/playlistItems?part=id,snippet&maxResults='.$num.'&playlistId='.$params['playlist_id'].'&' . $access_credentials . $next_page;
168
+ } else {
169
+ $channel_param = 'mine=true';
170
+ if ( isset( $params['username'] ) ) {
171
+ $channel_param = 'forUsername=' . $params['username'];
172
+ } elseif ( isset( $params['channel_id'] ) ) {
173
+ $channel_param = 'id=' . $params['channel_id'];
174
+ }
175
+ $access_credentials = isset( $connected_account['api_key'] ) ? 'key=' . $connected_account['api_key'] : 'access_token=' . $connected_account['access_token'];
176
+
177
+ $url = 'https://www.googleapis.com/youtube/v3/channels?part=id,snippet&'.$channel_param.'&' . $access_credentials;
178
+ }
179
+
180
+ $this->set_url_from_args( $url );
181
+ }
182
+
183
+ public static function refresh_token( $client_id, $refresh_token, $client_secret ) {
184
+ $response = wp_remote_post( 'https://www.googleapis.com/oauth2/v4/token/?client_id=' . $client_id . '&client_secret=' . $client_secret . '&refresh_token='. $refresh_token . '&grant_type=refresh_token' );
185
+
186
+ if ( $response['response']['code'] === 200 ) {
187
+ $return = json_decode( $response['body'], true );
188
+ } else {
189
+ $return = array();
190
+ }
191
+
192
+ return $return;
193
+ }
194
+
195
  }
inc/class-sby-cron-update.php CHANGED
@@ -1,205 +1,205 @@
1
- <?php
2
- /**
3
- * Class SBY_Cron_Updater
4
- *
5
- * Finds all regular feed transients saved in the database and updates
6
- * each cached feed in the background using WP Cron. This is set up with the
7
- * "sby_cron_updater" function in the if-functions.php file. The "display_instagram"
8
- * function will trigger a single feed update if no transient is found
9
- * for the feed
10
- *
11
- * @since 1.0/1.0
12
- */
13
-
14
- if ( ! defined( 'ABSPATH' ) ) {
15
- die( '-1' );
16
- }
17
-
18
- class SBY_Cron_Updater
19
- {
20
- /**
21
- * Find and loop through all feed cache transients and update the post and
22
- * header caches
23
- *
24
- * Overwritten in the Pro version
25
- *
26
- * @since 1.0
27
- */
28
- public static function do_feed_updates() {
29
- $feed_caches = SBY_Cron_Updater::get_feed_cache_option_names();
30
- shuffle( $feed_caches );
31
- $database_settings = sby_get_database_settings();
32
-
33
- // this is outputted in system info
34
- $report = array(
35
- 'notes' => array(
36
- 'time_ran' => date( 'Y-m-d H:i:s' ),
37
- 'num_found_transients' => count( $feed_caches )
38
- )
39
- );
40
-
41
- foreach ( $feed_caches as $feed_cache ) {
42
-
43
- $feed_id = str_replace( '_transient_', '', $feed_cache['option_name'] );
44
- $report[ $feed_id ] = array();
45
-
46
- $transient = get_transient( $feed_id );
47
-
48
- if ( $transient ) {
49
- $feed_data = json_decode( $transient, true );
50
-
51
- // shortcode attributes are saved in order to recreate the feed is needed
52
- $atts = isset( $feed_data['atts'] ) ? $feed_data['atts'] : array();
53
- $last_retrieve = isset( $feed_data['last_retrieve'] ) ? (int)$feed_data['last_retrieve'] : 0;
54
- // the last approximate time the feed was requested to be displayed on a page is recorded
55
- // in order to stop updating feeds not in use.
56
- $last_requested = isset( $feed_data['last_requested'] ) ? (int)$feed_data['last_requested'] : false;
57
- $report[ $feed_id ]['last_retrieve'] = date( 'Y-m-d H:i:s', $last_retrieve );
58
- if ( $atts !== false ) {
59
-
60
- if ( ! $last_requested || $last_requested > (time() - 60*60*24*30) ) {
61
- $sby_settings_obj = new SBY_Settings( $atts, $database_settings );
62
-
63
- if ( empty( $database_settings['connected_accounts'] ) && empty( $database_settings['api_key'] ) ) {
64
- $report[ $feed_id ]['did_update'] = 'no - no connected account';
65
- } else {
66
- SBY_Cron_Updater::do_single_feed_cron_update( $sby_settings_obj, $feed_data, $atts );
67
-
68
- $report[ $feed_id ]['did_update'] = 'yes';
69
- }
70
- } else {
71
- $report[ $feed_id ]['did_update'] = 'no - not recently requested';
72
- }
73
-
74
-
75
- } else {
76
- $report[ $feed_id ]['did_update'] = 'no - missing atts';
77
- }
78
-
79
- } else {
80
- $report[ $feed_id ]['did_update'] = 'no - no transient found';
81
- }
82
-
83
- }
84
-
85
- update_option( 'sby_cron_report', $report, false );
86
- }
87
-
88
- /**
89
- * Update a single feed cache based on settings. Local image storing and
90
- * resizing is done in the background here as well unless this is the initial
91
- * time the feed is created and no cached data exists yet.
92
- *
93
- * Overwritten in the Pro version
94
- *
95
- * @param object $sby_settings_obj object created by the sby_settings class
96
- * @param array $feed_data post, header, shortcode settings, and other info
97
- * associated with the feed that is saved in the cache
98
- * @param array $atts shortcode settings
99
- * @param bool $include_resize whether or not to resize images during the update since
100
- * images can also be resized with an ajax call when the feed is viewed on the frontend
101
- *
102
- * @since 1.0
103
- */
104
- public static function do_single_feed_cron_update( $sby_settings_obj, $feed_data, $atts, $include_resize = true ) {
105
- $sby_settings_obj->set_feed_type_and_terms();
106
- $sby_settings_obj->set_transient_name();
107
- $transient_name = $sby_settings_obj->get_transient_name();
108
- $settings = $sby_settings_obj->get_settings();
109
- $feed_type_and_terms = $sby_settings_obj->get_feed_type_and_terms();
110
-
111
- $youtube_feed = new SBY_Feed( $transient_name );
112
-
113
- while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
114
- $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $sby_settings_obj->get_connected_accounts_in_feed() );
115
- }
116
-
117
- $to_cache = array(
118
- 'atts' => $atts,
119
- 'last_requested' => $feed_data['last_requested'],
120
- 'last_retrieve' => time()
121
- );
122
-
123
- $youtube_feed->set_cron_cache( $to_cache, $sby_settings_obj->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
124
-
125
- if ( $youtube_feed->need_header( $settings, $feed_type_and_terms ) ) {
126
- $youtube_feed->set_remote_header_data( $settings, $feed_type_and_terms, $sby_settings_obj->get_connected_accounts_in_feed() );
127
-
128
- $youtube_feed->cache_header_data( $sby_settings_obj->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
129
- }
130
-
131
- $post_data = $youtube_feed->get_post_data();
132
- $post_data = array_slice( $post_data, 0, $settings['num'] );
133
-
134
- sby_process_post_set_caching( $post_data, $transient_name );
135
-
136
- }
137
-
138
- /**
139
- * Retrieve option name column values for all feed cache transients
140
- *
141
- * @return array
142
- *
143
- * @since 1.0
144
- */
145
- public static function get_feed_cache_option_names() {
146
- global $wpdb;
147
- $feed_caches = array();
148
-
149
- $results = $wpdb->get_results( "
150
- SELECT option_name
151
- FROM $wpdb->options
152
- WHERE `option_name` LIKE ('%\_transient\_sby\_%')
153
- AND `option_name` NOT LIKE ('%\_transient\_sby\_header%');", ARRAY_A );
154
-
155
- if ( isset( $results[0] ) ) {
156
- $feed_caches = $results;
157
- }
158
-
159
- return $feed_caches;
160
- }
161
-
162
- /**
163
- * Start cron jobs based on user's settings for cron cache update frequency.
164
- * This is triggered when settings are saved on the "Configure" tab.
165
- *
166
- * @param string $sby_cache_cron_interval arbitrary name from one of the
167
- * settings on the "Configure" tab
168
- * @param string $sby_cache_cron_time hour of the day (1 = 1:00)
169
- * @param string $sby_cache_cron_am_pm am or pm (time of day)
170
- *
171
- * @since 1.0
172
- */
173
- public static function start_cron_job( $sby_cache_cron_interval, $sby_cache_cron_time, $sby_cache_cron_am_pm ) {
174
- wp_clear_scheduled_hook( 'sby_feed_update' );
175
-
176
- if ( $sby_cache_cron_interval === '12hours' || $sby_cache_cron_interval === '24hours' ) {
177
- $relative_time_now = time() + sby_get_utc_offset();
178
- $base_day = strtotime( date( 'Y-m-d', $relative_time_now ) );
179
- $add_time = $sby_cache_cron_am_pm === 'pm' ? (int)$sby_cache_cron_time + 12 : (int)$sby_cache_cron_time;
180
- $utc_start_time = $base_day + (($add_time * 60 * 60) - sby_get_utc_offset());
181
-
182
- if ( $utc_start_time < time() ) {
183
- if ( $sby_cache_cron_interval === '12hours' ) {
184
- $utc_start_time += 60*60*12;
185
- } else {
186
- $utc_start_time += 60*60*24;
187
- }
188
- }
189
-
190
- if ( $sby_cache_cron_interval === '12hours' ) {
191
- wp_schedule_event( $utc_start_time, 'twicedaily', 'sby_feed_update' );
192
- } else {
193
- wp_schedule_event( $utc_start_time, 'daily', 'sby_feed_update' );
194
- }
195
-
196
- } else {
197
- if ( $sby_cache_cron_interval === '30mins' ) {
198
- wp_schedule_event( time(), 'sby30mins', 'sby_feed_update' );
199
- } else {
200
- wp_schedule_event( time(), 'hourly', 'sby_feed_update' );
201
- }
202
- }
203
-
204
- }
205
  }
1
+ <?php
2
+ /**
3
+ * Class SBY_Cron_Updater
4
+ *
5
+ * Finds all regular feed transients saved in the database and updates
6
+ * each cached feed in the background using WP Cron. This is set up with the
7
+ * "sby_cron_updater" function in the if-functions.php file. The "display_instagram"
8
+ * function will trigger a single feed update if no transient is found
9
+ * for the feed
10
+ *
11
+ * @since 1.0/1.0
12
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ die( '-1' );
16
+ }
17
+
18
+ class SBY_Cron_Updater
19
+ {
20
+ /**
21
+ * Find and loop through all feed cache transients and update the post and
22
+ * header caches
23
+ *
24
+ * Overwritten in the Pro version
25
+ *
26
+ * @since 1.0
27
+ */
28
+ public static function do_feed_updates() {
29
+ $feed_caches = SBY_Cron_Updater::get_feed_cache_option_names();
30
+ shuffle( $feed_caches );
31
+ $database_settings = sby_get_database_settings();
32
+
33
+ // this is outputted in system info
34
+ $report = array(
35
+ 'notes' => array(
36
+ 'time_ran' => date( 'Y-m-d H:i:s' ),
37
+ 'num_found_transients' => count( $feed_caches )
38
+ )
39
+ );
40
+
41
+ foreach ( $feed_caches as $feed_cache ) {
42
+
43
+ $feed_id = str_replace( '_transient_', '', $feed_cache['option_name'] );
44
+ $report[ $feed_id ] = array();
45
+
46
+ $transient = get_transient( $feed_id );
47
+
48
+ if ( $transient ) {
49
+ $feed_data = json_decode( $transient, true );
50
+
51
+ // shortcode attributes are saved in order to recreate the feed is needed
52
+ $atts = isset( $feed_data['atts'] ) ? $feed_data['atts'] : array();
53
+ $last_retrieve = isset( $feed_data['last_retrieve'] ) ? (int)$feed_data['last_retrieve'] : 0;
54
+ // the last approximate time the feed was requested to be displayed on a page is recorded
55
+ // in order to stop updating feeds not in use.
56
+ $last_requested = isset( $feed_data['last_requested'] ) ? (int)$feed_data['last_requested'] : false;
57
+ $report[ $feed_id ]['last_retrieve'] = date( 'Y-m-d H:i:s', $last_retrieve );
58
+ if ( $atts !== false ) {
59
+
60
+ if ( ! $last_requested || $last_requested > (time() - 60*60*24*30) ) {
61
+ $sby_settings_obj = new SBY_Settings( $atts, $database_settings );
62
+
63
+ if ( empty( $database_settings['connected_accounts'] ) && empty( $database_settings['api_key'] ) ) {
64
+ $report[ $feed_id ]['did_update'] = 'no - no connected account';
65
+ } else {
66
+ SBY_Cron_Updater::do_single_feed_cron_update( $sby_settings_obj, $feed_data, $atts );
67
+
68
+ $report[ $feed_id ]['did_update'] = 'yes';
69
+ }
70
+ } else {
71
+ $report[ $feed_id ]['did_update'] = 'no - not recently requested';
72
+ }
73
+
74
+
75
+ } else {
76
+ $report[ $feed_id ]['did_update'] = 'no - missing atts';
77
+ }
78
+
79
+ } else {
80
+ $report[ $feed_id ]['did_update'] = 'no - no transient found';
81
+ }
82
+
83
+ }
84
+
85
+ update_option( 'sby_cron_report', $report, false );
86
+ }
87
+
88
+ /**
89
+ * Update a single feed cache based on settings. Local image storing and
90
+ * resizing is done in the background here as well unless this is the initial
91
+ * time the feed is created and no cached data exists yet.
92
+ *
93
+ * Overwritten in the Pro version
94
+ *
95
+ * @param object $sby_settings_obj object created by the sby_settings class
96
+ * @param array $feed_data post, header, shortcode settings, and other info
97
+ * associated with the feed that is saved in the cache
98
+ * @param array $atts shortcode settings
99
+ * @param bool $include_resize whether or not to resize images during the update since
100
+ * images can also be resized with an ajax call when the feed is viewed on the frontend
101
+ *
102
+ * @since 1.0
103
+ */
104
+ public static function do_single_feed_cron_update( $sby_settings_obj, $feed_data, $atts, $include_resize = true ) {
105
+ $sby_settings_obj->set_feed_type_and_terms();
106
+ $sby_settings_obj->set_transient_name();
107
+ $transient_name = $sby_settings_obj->get_transient_name();
108
+ $settings = $sby_settings_obj->get_settings();
109
+ $feed_type_and_terms = $sby_settings_obj->get_feed_type_and_terms();
110
+
111
+ $youtube_feed = new SBY_Feed( $transient_name );
112
+
113
+ while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
114
+ $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $sby_settings_obj->get_connected_accounts_in_feed() );
115
+ }
116
+
117
+ $to_cache = array(
118
+ 'atts' => $atts,
119
+ 'last_requested' => $feed_data['last_requested'],
120
+ 'last_retrieve' => time()
121
+ );
122
+
123
+ $youtube_feed->set_cron_cache( $to_cache, $sby_settings_obj->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
124
+
125
+ if ( $youtube_feed->need_header( $settings, $feed_type_and_terms ) ) {
126
+ $youtube_feed->set_remote_header_data( $settings, $feed_type_and_terms, $sby_settings_obj->get_connected_accounts_in_feed() );
127
+
128
+ $youtube_feed->cache_header_data( $sby_settings_obj->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
129
+ }
130
+
131
+ $post_data = $youtube_feed->get_post_data();
132
+ $post_data = array_slice( $post_data, 0, $settings['num'] );
133
+
134
+ sby_process_post_set_caching( $post_data, $transient_name );
135
+
136
+ }
137
+
138
+ /**
139
+ * Retrieve option name column values for all feed cache transients
140
+ *
141
+ * @return array
142
+ *
143
+ * @since 1.0
144
+ */
145
+ public static function get_feed_cache_option_names() {
146
+ global $wpdb;
147
+ $feed_caches = array();
148
+
149
+ $results = $wpdb->get_results( "
150
+ SELECT option_name
151
+ FROM $wpdb->options
152
+ WHERE `option_name` LIKE ('%\_transient\_sby\_%')
153
+ AND `option_name` NOT LIKE ('%\_transient\_sby\_header%');", ARRAY_A );
154
+
155
+ if ( isset( $results[0] ) ) {
156
+ $feed_caches = $results;
157
+ }
158
+
159
+ return $feed_caches;
160
+ }
161
+
162
+ /**
163
+ * Start cron jobs based on user's settings for cron cache update frequency.
164
+ * This is triggered when settings are saved on the "Configure" tab.
165
+ *
166
+ * @param string $sby_cache_cron_interval arbitrary name from one of the
167
+ * settings on the "Configure" tab
168
+ * @param string $sby_cache_cron_time hour of the day (1 = 1:00)
169
+ * @param string $sby_cache_cron_am_pm am or pm (time of day)
170
+ *
171
+ * @since 1.0
172
+ */
173
+ public static function start_cron_job( $sby_cache_cron_interval, $sby_cache_cron_time, $sby_cache_cron_am_pm ) {
174
+ wp_clear_scheduled_hook( 'sby_feed_update' );
175
+
176
+ if ( $sby_cache_cron_interval === '12hours' || $sby_cache_cron_interval === '24hours' ) {
177
+ $relative_time_now = time() + sby_get_utc_offset();
178
+ $base_day = strtotime( date( 'Y-m-d', $relative_time_now ) );
179
+ $add_time = $sby_cache_cron_am_pm === 'pm' ? (int)$sby_cache_cron_time + 12 : (int)$sby_cache_cron_time;
180
+ $utc_start_time = $base_day + (($add_time * 60 * 60) - sby_get_utc_offset());
181
+
182
+ if ( $utc_start_time < time() ) {
183
+ if ( $sby_cache_cron_interval === '12hours' ) {
184
+ $utc_start_time += 60*60*12;
185
+ } else {
186
+ $utc_start_time += 60*60*24;
187
+ }
188
+ }
189
+
190
+ if ( $sby_cache_cron_interval === '12hours' ) {
191
+ wp_schedule_event( $utc_start_time, 'twicedaily', 'sby_feed_update' );
192
+ } else {
193
+ wp_schedule_event( $utc_start_time, 'daily', 'sby_feed_update' );
194
+ }
195
+
196
+ } else {
197
+ if ( $sby_cache_cron_interval === '30mins' ) {
198
+ wp_schedule_event( time(), 'sby30mins', 'sby_feed_update' );
199
+ } else {
200
+ wp_schedule_event( time(), 'hourly', 'sby_feed_update' );
201
+ }
202
+ }
203
+
204
+ }
205
  }
inc/class-sby-display-elements.php CHANGED
@@ -1,376 +1,392 @@
1
- <?php
2
-
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- die( '-1' );
5
- }
6
-
7
- class SBY_Display_Elements
8
- {
9
- /**
10
- * Images are hidden initially with the new/transition classes
11
- * except if the js image loading is disabled using the plugin
12
- * settings
13
- *
14
- * @param $settings
15
- *
16
- * @return string
17
- *
18
- * @since 1.0
19
- */
20
- public static function get_item_classes( $settings ) {
21
- $classes = array( 'sby_new' );
22
- if ( !$settings['disable_js_image_loading'] ) {
23
- $classes[] = 'sby_transition';
24
- } else {
25
- $classes[] = 'sby_no_js';
26
-
27
- $classes[] = 'sby_no_resraise';
28
- $classes[] = 'sby_js_load_disabled';
29
- }
30
-
31
- if ( $settings['layout'] !== 'list' ) {
32
- $classes[] = 'sby_no_margin';
33
- }
34
-
35
- return ' ' . implode( ' ', $classes );
36
- }
37
-
38
- /**
39
- * Overwritten in the Pro version.
40
- *
41
- * @param string $type key of the kind of icon needed
42
- * @param string $icon_type svg or font
43
- *
44
- * @return string the complete html for the icon
45
- *
46
- * @since 1.0
47
- */
48
- public static function get_icon( $type, $icon_type ) {
49
- return self::get_basic_icons( $type, $icon_type );
50
- }
51
-
52
- public static function get_cols( $settings ) {
53
- if ( isset( $settings[ $settings['layout'] . 'cols'] ) ) {
54
- return $settings[ $settings['layout'] . 'cols'];
55
- }
56
- return 0;
57
- }
58
-
59
- public static function get_cols_mobile( $settings ) {
60
- if ( isset( $settings[ $settings['layout'] . 'colsmobile'] ) ) {
61
- return $settings[ $settings['layout'] . 'colsmobile'];
62
- }
63
- return 0;
64
- }
65
-
66
- public static function get_style_att( $context, $settings, $pos = false ) {
67
- $style_settings = array();
68
- $item_spacing_setting = $settings['itemspacing'];
69
- if ( ! preg_match("/(px)|(%)/", $item_spacing_setting ) ) {
70
- $item_spacing_setting = $item_spacing_setting . $settings['itemspacingunit'];
71
- }
72
- if ( $context === 'player' ) {
73
- $style_settings['margin-bottom'] = $item_spacing_setting;
74
- } elseif ( $context === 'item' ) {
75
- if ( $settings['layout'] === 'list' ) {
76
- $style_settings['margin-bottom'] = $item_spacing_setting;
77
- }
78
- } elseif ( $context === 'items_wrap' || $context === 'player_outer_wrap' ) {
79
- if ( $settings['layout'] !== 'list' ) {
80
- $style_settings['padding'] = $item_spacing_setting;
81
- }
82
- if ( isset( $settings['descriptiontextsize'] ) && $settings['descriptiontextsize'] !== '13px' ) {
83
- $style_settings['font-size'] = $settings['descriptiontextsize'];
84
- }
85
- } elseif ( $context === 'header' ) {
86
- if ( $settings['itemspacing'] > 0 ) {
87
- $style_settings['padding'] = $item_spacing_setting;
88
- }
89
- if ( $settings['itemspacing'] < 10 ) {
90
- $style_settings['margin-bottom'] = '10px';
91
- }
92
- $style_settings['padding-bottom'] = '0';
93
- }
94
-
95
- if ( $context === 'player_outer_wrap' ) {
96
- $style_settings['padding-bottom'] = 0;
97
- }
98
-
99
- $style_att = '';
100
- if ( ! empty( $style_settings ) ) {
101
- $style_att = ' style="';
102
- foreach ( $style_settings as $prop => $val ) {
103
- $style_att .= $prop . ': '. $val . ';';
104
- }
105
- $style_att .= '"';
106
- }
107
-
108
- return $style_att;
109
- }
110
-
111
- public static function get_display_avatar( $header_data, $settings ) {
112
- if ( SBY_GDPR_Integrations::doing_gdpr( $settings ) && $settings['disablecdn'] ) {
113
- return trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png';
114
- }
115
- return SBY_Parse::get_avatar( $header_data, $settings );
116
- }
117
-
118
- /**
119
- * Returns the best media url for an image based on settings.
120
- * By default a white placeholder image is loaded and replaced
121
- * with the most optimal image size based on the actual dimensions
122
- * of the image element in the feed.
123
- *
124
- * @param array $post data for an individual post
125
- * @param array $settings
126
- * @param array $resized_images (optional) not yet used but
127
- * can pass in existing resized images to use in the source
128
- *
129
- * @return string
130
- *
131
- * @since 1.0
132
- */
133
- public static function get_optimum_media_url( $post, $settings, $resized_images = array() ) {
134
- $media_url = '';
135
- $optimum_res = $settings['imageres'];
136
- $account_type = isset( $post['images'] ) ? 'personal' : 'business';
137
-
138
- // only use the placeholder if it will be replaced using JS
139
- if ( !$settings['disable_js_image_loading'] || $settings['disablecdn'] ) {
140
- return trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png';
141
- } else {
142
- $optimum_res = 'full';
143
- $settings['imageres'] = 'full';
144
- }
145
-
146
- $media_url = SBY_Parse::get_media_url( $post, 'lightbox' );
147
-
148
- return $media_url;
149
- }
150
-
151
- /**
152
- * Creates a style attribute that contains all of the styles for
153
- * the main feed div.
154
- *
155
- * @param $settings
156
- *
157
- * @return string
158
- */
159
- public static function get_feed_style( $settings ) {
160
-
161
- $styles = '';
162
- $bg_color = str_replace( '#', '', $settings['background'] );
163
-
164
- if ( ! empty( $settings['imagepadding'] )
165
- || ! empty( $bg_color )
166
- || ! empty( $settings['width'] )
167
- || ! empty( $settings['height'] ) ) {
168
- $styles = ' style="';
169
- if ( ! empty( $settings['imagepadding'] ) ) {
170
- $styles .= 'padding-bottom: ' . ((int)$settings['imagepadding'] * 2) . esc_attr( $settings['imagepaddingunit'] ) . ';';
171
- }
172
- if ( ! empty( $bg_color ) ) {
173
- $styles .= 'background-color: rgb(' . esc_attr( sby_hextorgb( $bg_color ) ). ');';
174
- }
175
- if ( ! empty( $settings['width'] ) ) {
176
- $styles .= 'width: ' . (int)$settings['width'] . esc_attr( $settings['widthunit'] ) . ';';
177
- }
178
- if ( ! empty( $settings['height'] ) ) {
179
- $styles .= 'height: ' . (int)$settings['height'] . esc_attr( $settings['heightunit'] ) . ';';
180
- }
181
- $styles .= '"';
182
- }
183
- return $styles;
184
- }
185
-
186
- /**
187
- * Creates a style attribute for the sby_images div
188
- *
189
- * @param $settings
190
- *
191
- * @return string
192
- *
193
- * @since 1.0
194
- */
195
- public static function get_items_wrap_style( $settings ) {
196
- if ( ! empty ( $settings['imagepadding'] ) ) {
197
- return 'style="padding: '.(int)$settings['imagepadding'] . esc_attr( $settings['imagepaddingunit'] ) . ';"';
198
- }
199
- return '';
200
- }
201
-
202
- /**
203
- * Creates a style attribute for the header. Can be used in
204
- * several places based on the header style
205
- *
206
- * @param $settings
207
- *
208
- * @return string
209
- *
210
- * @since 1.0
211
- */
212
- public static function get_header_text_color_styles( $settings ) {
213
- $header_color = str_replace( '#', '', $settings['headercolor'] );
214
-
215
- if ( ! empty( $header_color ) ) {
216
- return 'style="color: rgb(' . esc_attr( sby_hextorgb( $header_color ) ). ');"';
217
- }
218
- return '';
219
- }
220
-
221
- /**
222
- * Header icon and text size is styled using the class added here.
223
- *
224
- * @param $settings
225
- *
226
- * @return string
227
- *
228
- * @since 1.0
229
- */
230
- public static function get_header_size_class( $settings ) {
231
- $header_size_class = in_array( strtolower( $settings['headersize'] ), array( 'medium', 'large' ) ) ? ' sby_'.strtolower( $settings['headersize'] ) : '';
232
- return $header_size_class;
233
- }
234
-
235
- /**
236
- * Creates a style attribute for the subscribe button. Can be in
237
- * the feed footer or in a boxed header.
238
- *
239
- * @param $settings
240
- *
241
- * @return string
242
- *
243
- * @since 1.0
244
- */
245
- public static function get_subscribe_styles( $settings ) {
246
- $styles = '';
247
- $subscribe_color = str_replace( '#', '', $settings['subscribecolor'] );
248
- $subscribe_text_color = str_replace( '#', '', $settings['subscribetextcolor'] );
249
-
250
- if ( ! empty( $subscribe_color ) || ! empty( $subscribe_text_color ) ) {
251
- $styles = 'style="';
252
- if ( ! empty( $subscribe_color ) ) {
253
- $styles .= 'background: rgb(' . esc_attr( sby_hextorgb( $subscribe_color ) ) . ');';
254
- }
255
- if ( ! empty( $subscribe_text_color ) ) {
256
- $styles .= 'color: rgb(' . esc_attr( sby_hextorgb( $subscribe_text_color ) ). ');';
257
- }
258
- $styles .= '"';
259
- }
260
- return $styles;
261
- }
262
-
263
- /**
264
- * Creates a style attribute for styling the load more button.
265
- *
266
- * @param $settings
267
- *
268
- * @return string
269
- *
270
- * @since 1.0
271
- */
272
- public static function get_load_button_styles( $settings ) {
273
- $styles = '';
274
- $button_color = str_replace( '#', '', $settings['buttoncolor'] );
275
- $button_text_color = str_replace( '#', '', $settings['buttontextcolor'] );
276
-
277
- if ( ! empty( $button_color ) || ! empty( $button_text_color ) ) {
278
- $styles = 'style="';
279
- if ( ! empty( $button_color ) ) {
280
- $styles .= 'background: rgb(' . esc_attr( sby_hextorgb( $button_color ) ) . ');';
281
- }
282
- if ( ! empty( $button_text_color ) ) {
283
- $styles .= 'color: rgb(' . esc_attr( sby_hextorgb( $button_text_color ) ). ');';
284
- }
285
- $styles .= '"';
286
- }
287
- return $styles;
288
- }
289
-
290
- /**
291
- * A not very elegant but useful method to abstract out how the settings
292
- * work for displaying certain elements in the feed.
293
- *
294
- * @param string $element specific key, view below for supported ones
295
- * @param $settings
296
- *
297
- * @return bool
298
- *
299
- * @since 5.0
300
- */
301
- public static function should_show_element( $element, $context, $settings ) {
302
- //user, views, date
303
- if ( $context === 'item-hover' ) {
304
- $include_array = is_array( $settings['hoverinclude'] ) ? $settings['hoverinclude'] : explode( ',', str_replace( ' ', '', $settings['hoverinclude'] ) );
305
- } else {
306
- $include_array = is_array( $settings['include'] ) ? $settings['include'] : explode( ',', str_replace( ' ', '', $settings['include'] ) );
307
- }
308
-
309
- if ( in_array( $element, $include_array, true ) ) {
310
- return true;
311
- }
312
-
313
- return false;
314
- }
315
-
316
- /**
317
- * Returns the html for an icon based on the kind requested
318
- *
319
- * @param string $type kind of icon needed (ex "video" is a play button)
320
- * @param string $icon_type svg or font
321
- *
322
- * @return string
323
- *
324
- * @since 1.0
325
- */
326
- protected static function get_basic_icons( $type, $icon_type ) {
327
- if ( $type === 'carousel' ) {
328
- if ( $icon_type === 'svg' ) {
329
- return '<svg class="svg-inline--fa fa-clone fa-w-16 sby_lightbox_carousel_icon" aria-hidden="true" data-fa-proƒcessed="" data-prefix="far" data-icon="clone" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
330
- <path fill="currentColor" d="M464 0H144c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h48c26.51 0 48-21.49 48-48V48c0-26.51-21.49-48-48-48zM362 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h42v224c0 26.51 21.49 48 48 48h224v42a6 6 0 0 1-6 6zm96-96H150a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v308a6 6 0 0 1-6 6z"></path>
331
- </svg>';
332
- } else {
333
- return '<i class="fa fa-clone sby_carousel_icon" aria-hidden="true"></i>';
334
- }
335
-
336
- } elseif ( $type === 'video' ) {
337
- if ( $icon_type === 'svg' ) {
338
- return '<svg style="color: rgba(255,255,255,1)" class="svg-inline--fa fa-play fa-w-14 sby_playbtn" aria-hidden="true" data-fa-processed="" data-prefix="fa" data-icon="play" role="presentation" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"></path></svg>';
339
- } else {
340
- return '<i class="fa fa-play sby_playbtn" aria-hidden="true"></i>';
341
- }
342
- } elseif ( $type === 'youtube' ) {
343
- if ( $icon_type === 'svg' ) {
344
- return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-youtube fa-w-18"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
345
- } else {
346
- return '<i aria-hidden="true" role="img" class="sby_new_logo fab fa-youtube"></i>';
347
- }
348
- } elseif ( $type === 'newlogo' ) {
349
- if ( $icon_type === 'svg' ) {
350
- return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="sby_new_logo svg-inline--fa fa-youtube fa-w-18"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
351
- } else {
352
- return '<i aria-hidden="true" role="img" class="sby_new_logo fab fa-youtube"></i>';
353
- }
354
- } elseif ( $type === 'play') {
355
- if ( $icon_type === 'svg' ) {
356
- return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-youtube fa-w-18"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
357
- } else {
358
- return '<i aria-hidden="true" role="img" class="fa fas fa-play"></i>';
359
- }
360
- } else {
361
- return '';
362
- }
363
- }
364
-
365
- public static function escaped_data_att_string( $atts ) {
366
- if ( empty( $atts ) ) {
367
- return '';
368
- }
369
- $string = '';
370
- foreach ( $atts as $key => $value ) {
371
- $string .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
372
- }
373
-
374
- return $string;
375
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  }
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ die( '-1' );
5
+ }
6
+
7
+ class SBY_Display_Elements
8
+ {
9
+ /**
10
+ * Images are hidden initially with the new/transition classes
11
+ * except if the js image loading is disabled using the plugin
12
+ * settings
13
+ *
14
+ * @param $settings
15
+ *
16
+ * @return string
17
+ *
18
+ * @since 1.0
19
+ */
20
+ public static function get_item_classes( $settings ) {
21
+ $classes = array( 'sby_new' );
22
+ if ( !$settings['disable_js_image_loading'] ) {
23
+ $classes[] = 'sby_transition';
24
+ } else {
25
+ $classes[] = 'sby_no_js';
26
+
27
+ $classes[] = 'sby_no_resraise';
28
+ $classes[] = 'sby_js_load_disabled';
29
+ }
30
+
31
+ if ( $settings['layout'] !== 'list' ) {
32
+ $classes[] = 'sby_no_margin';
33
+ }
34
+
35
+ return ' ' . implode( ' ', $classes );
36
+ }
37
+
38
+ /**
39
+ * Overwritten in the Pro version.
40
+ *
41
+ * @param string $type key of the kind of icon needed
42
+ * @param string $icon_type svg or font
43
+ *
44
+ * @return string the complete html for the icon
45
+ *
46
+ * @since 1.0
47
+ */
48
+ public static function get_icon( $type, $icon_type ) {
49
+ return self::get_basic_icons( $type, $icon_type );
50
+ }
51
+
52
+ public static function get_cols( $settings ) {
53
+ if ( isset( $settings[ $settings['layout'] . 'cols'] ) ) {
54
+ return $settings[ $settings['layout'] . 'cols'];
55
+ }
56
+ return 0;
57
+ }
58
+
59
+ public static function get_cols_mobile( $settings ) {
60
+ if ( isset( $settings[ $settings['layout'] . 'colsmobile'] ) ) {
61
+ return $settings[ $settings['layout'] . 'colsmobile'];
62
+ }
63
+ return 0;
64
+ }
65
+
66
+ public static function get_style_att( $context, $settings, $pos = false ) {
67
+ $style_settings = array();
68
+ $item_spacing_setting = $settings['itemspacing'];
69
+ if ( ! preg_match("/(px)|(%)/", $item_spacing_setting ) ) {
70
+ $item_spacing_setting = $item_spacing_setting . $settings['itemspacingunit'];
71
+ }
72
+ if ( $context === 'player' ) {
73
+ $style_settings['margin-bottom'] = $item_spacing_setting;
74
+ } elseif ( $context === 'item' ) {
75
+ if ( $settings['layout'] === 'list' ) {
76
+ $style_settings['margin-bottom'] = $item_spacing_setting;
77
+ }
78
+ } elseif ( $context === 'items_wrap' || $context === 'player_outer_wrap' ) {
79
+ if ( $settings['layout'] !== 'list' ) {
80
+ $style_settings['padding'] = $item_spacing_setting;
81
+ }
82
+ if ( isset( $settings['descriptiontextsize'] ) && $settings['descriptiontextsize'] !== '13px' ) {
83
+ $style_settings['font-size'] = $settings['descriptiontextsize'];
84
+ }
85
+ } elseif ( $context === 'header' ) {
86
+ if ( $settings['itemspacing'] > 0 ) {
87
+ $style_settings['padding'] = $item_spacing_setting;
88
+ }
89
+ if ( $settings['itemspacing'] < 10 ) {
90
+ $style_settings['margin-bottom'] = '10px';
91
+ }
92
+ $style_settings['padding-bottom'] = '0';
93
+ }
94
+
95
+ if ( $context === 'player_outer_wrap' ) {
96
+ $style_settings['padding-bottom'] = 0;
97
+ }
98
+
99
+ $style_att = '';
100
+ if ( ! empty( $style_settings ) ) {
101
+ $style_att = ' style="';
102
+ foreach ( $style_settings as $prop => $val ) {
103
+ $style_att .= $prop . ': '. $val . ';';
104
+ }
105
+ $style_att .= '"';
106
+ }
107
+
108
+ return $style_att;
109
+ }
110
+
111
+ public static function get_display_avatar( $header_data, $settings ) {
112
+ if ( SBY_GDPR_Integrations::doing_gdpr( $settings ) && $settings['disablecdn'] ) {
113
+ return trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png';
114
+ }
115
+ return SBY_Parse::get_avatar( $header_data, $settings );
116
+ }
117
+
118
+ /**
119
+ * Returns the best media url for an image based on settings.
120
+ * By default a white placeholder image is loaded and replaced
121
+ * with the most optimal image size based on the actual dimensions
122
+ * of the image element in the feed.
123
+ *
124
+ * @param array $post data for an individual post
125
+ * @param array $settings
126
+ * @param array $resized_images (optional) not yet used but
127
+ * can pass in existing resized images to use in the source
128
+ *
129
+ * @return string
130
+ *
131
+ * @since 1.0
132
+ */
133
+ public static function get_optimum_media_url( $post, $settings, $resized_images = array() ) {
134
+ $media_url = '';
135
+ $optimum_res = $settings['imageres'];
136
+ $account_type = isset( $post['images'] ) ? 'personal' : 'business';
137
+
138
+ // only use the placeholder if it will be replaced using JS
139
+ if ( !$settings['disable_js_image_loading'] || $settings['disablecdn'] ) {
140
+ return trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png';
141
+ } else {
142
+ $optimum_res = 'full';
143
+ $settings['imageres'] = 'full';
144
+ }
145
+
146
+ $media_url = SBY_Parse::get_media_url( $post, 'lightbox' );
147
+
148
+ return $media_url;
149
+ }
150
+
151
+ /**
152
+ * Creates a style attribute that contains all of the styles for
153
+ * the main feed div.
154
+ *
155
+ * @param $settings
156
+ *
157
+ * @return string
158
+ */
159
+ public static function get_feed_style( $settings ) {
160
+
161
+ $styles = '';
162
+ $bg_color = str_replace( '#', '', $settings['background'] );
163
+
164
+ if ( ! isset( $settings['widthunit'] ) ) {
165
+ $settings['widthunit'] = 'px';
166
+ }
167
+
168
+ if ( ! isset( $settings['heightunit'] ) ) {
169
+ $settings['heightunit'] = 'px';
170
+ }
171
+
172
+ if ( ! empty( $settings['imagepadding'] )
173
+ || ! empty( $bg_color )
174
+ || ! empty( $settings['width'] )
175
+ || ! empty( $settings['height'] ) ) {
176
+
177
+ // The plugin settings did not mention widthunit but instead accepts px or % in the width option directly. This is a check for this to make sure widthunit is assigned properly.
178
+ $settings['widthunit'] = ( strpos( $settings['width'], 'px' ) === false && strpos( $settings['width'], '%' ) === false ) ? $settings['widthunit'] : (strpos( $settings['width'], 'px' ) !== false ? 'px' : '%' );
179
+
180
+ // The plugin settings did not mention heightunit but instead accepts px or % in the height option directly. This is a check for this to make sure heightunit is assigned properly.
181
+ $settings['heightunit'] = ( strpos( $settings['height'], 'px' ) === false && strpos( $settings['height'], '%' ) === false ) ? $settings['heightunit'] : (strpos( $settings['height'], 'px' ) !== false ? 'px' : '%' );
182
+
183
+
184
+ $styles = ' style="';
185
+ if ( ! empty( $settings['imagepadding'] ) ) {
186
+ $styles .= 'padding-bottom: ' . ((int)$settings['imagepadding'] * 2) . esc_attr( $settings['imagepaddingunit'] ) . ';';
187
+ }
188
+ if ( ! empty( $bg_color ) ) {
189
+ $styles .= 'background-color: rgb(' . esc_attr( sby_hextorgb( $bg_color ) ). ');';
190
+ }
191
+ if ( ! empty( $settings['width'] ) ) {
192
+ $styles .= 'width: ' . (int)$settings['width'] . esc_attr( $settings['widthunit'] ) . ';';
193
+ }
194
+ if ( ! empty( $settings['height'] ) ) {
195
+ $styles .= 'height: ' . (int)$settings['height'] . esc_attr( $settings['heightunit'] ) . ';';
196
+ }
197
+ $styles .= '"';
198
+ }
199
+ return $styles;
200
+ }
201
+
202
+ /**
203
+ * Creates a style attribute for the sby_images div
204
+ *
205
+ * @param $settings
206
+ *
207
+ * @return string
208
+ *
209
+ * @since 1.0
210
+ */
211
+ public static function get_items_wrap_style( $settings ) {
212
+ if ( ! empty ( $settings['imagepadding'] ) ) {
213
+ return 'style="padding: '.(int)$settings['imagepadding'] . esc_attr( $settings['imagepaddingunit'] ) . ';"';
214
+ }
215
+ return '';
216
+ }
217
+
218
+ /**
219
+ * Creates a style attribute for the header. Can be used in
220
+ * several places based on the header style
221
+ *
222
+ * @param $settings
223
+ *
224
+ * @return string
225
+ *
226
+ * @since 1.0
227
+ */
228
+ public static function get_header_text_color_styles( $settings ) {
229
+ $header_color = str_replace( '#', '', $settings['headercolor'] );
230
+
231
+ if ( ! empty( $header_color ) ) {
232
+ return 'style="color: rgb(' . esc_attr( sby_hextorgb( $header_color ) ). ');"';
233
+ }
234
+ return '';
235
+ }
236
+
237
+ /**
238
+ * Header icon and text size is styled using the class added here.
239
+ *
240
+ * @param $settings
241
+ *
242
+ * @return string
243
+ *
244
+ * @since 1.0
245
+ */
246
+ public static function get_header_size_class( $settings ) {
247
+ $header_size_class = in_array( strtolower( $settings['headersize'] ), array( 'medium', 'large' ) ) ? ' sby_'.strtolower( $settings['headersize'] ) : '';
248
+ return $header_size_class;
249
+ }
250
+
251
+ /**
252
+ * Creates a style attribute for the subscribe button. Can be in
253
+ * the feed footer or in a boxed header.
254
+ *
255
+ * @param $settings
256
+ *
257
+ * @return string
258
+ *
259
+ * @since 1.0
260
+ */
261
+ public static function get_subscribe_styles( $settings ) {
262
+ $styles = '';
263
+ $subscribe_color = str_replace( '#', '', $settings['subscribecolor'] );
264
+ $subscribe_text_color = str_replace( '#', '', $settings['subscribetextcolor'] );
265
+
266
+ if ( ! empty( $subscribe_color ) || ! empty( $subscribe_text_color ) ) {
267
+ $styles = 'style="';
268
+ if ( ! empty( $subscribe_color ) ) {
269
+ $styles .= 'background: rgb(' . esc_attr( sby_hextorgb( $subscribe_color ) ) . ');';
270
+ }
271
+ if ( ! empty( $subscribe_text_color ) ) {
272
+ $styles .= 'color: rgb(' . esc_attr( sby_hextorgb( $subscribe_text_color ) ). ');';
273
+ }
274
+ $styles .= '"';
275
+ }
276
+ return $styles;
277
+ }
278
+
279
+ /**
280
+ * Creates a style attribute for styling the load more button.
281
+ *
282
+ * @param $settings
283
+ *
284
+ * @return string
285
+ *
286
+ * @since 1.0
287
+ */
288
+ public static function get_load_button_styles( $settings ) {
289
+ $styles = '';
290
+ $button_color = str_replace( '#', '', $settings['buttoncolor'] );
291
+ $button_text_color = str_replace( '#', '', $settings['buttontextcolor'] );
292
+
293
+ if ( ! empty( $button_color ) || ! empty( $button_text_color ) ) {
294
+ $styles = 'style="';
295
+ if ( ! empty( $button_color ) ) {
296
+ $styles .= 'background: rgb(' . esc_attr( sby_hextorgb( $button_color ) ) . ');';
297
+ }
298
+ if ( ! empty( $button_text_color ) ) {
299
+ $styles .= 'color: rgb(' . esc_attr( sby_hextorgb( $button_text_color ) ). ');';
300
+ }
301
+ $styles .= '"';
302
+ }
303
+ return $styles;
304
+ }
305
+
306
+ /**
307
+ * A not very elegant but useful method to abstract out how the settings
308
+ * work for displaying certain elements in the feed.
309
+ *
310
+ * @param string $element specific key, view below for supported ones
311
+ * @param $settings
312
+ *
313
+ * @return bool
314
+ *
315
+ * @since 5.0
316
+ */
317
+ public static function should_show_element( $element, $context, $settings ) {
318
+ //user, views, date
319
+ if ( $context === 'item-hover' ) {
320
+ $include_array = is_array( $settings['hoverinclude'] ) ? $settings['hoverinclude'] : explode( ',', str_replace( ' ', '', $settings['hoverinclude'] ) );
321
+ } else {
322
+ $include_array = is_array( $settings['include'] ) ? $settings['include'] : explode( ',', str_replace( ' ', '', $settings['include'] ) );
323
+ }
324
+
325
+ if ( in_array( $element, $include_array, true ) ) {
326
+ return true;
327
+ }
328
+
329
+ return false;
330
+ }
331
+
332
+ /**
333
+ * Returns the html for an icon based on the kind requested
334
+ *
335
+ * @param string $type kind of icon needed (ex "video" is a play button)
336
+ * @param string $icon_type svg or font
337
+ *
338
+ * @return string
339
+ *
340
+ * @since 1.0
341
+ */
342
+ protected static function get_basic_icons( $type, $icon_type ) {
343
+ if ( $type === 'carousel' ) {
344
+ if ( $icon_type === 'svg' ) {
345
+ return '<svg class="svg-inline--fa fa-clone fa-w-16 sby_lightbox_carousel_icon" aria-hidden="true" data-fa-proƒcessed="" data-prefix="far" data-icon="clone" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
346
+ <path fill="currentColor" d="M464 0H144c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h48c26.51 0 48-21.49 48-48V48c0-26.51-21.49-48-48-48zM362 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h42v224c0 26.51 21.49 48 48 48h224v42a6 6 0 0 1-6 6zm96-96H150a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v308a6 6 0 0 1-6 6z"></path>
347
+ </svg>';
348
+ } else {
349
+ return '<i class="fa fa-clone sby_carousel_icon" aria-hidden="true"></i>';
350
+ }
351
+
352
+ } elseif ( $type === 'video' ) {
353
+ if ( $icon_type === 'svg' ) {
354
+ return '<svg style="color: rgba(255,255,255,1)" class="svg-inline--fa fa-play fa-w-14 sby_playbtn" aria-hidden="true" data-fa-processed="" data-prefix="fa" data-icon="play" role="presentation" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"></path></svg>';
355
+ } else {
356
+ return '<i class="fa fa-play sby_playbtn" aria-hidden="true"></i>';
357
+ }
358
+ } elseif ( $type === 'youtube' ) {
359
+ if ( $icon_type === 'svg' ) {
360
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-youtube fa-w-18"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
361
+ } else {
362
+ return '<i aria-hidden="true" role="img" class="sby_new_logo fab fa-youtube"></i>';
363
+ }
364
+ } elseif ( $type === 'newlogo' ) {
365
+ if ( $icon_type === 'svg' ) {
366
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="sby_new_logo svg-inline--fa fa-youtube fa-w-18"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
367
+ } else {
368
+ return '<i aria-hidden="true" role="img" class="sby_new_logo fab fa-youtube"></i>';
369
+ }
370
+ } elseif ( $type === 'play') {
371
+ if ( $icon_type === 'svg' ) {
372
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-youtube fa-w-18"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
373
+ } else {
374
+ return '<i aria-hidden="true" role="img" class="fa fas fa-play"></i>';
375
+ }
376
+ } else {
377
+ return '';
378
+ }
379
+ }
380
+
381
+ public static function escaped_data_att_string( $atts ) {
382
+ if ( empty( $atts ) ) {
383
+ return '';
384
+ }
385
+ $string = '';
386
+ foreach ( $atts as $key => $value ) {
387
+ $string .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
388
+ }
389
+
390
+ return $string;
391
+ }
392
  }
inc/class-sby-feed-locator.php CHANGED
@@ -1,419 +1,419 @@
1
- <?php
2
- /**
3
- * Class SBY_Feed_Locator
4
- *
5
- * Locates feeds on the site and logs information about them in the database.
6
- *
7
- * @since 1.14
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) {
11
- die( '-1' );
12
- }
13
-
14
- class SBY_Feed_Locator
15
- {
16
- private $feed_details;
17
-
18
- private $expiration_time;
19
-
20
- private $matching_entries;
21
-
22
- public function __construct( $feed_details ) {
23
- /**
24
- * Example of how $feed_details is structured
25
- *
26
- * $feed_details = array(
27
- * 'feed_id' => $transient_name,
28
- * 'atts' => $atts,
29
- * 'location' => array(
30
- * 'post_id' => get_the_ID(),
31
- * 'html' => 'unknown'
32
- * )
33
- * );
34
- */
35
- $this->feed_details = $feed_details;
36
-
37
- $this->matching_entries = array();
38
-
39
- $this->expiration_time = time() - 2 * WEEK_IN_SECONDS;
40
- }
41
-
42
- /**
43
- * Returns records that match the post ID and feed ID
44
- * of the feed being located
45
- *
46
- * @return array
47
- *
48
- * @since 1.14
49
- */
50
- public function retrieve_matching_entries() {
51
- global $wpdb;
52
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
53
-
54
- $results = $wpdb->get_results( $wpdb->prepare("
55
- SELECT *
56
- FROM $feed_locator_table_name
57
- WHERE post_id = %d
58
- AND feed_id = %s", $this->feed_details['location']['post_id'], $this->feed_details['feed_id'] ),ARRAY_A );
59
-
60
- return $results;
61
- }
62
-
63
- /**
64
- * Add feed being located to the database
65
- *
66
- * @since 1.14
67
- */
68
- public function insert_entry() {
69
- global $wpdb;
70
-
71
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
72
-
73
- $affected = $wpdb->query( $wpdb->prepare( "INSERT INTO $feed_locator_table_name
74
- (feed_id,
75
- post_id,
76
- html_location,
77
- shortcode_atts,
78
- last_update)
79
- VALUES (
80
- %s,
81
- %d,
82
- %s,
83
- %s,
84
- %s);",
85
- $this->feed_details['feed_id'],
86
- $this->feed_details['location']['post_id'],
87
- $this->feed_details['location']['html'],
88
- sby_json_encode( $this->feed_details['atts'] ),
89
- date( 'Y-m-d H:i:s' ) ) );
90
- }
91
-
92
- /**
93
- * Update a record based on the existing "id" column. Location can change
94
- * from "unknown" to one of footer, content, header, or sidebar.
95
- *
96
- * @param $id
97
- * @param $location
98
- *
99
- * @since 1.14
100
- */
101
- public function update_entry( $id, $location ) {
102
- global $wpdb;
103
-
104
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
105
-
106
- $query = $wpdb->query( $wpdb->prepare( "
107
- UPDATE $feed_locator_table_name
108
- SET last_update = %s, html_location = %s
109
- WHERE id = %d;", date( 'Y-m-d H:i:s' ), $location, $id ) );
110
- }
111
-
112
- /**
113
- * Processes a feed being located based on whether or not the record
114
- * exists as well as whether or not an unknown location needs to be
115
- * updated.
116
- *
117
- * @since 1.14
118
- */
119
- public function add_or_update_entry() {
120
- if ( empty( $this->feed_details['feed_id'] ) ) {
121
- return;
122
- }
123
-
124
- $this->matching_entries = $this->retrieve_matching_entries();
125
-
126
- if ( empty( $this->matching_entries ) ) {
127
- $this->insert_entry();
128
- } else {
129
- $matching_indices = array();
130
- $matched_location = false;
131
- $non_unknown_match = false;
132
- $unknown_match = false;
133
-
134
- foreach ( $this->matching_entries as $index => $matching_entry ) {
135
- $details_atts = is_array( $this->feed_details['atts'] ) ? $this->feed_details['atts'] : array();
136
- $matching_atts = json_decode( $matching_entry['shortcode_atts'], true );
137
- if ( ! is_array( $matching_atts ) ) {
138
- $matching_atts = array();
139
- }
140
- $atts_diff = array_diff( $matching_atts, $details_atts ); // determines if the shortcode settings match the shortcode settings of an existing feed
141
- if ( empty( $atts_diff ) ) {
142
- $matching_indices[] = $matching_entry['id'];
143
- if ( $matching_entry['html_location'] === $this->feed_details['location']['html'] ) {
144
- $matched_location = $index;
145
- $this->update_entry( $matching_entry['id'], $matching_entry['html_location'] );
146
- }
147
- if ( $matching_entry['html_location'] !== 'unknown' ) {
148
- $non_unknown_match = $index;
149
- } else {
150
- $unknown_match = $index;
151
- }
152
- }
153
- }
154
-
155
- if ( false === $matched_location ) {
156
- // if there is no matched location, there is only one feed on the page, and the feed being checked has an unknown location, update the known location
157
- if ( count( $matching_indices ) === 1
158
- && $this->feed_details['location']['html'] === 'unknown'
159
- && false !== $non_unknown_match ) {
160
- $this->update_entry( $this->matching_entries[ $non_unknown_match ]['id'], $this->matching_entries[ $non_unknown_match ]['html_location'] );
161
- } else {
162
- if ( $this->feed_details['location']['html'] !== 'unknown'
163
- && false !== $unknown_match ) {
164
- $this->update_entry( $this->matching_entries[ $unknown_match ]['id'], $this->feed_details['location']['html'] );
165
- } else {
166
- $this->insert_entry();
167
- }
168
-
169
- }
170
- }
171
-
172
- }
173
- }
174
-
175
- /**
176
- * Old feeds are only detected once a day to keep load on the server low.
177
- *
178
- * @return bool
179
- *
180
- * @since 1.14
181
- */
182
- public static function should_clear_old_locations() {
183
- $sby_statuses_option = get_option( 'sby_statuses', array() );
184
- $last_old_feed_check = isset( $sby_statuses_option['feed_locator']['last_check'] ) ? $sby_statuses_option['feed_locator']['last_check'] : 0;
185
-
186
- return $last_old_feed_check < time() - DAY_IN_SECONDS;
187
- }
188
-
189
- /**
190
- * Old feeds are removed if they haven't been updated in two weeks.
191
- *
192
- * @since 1.14
193
- */
194
- public static function delete_old_locations() {
195
- global $wpdb;
196
-
197
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
198
- $two_weeks_ago = date( 'Y-m-d H:i:s', time() - 2 * WEEK_IN_SECONDS );
199
-
200
- $affected = $wpdb->query( $wpdb->prepare(
201
- "DELETE FROM $feed_locator_table_name WHERE last_update < %s;", $two_weeks_ago ) );
202
-
203
- $sby_statuses_option = get_option( 'sby_statuses', array() );
204
- $sby_statuses_option['feed_locator']['last_check'] = time();
205
- if ( ! isset( $sby_statuses_option['feed_locator']['initialized'] ) ) {
206
- $sby_statuses_option['feed_locator']['initialized'] = time();
207
- }
208
-
209
- update_option( 'sby_statuses', $sby_statuses_option, true );
210
- }
211
-
212
- /**
213
- * Feeds are located with the page load randomly (5% or 1/30 loads)
214
- * to decrease load on the server.
215
- *
216
- * If the locating just started (within 5 minutes) it is run more often
217
- * to collect feed locations quickly.
218
- *
219
- * @return bool
220
- *
221
- * @since 1.14
222
- */
223
- public static function should_do_locating() {
224
- $sby_statuses_option = get_option( 'sby_statuses', array() );
225
- if ( isset( $sby_statuses_option['feed_locator']['initialized'] )
226
- && $sby_statuses_option['feed_locator']['initialized'] < (time() - 300) ) {
227
- $should_do_locating = rand( 1, 10 ) === 10;
228
- } else {
229
- $should_do_locating = rand( 1, 30 ) === 30;
230
- }
231
- $should_do_locating = apply_filters( 'sby_should_do_locating', $should_do_locating );
232
-
233
- return $should_do_locating;
234
- }
235
-
236
- /**
237
- * Simliar to the should_do_locating method but will add an additional
238
- * database query to see if there is a feed with an unknown location that
239
- * matches the details of the feed in question.
240
- *
241
- * @param $feed_id
242
- * @param $post_id
243
- *
244
- * @return bool
245
- *
246
- * @since 1.14
247
- */
248
- public static function should_do_ajax_locating( $feed_id, $post_id ) {
249
-
250
- $should_do_locating = rand( 1, 50 ) === 50;
251
-
252
- $should_do_locating = apply_filters( 'sby_should_do_ajax_locating', $should_do_locating );
253
-
254
- return $should_do_locating;
255
- }
256
-
257
- /**
258
- * Feeds are located with the page load randomly (1/30 loads)
259
- * to decrease load on the server.
260
- *
261
- * If the locating just started (within 5 minutes) it is run more often
262
- * to collect feed locations quickly.
263
- *
264
- * @param $feed_id
265
- * @param $post_id
266
- *
267
- * @return bool
268
- *
269
- * @since 1.14
270
- */
271
- public static function entries_need_locating( $feed_id, $post_id ) {
272
- global $wpdb;
273
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
274
-
275
- $one_day_ago = date( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS );
276
-
277
- $results = $wpdb->get_results( $wpdb->prepare("
278
- SELECT id
279
- FROM $feed_locator_table_name
280
- WHERE html_location = 'unknown'
281
- AND last_update < %s
282
- AND feed_id = %s
283
- AND post_id = %d
284
- LIMIT 1;", $one_day_ago, $feed_id, $post_id ),ARRAY_A );
285
-
286
- return isset( $results[0] );
287
- }
288
-
289
- /**
290
- * A custom table stores locations
291
- *
292
- * @since 1.14
293
- */
294
- public static function create_table() {
295
- global $wpdb;
296
-
297
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
298
-
299
- if ( $wpdb->get_var( "show tables like '$feed_locator_table_name'" ) != $feed_locator_table_name ) {
300
- $sql = "CREATE TABLE " . $feed_locator_table_name . " (
301
- id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
302
- feed_id VARCHAR(50) DEFAULT '' NOT NULL,
303
- post_id BIGINT(20) UNSIGNED NOT NULL,
304
- html_location VARCHAR(50) DEFAULT 'unknown' NOT NULL,
305
- shortcode_atts LONGTEXT NOT NULL,
306
- last_update DATETIME
307
- );";
308
- $wpdb->query( $sql );
309
- }
310
- $error = $wpdb->last_error;
311
- $query = $wpdb->last_query;
312
- $had_error = false;
313
- if ( $wpdb->get_var( "show tables like '$feed_locator_table_name'" ) != $feed_locator_table_name ) {
314
- $had_error = true;
315
- }
316
-
317
- if ( ! $had_error ) {
318
- $wpdb->query( "ALTER TABLE $feed_locator_table_name ADD INDEX feed_id (feed_id)" );
319
- $wpdb->query( "ALTER TABLE $feed_locator_table_name ADD INDEX post_id (post_id)" );
320
- }
321
- }
322
-
323
- /**
324
- * Counts the number of unique feeds in the database.
325
- *
326
- * @return int
327
- *
328
- * @since 1.14
329
- */
330
- public static function count_unique() {
331
- global $wpdb;
332
-
333
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
334
- $results_content = $wpdb->get_results( "
335
- SELECT COUNT(*) AS num_entries
336
- FROM $feed_locator_table_name
337
- WHERE html_location = 'content'
338
- ", ARRAY_A );
339
-
340
-
341
- $results_other = $wpdb->get_results( "
342
- SELECT COUNT(*) AS num_entries
343
- FROM $feed_locator_table_name
344
- WHERE html_location != 'content'
345
- AND html_location != 'unknown'
346
- GROUP BY feed_id
347
- ", ARRAY_A );
348
-
349
- $total = 0;
350
- if ( isset( $results_content[0]['num_entries'] ) ) {
351
- $total += (int)$results_content[0]['num_entries'];
352
- }
353
- if ( isset( $results_other[0]['num_entries'] ) ) {
354
- $total += (int)$results_other[0]['num_entries'];
355
- }
356
-
357
- return $total;
358
- }
359
-
360
- /**
361
- * Creates a summary of the located feeds in an array
362
- *
363
- * @return array
364
- *
365
- * @since 1.14
366
- */
367
- public static function summary() {
368
- global $wpdb;
369
-
370
- $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
371
-
372
- $locations = array(
373
- array(
374
- 'label' => __( 'Content', 'feeds-for-youtube' ),
375
- 'html_locations' => array( 'content', 'unknown' )
376
- ),
377
- array(
378
- 'label' => __( 'Header', 'feeds-for-youtube' ),
379
- 'html_locations' => array( 'header' ),
380
- 'group_by' => 'feed_id'
381
- ),
382
- array(
383
- 'label' => __( 'Sidebar', 'feeds-for-youtube' ),
384
- 'html_locations' => array( 'sidebar' ),
385
- 'group_by' => 'feed_id'
386
- ),
387
- array(
388
- 'label' => __( 'Footer', 'feeds-for-youtube' ),
389
- 'html_locations' => array( 'footer' ),
390
- 'group_by' => 'feed_id'
391
- )
392
- );
393
-
394
- $one_result_found = false;
395
-
396
- foreach ( $locations as $key => $location ) {
397
- $in = implode( "', '", $location['html_locations'] );
398
- $group_by = isset( $location['group_by'] ) ? "GROUP BY " . $location['group_by'] : "";
399
- $results = $wpdb->get_results("
400
- SELECT *
401
- FROM $feed_locator_table_name
402
- WHERE html_location IN ('$in')
403
- $group_by
404
- ORDER BY last_update ASC",ARRAY_A );
405
-
406
- if ( isset( $results[0] ) ) {
407
- $one_result_found = true;
408
- }
409
-
410
- $locations[ $key ]['results'] = $results;
411
- }
412
-
413
- if ( ! $one_result_found ) {
414
- return array();
415
- }
416
-
417
- return $locations;
418
- }
419
  }
1
+ <?php
2
+ /**
3
+ * Class SBY_Feed_Locator
4
+ *
5
+ * Locates feeds on the site and logs information about them in the database.
6
+ *
7
+ * @since 1.14
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ die( '-1' );
12
+ }
13
+
14
+ class SBY_Feed_Locator
15
+ {
16
+ private $feed_details;
17
+
18
+ private $expiration_time;
19
+
20
+ private $matching_entries;
21
+
22
+ public function __construct( $feed_details ) {
23
+ /**
24
+ * Example of how $feed_details is structured
25
+ *
26
+ * $feed_details = array(
27
+ * 'feed_id' => $transient_name,
28
+ * 'atts' => $atts,
29
+ * 'location' => array(
30
+ * 'post_id' => get_the_ID(),
31
+ * 'html' => 'unknown'
32
+ * )
33
+ * );
34
+ */
35
+ $this->feed_details = $feed_details;
36
+
37
+ $this->matching_entries = array();
38
+
39
+ $this->expiration_time = time() - 2 * WEEK_IN_SECONDS;
40
+ }
41
+
42
+ /**
43
+ * Returns records that match the post ID and feed ID
44
+ * of the feed being located
45
+ *
46
+ * @return array
47
+ *
48
+ * @since 1.14
49
+ */
50
+ public function retrieve_matching_entries() {
51
+ global $wpdb;
52
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
53
+
54
+ $results = $wpdb->get_results( $wpdb->prepare("
55
+ SELECT *
56
+ FROM $feed_locator_table_name
57
+ WHERE post_id = %d
58
+ AND feed_id = %s", $this->feed_details['location']['post_id'], $this->feed_details['feed_id'] ),ARRAY_A );
59
+
60
+ return $results;
61
+ }
62
+
63
+ /**
64
+ * Add feed being located to the database
65
+ *
66
+ * @since 1.14
67
+ */
68
+ public function insert_entry() {
69
+ global $wpdb;
70
+
71
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
72
+
73
+ $affected = $wpdb->query( $wpdb->prepare( "INSERT INTO $feed_locator_table_name
74
+ (feed_id,
75
+ post_id,
76
+ html_location,
77
+ shortcode_atts,
78
+ last_update)
79
+ VALUES (
80
+ %s,
81
+ %d,
82
+ %s,
83
+ %s,
84
+ %s);",
85
+ $this->feed_details['feed_id'],
86
+ $this->feed_details['location']['post_id'],
87
+ $this->feed_details['location']['html'],
88
+ sby_json_encode( $this->feed_details['atts'] ),
89
+ date( 'Y-m-d H:i:s' ) ) );
90
+ }
91
+
92
+ /**
93
+ * Update a record based on the existing "id" column. Location can change
94
+ * from "unknown" to one of footer, content, header, or sidebar.
95
+ *
96
+ * @param $id
97
+ * @param $location
98
+ *
99
+ * @since 1.14
100
+ */
101
+ public function update_entry( $id, $location ) {
102
+ global $wpdb;
103
+
104
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
105
+
106
+ $query = $wpdb->query( $wpdb->prepare( "
107
+ UPDATE $feed_locator_table_name
108
+ SET last_update = %s, html_location = %s
109
+ WHERE id = %d;", date( 'Y-m-d H:i:s' ), $location, $id ) );
110
+ }
111
+
112
+ /**
113
+ * Processes a feed being located based on whether or not the record
114
+ * exists as well as whether or not an unknown location needs to be
115
+ * updated.
116
+ *
117
+ * @since 1.14
118
+ */
119
+ public function add_or_update_entry() {
120
+ if ( empty( $this->feed_details['feed_id'] ) ) {
121
+ return;
122
+ }
123
+
124
+ $this->matching_entries = $this->retrieve_matching_entries();
125
+
126
+ if ( empty( $this->matching_entries ) ) {
127
+ $this->insert_entry();
128
+ } else {
129
+ $matching_indices = array();
130
+ $matched_location = false;
131
+ $non_unknown_match = false;
132
+ $unknown_match = false;
133
+
134
+ foreach ( $this->matching_entries as $index => $matching_entry ) {
135
+ $details_atts = is_array( $this->feed_details['atts'] ) ? $this->feed_details['atts'] : array();
136
+ $matching_atts = json_decode( $matching_entry['shortcode_atts'], true );
137
+ if ( ! is_array( $matching_atts ) ) {
138
+ $matching_atts = array();
139
+ }
140
+ $atts_diff = array_diff( $matching_atts, $details_atts ); // determines if the shortcode settings match the shortcode settings of an existing feed
141
+ if ( empty( $atts_diff ) ) {
142
+ $matching_indices[] = $matching_entry['id'];
143
+ if ( $matching_entry['html_location'] === $this->feed_details['location']['html'] ) {
144
+ $matched_location = $index;
145
+ $this->update_entry( $matching_entry['id'], $matching_entry['html_location'] );
146
+ }
147
+ if ( $matching_entry['html_location'] !== 'unknown' ) {
148
+ $non_unknown_match = $index;
149
+ } else {
150
+ $unknown_match = $index;
151
+ }
152
+ }
153
+ }
154
+
155
+ if ( false === $matched_location ) {
156
+ // if there is no matched location, there is only one feed on the page, and the feed being checked has an unknown location, update the known location
157
+ if ( count( $matching_indices ) === 1
158
+ && $this->feed_details['location']['html'] === 'unknown'
159
+ && false !== $non_unknown_match ) {
160
+ $this->update_entry( $this->matching_entries[ $non_unknown_match ]['id'], $this->matching_entries[ $non_unknown_match ]['html_location'] );
161
+ } else {
162
+ if ( $this->feed_details['location']['html'] !== 'unknown'
163
+ && false !== $unknown_match ) {
164
+ $this->update_entry( $this->matching_entries[ $unknown_match ]['id'], $this->feed_details['location']['html'] );
165
+ } else {
166
+ $this->insert_entry();
167
+ }
168
+
169
+ }
170
+ }
171
+
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Old feeds are only detected once a day to keep load on the server low.
177
+ *
178
+ * @return bool
179
+ *
180
+ * @since 1.14
181
+ */
182
+ public static function should_clear_old_locations() {
183
+ $sby_statuses_option = get_option( 'sby_statuses', array() );
184
+ $last_old_feed_check = isset( $sby_statuses_option['feed_locator']['last_check'] ) ? $sby_statuses_option['feed_locator']['last_check'] : 0;
185
+
186
+ return $last_old_feed_check < time() - DAY_IN_SECONDS;
187
+ }
188
+
189
+ /**
190
+ * Old feeds are removed if they haven't been updated in two weeks.
191
+ *
192
+ * @since 1.14
193
+ */
194
+ public static function delete_old_locations() {
195
+ global $wpdb;
196
+
197
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
198
+ $two_weeks_ago = date( 'Y-m-d H:i:s', time() - 2 * WEEK_IN_SECONDS );
199
+
200
+ $affected = $wpdb->query( $wpdb->prepare(
201
+ "DELETE FROM $feed_locator_table_name WHERE last_update < %s;", $two_weeks_ago ) );
202
+
203
+ $sby_statuses_option = get_option( 'sby_statuses', array() );
204
+ $sby_statuses_option['feed_locator']['last_check'] = time();
205
+ if ( ! isset( $sby_statuses_option['feed_locator']['initialized'] ) ) {
206
+ $sby_statuses_option['feed_locator']['initialized'] = time();
207
+ }
208
+
209
+ update_option( 'sby_statuses', $sby_statuses_option, true );
210
+ }
211
+
212
+ /**
213
+ * Feeds are located with the page load randomly (5% or 1/30 loads)
214
+ * to decrease load on the server.
215
+ *
216
+ * If the locating just started (within 5 minutes) it is run more often
217
+ * to collect feed locations quickly.
218
+ *
219
+ * @return bool
220
+ *
221
+ * @since 1.14
222
+ */
223
+ public static function should_do_locating() {
224
+ $sby_statuses_option = get_option( 'sby_statuses', array() );
225
+ if ( isset( $sby_statuses_option['feed_locator']['initialized'] )
226
+ && $sby_statuses_option['feed_locator']['initialized'] < (time() - 300) ) {
227
+ $should_do_locating = rand( 1, 10 ) === 10;
228
+ } else {
229
+ $should_do_locating = rand( 1, 30 ) === 30;
230
+ }
231
+ $should_do_locating = apply_filters( 'sby_should_do_locating', $should_do_locating );
232
+
233
+ return $should_do_locating;
234
+ }
235
+
236
+ /**
237
+ * Simliar to the should_do_locating method but will add an additional
238
+ * database query to see if there is a feed with an unknown location that
239
+ * matches the details of the feed in question.
240
+ *
241
+ * @param $feed_id
242
+ * @param $post_id
243
+ *
244
+ * @return bool
245
+ *
246
+ * @since 1.14
247
+ */
248
+ public static function should_do_ajax_locating( $feed_id, $post_id ) {
249
+
250
+ $should_do_locating = rand( 1, 50 ) === 50;
251
+
252
+ $should_do_locating = apply_filters( 'sby_should_do_ajax_locating', $should_do_locating );
253
+
254
+ return $should_do_locating;
255
+ }
256
+
257
+ /**
258
+ * Feeds are located with the page load randomly (1/30 loads)
259
+ * to decrease load on the server.
260
+ *
261
+ * If the locating just started (within 5 minutes) it is run more often
262
+ * to collect feed locations quickly.
263
+ *
264
+ * @param $feed_id
265
+ * @param $post_id
266
+ *
267
+ * @return bool
268
+ *
269
+ * @since 1.14
270
+ */
271
+ public static function entries_need_locating( $feed_id, $post_id ) {
272
+ global $wpdb;
273
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
274
+
275
+ $one_day_ago = date( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS );
276
+
277
+ $results = $wpdb->get_results( $wpdb->prepare("
278
+ SELECT id
279
+ FROM $feed_locator_table_name
280
+ WHERE html_location = 'unknown'
281
+ AND last_update < %s
282
+ AND feed_id = %s
283
+ AND post_id = %d
284
+ LIMIT 1;", $one_day_ago, $feed_id, $post_id ),ARRAY_A );
285
+
286
+ return isset( $results[0] );
287
+ }
288
+
289
+ /**
290
+ * A custom table stores locations
291
+ *
292
+ * @since 1.14
293
+ */
294
+ public static function create_table() {
295
+ global $wpdb;
296
+
297
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
298
+
299
+ if ( $wpdb->get_var( "show tables like '$feed_locator_table_name'" ) != $feed_locator_table_name ) {
300
+ $sql = "CREATE TABLE " . $feed_locator_table_name . " (
301
+ id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
302
+ feed_id VARCHAR(50) DEFAULT '' NOT NULL,
303
+ post_id BIGINT(20) UNSIGNED NOT NULL,
304
+ html_location VARCHAR(50) DEFAULT 'unknown' NOT NULL,
305
+ shortcode_atts LONGTEXT NOT NULL,
306
+ last_update DATETIME
307
+ );";
308
+ $wpdb->query( $sql );
309
+ }
310
+ $error = $wpdb->last_error;
311
+ $query = $wpdb->last_query;
312
+ $had_error = false;
313
+ if ( $wpdb->get_var( "show tables like '$feed_locator_table_name'" ) != $feed_locator_table_name ) {
314
+ $had_error = true;
315
+ }
316
+
317
+ if ( ! $had_error ) {
318
+ $wpdb->query( "ALTER TABLE $feed_locator_table_name ADD INDEX feed_id (feed_id)" );
319
+ $wpdb->query( "ALTER TABLE $feed_locator_table_name ADD INDEX post_id (post_id)" );
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Counts the number of unique feeds in the database.
325
+ *
326
+ * @return int
327
+ *
328
+ * @since 1.14
329
+ */
330
+ public static function count_unique() {
331
+ global $wpdb;
332
+
333
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
334
+ $results_content = $wpdb->get_results( "
335
+ SELECT COUNT(*) AS num_entries
336
+ FROM $feed_locator_table_name
337
+ WHERE html_location = 'content'
338
+ ", ARRAY_A );
339
+
340
+
341
+ $results_other = $wpdb->get_results( "
342
+ SELECT COUNT(*) AS num_entries
343
+ FROM $feed_locator_table_name
344
+ WHERE html_location != 'content'
345
+ AND html_location != 'unknown'
346
+ GROUP BY feed_id
347
+ ", ARRAY_A );
348
+
349
+ $total = 0;
350
+ if ( isset( $results_content[0]['num_entries'] ) ) {
351
+ $total += (int)$results_content[0]['num_entries'];
352
+ }
353
+ if ( isset( $results_other[0]['num_entries'] ) ) {
354
+ $total += (int)$results_other[0]['num_entries'];
355
+ }
356
+
357
+ return $total;
358
+ }
359
+
360
+ /**
361
+ * Creates a summary of the located feeds in an array
362
+ *
363
+ * @return array
364
+ *
365
+ * @since 1.14
366
+ */
367
+ public static function summary() {
368
+ global $wpdb;
369
+
370
+ $feed_locator_table_name = esc_sql( $wpdb->prefix . SBY_FEED_LOCATOR );
371
+
372
+ $locations = array(
373
+ array(
374
+ 'label' => __( 'Content', 'feeds-for-youtube' ),
375
+ 'html_locations' => array( 'content', 'unknown' )
376
+ ),
377
+ array(
378
+ 'label' => __( 'Header', 'feeds-for-youtube' ),
379
+ 'html_locations' => array( 'header' ),
380
+ 'group_by' => 'feed_id'
381
+ ),
382
+ array(
383
+ 'label' => __( 'Sidebar', 'feeds-for-youtube' ),
384
+ 'html_locations' => array( 'sidebar' ),
385
+ 'group_by' => 'feed_id'
386
+ ),
387
+ array(
388
+ 'label' => __( 'Footer', 'feeds-for-youtube' ),
389
+ 'html_locations' => array( 'footer' ),
390
+ 'group_by' => 'feed_id'
391
+ )
392
+ );
393
+
394
+ $one_result_found = false;
395
+
396
+ foreach ( $locations as $key => $location ) {
397
+ $in = implode( "', '", $location['html_locations'] );
398
+ $group_by = isset( $location['group_by'] ) ? "GROUP BY " . $location['group_by'] : "";
399
+ $results = $wpdb->get_results("
400
+ SELECT *
401
+ FROM $feed_locator_table_name
402
+ WHERE html_location IN ('$in')
403
+ $group_by
404
+ ORDER BY last_update ASC",ARRAY_A );
405
+
406
+ if ( isset( $results[0] ) ) {
407
+ $one_result_found = true;
408
+ }
409
+
410
+ $locations[ $key ]['results'] = $results;
411
+ }
412
+
413
+ if ( ! $one_result_found ) {
414
+ return array();
415
+ }
416
+
417
+ return $locations;
418
+ }
419
  }
inc/class-sby-feed.php CHANGED
@@ -1,1644 +1,1648 @@
1
- <?php
2
-
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- die( '-1' );
5
- }
6
-
7
- class SBY_Feed
8
- {
9
- /**
10
- * @var string
11
- */
12
- protected $regular_feed_transient_name;
13
-
14
- /**
15
- * @var string
16
- */
17
- private $header_transient_name;
18
-
19
- /**
20
- * @var string
21
- */
22
- private $backup_feed_transient_name;
23
-
24
- /**
25
- * @var string
26
- */
27
- private $backup_header_transient_name;
28
-
29
- protected $channels_data;
30
-
31
- /**
32
- * @var array
33
- */
34
- private $post_data;
35
-
36
- /**
37
- * @var
38
- */
39
- private $header_data;
40
-
41
- /**
42
- * @var array
43
- */
44
- protected $next_pages;
45
-
46
- /**
47
- * @var array
48
- */
49
- private $transient_atts;
50
-
51
- /**
52
- * @var int
53
- */
54
- private $last_retrieve;
55
-
56
- /**
57
- * @var bool
58
- */
59
- private $should_paginate;
60
-
61
- /**
62
- * @var int
63
- */
64
- private $num_api_calls;
65
-
66
- /**
67
- * @var int
68
- */
69
- private $max_api_calls;
70
-
71
- /**
72
- * @var array
73
- */
74
- protected $image_ids_post_set;
75
-
76
- /**
77
- * @var array
78
- */
79
- public $post_ids_with_no_details;
80
-
81
- /**
82
- * @var bool
83
- */
84
- private $should_use_backup;
85
-
86
- /**
87
- * @var array
88
- */
89
- private $report;
90
-
91
- private $successful_video_api_request_made;
92
-
93
- private $do_page_cache_all;
94
-
95
- /**
96
- * SBY_Feed constructor.
97
- *
98
- * @param string $transient_name ID of this feed
99
- * generated in the SBY_Settings class
100
- */
101
- public function __construct( $transient_name ) {
102
- $this->regular_feed_transient_name = $transient_name;
103
- $this->backup_feed_transient_name = SBY_BACKUP_PREFIX . $transient_name;
104
-
105
- $sby_header_transient_name = str_replace( 'sby_', 'sby_header_', $transient_name );
106
- $sby_header_transient_name = substr($sby_header_transient_name, 0, 44);
107
- $this->header_transient_name = $sby_header_transient_name;
108
- $this->backup_header_transient_name = SBY_BACKUP_PREFIX . $sby_header_transient_name;
109
-
110
- $this->channels_data = array();
111
-
112
- $this->post_data = array();
113
- $this->next_pages = array();
114
- $this->should_paginate = true;
115
-
116
- // this is a count of how many api calls have been made for each feed
117
- // type and term.
118
- // By default the limit is 10
119
- $this->num_api_calls = 0;
120
- $this->max_api_calls = apply_filters( 'sby_max_concurrent_api_calls', 10 );
121
- $this->should_use_backup = false;
122
-
123
- // used for errors and the sby_debug report
124
- $this->report = array();
125
- $this->successful_video_api_request_made = false;
126
- $this->post_ids_with_no_details = array();
127
- $this->do_page_cache_all = false;
128
- }
129
-
130
- /**
131
- * @return array
132
- *
133
- * @since 1.0
134
- */
135
- public function get_post_data() {
136
- return $this->post_data;
137
- }
138
-
139
- /**
140
- * @return array
141
- *
142
- * @since 1.0
143
- */
144
- public function set_post_data( $post_data ) {
145
- $this->post_data = $post_data;
146
- }
147
-
148
- public function get_misc_data( $feed_id, $posts ) {
149
- return array();
150
- }
151
-
152
- /**
153
- * @return array
154
- *
155
- * @since 1.0
156
- */
157
- public function get_next_pages() {
158
- return $this->next_pages;
159
- }
160
-
161
- /**
162
- * Checks the database option related the transient expiration
163
- * to ensure it will be available when the page loads
164
- *
165
- * @return bool
166
- *
167
- * @since 2.0/4.0
168
- */
169
- public function regular_cache_exists() {
170
- //Check whether the cache transient exists in the database and is available for more than one more minute
171
- $transient_exists = get_transient( $this->regular_feed_transient_name );
172
-
173
- return $transient_exists;
174
- }
175
-
176
- /**
177
- * Checks the database option related the header transient
178
- * expiration to ensure it will be available when the page loads
179
- *
180
- * @return bool
181
- *
182
- * @since 1.0
183
- */
184
- public function regular_header_cache_exists() {
185
- $header_transient = get_transient( $this->header_transient_name );
186
-
187
- return $header_transient;
188
- }
189
-
190
- public function get_channel_cache( $channel, $force_get_cache = false ) {
191
- if ( $this->is_pageable() && ! $force_get_cache ) {
192
- return false;
193
- }
194
-
195
- $maybe_cache = get_option( SBY_CHANNEL_CACHE_PREFIX . $channel );
196
- if ( $maybe_cache !== false ) {
197
- $maybe_cache = json_decode( $maybe_cache, true );
198
- }
199
-
200
- return $maybe_cache;
201
- }
202
-
203
- public function set_channel_cache( $channel, $cache ) {
204
- if ( is_array( $cache ) ) {
205
- $cache = wp_json_encode( $cache );
206
- }
207
-
208
- update_option( SBY_CHANNEL_CACHE_PREFIX . $channel, $cache, false );
209
- }
210
-
211
- /**
212
- * @return bool
213
- *
214
- * @since 1.0
215
- */
216
- public function should_use_backup() {
217
- return $this->should_use_backup || empty( $this->post_data );
218
- }
219
-
220
- /**
221
- * The header is only displayed when the setting is enabled and
222
- * an account has been connected
223
- *
224
- * Overwritten in the Pro version
225
- *
226
- * @param array $settings settings specific to this feed
227
- * @param array $feed_types_and_terms organized settings related to feed data
228
- * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
229
- *
230
- * @return bool
231
- *
232
- * @since 1.0
233
- */
234
- public function need_header( $settings, $feed_types_and_terms ) {
235
- $showheader = ($settings['showheader'] === 'on' || $settings['showheader'] === 'true' || $settings['showheader'] === true);
236
- return ($showheader && isset( $feed_types_and_terms['channels'] ));
237
- }
238
-
239
- /**
240
- * Use the transient name to retrieve cached data for header
241
- *
242
- * @since 1.0
243
- */
244
- public function set_header_data_from_cache() {
245
- $header_cache = get_transient( $this->header_transient_name );
246
-
247
- $header_cache = json_decode( $header_cache, true );
248
-
249
- if ( ! empty( $header_cache ) ) {
250
- $this->header_data = $header_cache;
251
- }
252
- }
253
-
254
- public function set_header_data( $header_data ) {
255
- $this->header_data = $header_data;
256
- }
257
-
258
- /**
259
- * @since 1.0
260
- */
261
- public function get_header_data() {
262
- return $this->header_data;
263
- }
264
-
265
- /**
266
- * Sets the post data, pagination data, shortcode atts used (cron cache),
267
- * and timestamp of last retrieval from transient (cron cache)
268
- *
269
- * @param array $atts available for cron caching
270
- *
271
- * @since 1.0
272
- */
273
- public function set_post_data_from_cache( $atts = array() ) {
274
- $transient_data = get_transient( $this->regular_feed_transient_name );
275
-
276
- $transient_data = json_decode( $transient_data, true );
277
-
278
- if ( $transient_data ) {
279
- $post_data = isset( $transient_data['data'] ) ? $transient_data['data'] : array();
280
- $this->post_data = $post_data;
281
- $this->next_pages = isset( $transient_data['pagination'] ) ? $transient_data['pagination'] : array();
282
-
283
- if ( isset( $transient_data['atts'] ) ) {
284
- $this->transient_atts = $transient_data['atts'];
285
- $this->last_retrieve = $transient_data['last_retrieve'];
286
- }
287
- }
288
- }
289
-
290
- /**
291
- * Sets post data from a permanent database backup of feed
292
- * if it was created
293
- *
294
- * @since 1.0
295
- */
296
- public function maybe_set_post_data_from_backup() {
297
- $args = array(
298
- 'post_type' => SBY_CPT,
299
- 'post_status' => array( 'publish', 'pending', 'draft' ),
300
- 'orderby' => 'date',
301
- 'order' => 'DESC',
302
- 'posts_per_page' => 50,
303
- 'meta_query' => array(
304
- array(
305
- 'value' => sby_strip_after_hash( $this->regular_feed_transient_name ),
306
- 'key' => 'sby_feed_id'
307
- )
308
- )
309
- );
310
- $feed_videos = new WP_Query( $args );
311
-
312
- if ( $feed_videos->have_posts() ) {
313
- $posts = array();
314
- while ( $feed_videos->have_posts() ) {
315
- $feed_videos->the_post();
316
- $json = get_post_meta( get_the_ID(), 'sby_json', true );
317
-
318
- if ( $json ) {
319
- $posts[] = json_decode( $json, true );
320
- }
321
- }
322
-
323
- wp_reset_postdata();
324
-
325
- $this->post_data = $posts;
326
- return true;
327
- } else {
328
- $this->add_report( 'no backup post data found' );
329
- wp_reset_postdata();
330
-
331
- return false;
332
- }
333
- }
334
-
335
- /**
336
- * Sets header data from a permanent database backup of feed
337
- * if it was created
338
- *
339
- * @since 1.0
340
- */
341
- public function maybe_set_header_data_from_backup() {
342
- $backup_header_data = get_option( $this->backup_header_transient_name, false );
343
-
344
- if ( ! empty( $backup_header_data ) ) {
345
- $backup_header_data = json_decode( $backup_header_data, true );
346
- $this->header_data = $backup_header_data;
347
-
348
- return true;
349
- } else {
350
- $this->add_report( 'no backup header data found' );
351
-
352
- return false;
353
- }
354
- }
355
-
356
- /**
357
- * Returns recorded image IDs for this post set
358
- * for use with image resizing
359
- *
360
- * @return array
361
- *
362
- * @since 1.0
363
- */
364
- public function get_image_ids_post_set() {
365
- return $this->image_ids_post_set;
366
- }
367
-
368
- /**
369
- * Cron caching needs additional data saved in the transient
370
- * to work properly. This function checks to make sure it's present
371
- *
372
- * @return bool
373
- *
374
- * @since 1.0
375
- */
376
- public function need_to_start_cron_job() {
377
- return (( ! empty( $this->post_data ) && ! isset( $this->transient_atts )) || empty( $this->post_data ));
378
- }
379
-
380
- /**
381
- * Checks to see if there are enough posts available to create
382
- * the current page of the feed
383
- *
384
- * @param int $num
385
- * @param int $offset
386
- *
387
- * @return bool
388
- *
389
- * @since 1.0
390
- */
391
- public function need_posts( $num, $offset = 0 ) {
392
- $num_existing_posts = is_array( $this->post_data ) ? count( $this->post_data ) : 0;
393
- $num_needed_for_page = (int)$num + (int)$offset;
394
-
395
- ($num_existing_posts < $num_needed_for_page) ? $this->add_report( 'need more posts' ) : $this->add_report( 'have enough posts' );
396
-
397
- return ($num_existing_posts < $num_needed_for_page);
398
- }
399
-
400
- /**
401
- * Checks to see if there are additional pages available for any of the
402
- * accounts in the feed and that the max conccurrent api request limit
403
- * has not been reached
404
- *
405
- * @return bool
406
- *
407
- * @since 1.0
408
- */
409
- public function can_get_more_posts() {
410
- $one_type_and_term_has_more_ages = $this->next_pages !== false;
411
- $max_concurrent_api_calls_not_met = $this->num_api_calls < $this->max_api_calls;
412
- $max_concurrent_api_calls_not_met ? $this->add_report( 'max conccurrent requests not met' ) : $this->add_report( 'max concurrent met' );
413
- $one_type_and_term_has_more_ages ? $this->add_report( 'more pages available' ) : $this->add_report( 'no next page' );
414
-
415
- return ($one_type_and_term_has_more_ages && $max_concurrent_api_calls_not_met);
416
- }
417
-
418
- public function get_play_list_for_term( $type, $term, $connected_account_for_term, $params ) {
419
-
420
- if ( $type === 'search' || $type === 'live' ) {
421
- return false;
422
- }
423
- $existing_channel_cache = $this->get_channel_cache( $term );
424
-
425
- if ( $existing_channel_cache ) {
426
- $this->channels_data[ $term ] = $existing_channel_cache;
427
- }
428
-
429
- if ( empty( $this->channels_data[ $term ] ) ) {
430
- if ( $connected_account_for_term['expires'] < time() + 5 ) {
431
- $error_message = '<p><b>' . __( 'Reconnect to YouTube to show this feed.', 'custom-facebook-feed' ) . '</b></p>';
432
- $error_message .= '<p>' . __( 'To create a new feed, first connect to YouTube using the "Connect to YouTube to Create a Feed" button on the settings page and connect any account.', SBY_TEXT_DOMAIN ) . '</p>';
433
-
434
- if ( current_user_can( 'manage_youtube_feed_options' ) ) {
435
- $error_message .= '<a href="' . admin_url( 'admin.php?page=youtube-feed' ) . '" target="blank" rel="noopener nofollow">' . __( 'Reconnect in the YouTube Feed Settings Area' ) . '</a>';
436
- }
437
- global $sby_posts_manager;
438
-
439
- $sby_posts_manager->add_frontend_error( 'accesstoken', $error_message );
440
- $sby_posts_manager->add_error( 'accesstoken', array( 'Trying to connect a new account', $error_message ) );
441
-
442
- return false;
443
- }
444
- $channel_data = array();
445
- $api_connect_channels = $this->make_api_connection( $connected_account_for_term, 'channels', $params );
446
-
447
- $this->add_report( 'channel api call made for ' . $term . ' - ' . $type );
448
-
449
- $api_connect_channels->connect();
450
- if ( ! $api_connect_channels->is_wp_error() && ! $api_connect_channels->is_youtube_error() ) {
451
- $channel_data = $api_connect_channels->get_data();
452
- $channel_id = SBY_Parse::get_channel_id( $channel_data );
453
- $this->set_channel_cache( $channel_id, $channel_data );
454
-
455
- if ( isset( $params['channel_name'] ) ) {
456
- sby_set_channel_id_from_channel_name( $params['channel_name'], $channel_id );
457
- $this->set_channel_cache( $params['channel_name'], $channel_data );
458
- }
459
-
460
- $params = array( 'channel_id' => $channel_id );
461
- $this->channels_data[ $channel_id ] = $channel_data;
462
- $this->channels_data[ $term ] = $channel_data;
463
- } else {
464
- if ( ! $api_connect_channels->is_wp_error() ) {
465
- $return = SBY_API_Connect::handle_youtube_error( $api_connect_channels->get_data(), $connected_account_for_term );
466
- if ( $return && isset( $return['access_token'] ) ) {
467
- $connected_account_for_term['access_token'] = $return['access_token'];
468
- $connected_accounts_for_feed[ $term ]['access_token'] = $return['access_token'];
469
- $connected_account_for_term['expires'] = $return['expires_in'] + time();
470
- $connected_accounts_for_feed[ $term ]['expires'] = $return['expires_in'] + time();
471
-
472
- sby_update_or_connect_account( $connected_account_for_term );
473
- $this->add_report( 'refreshing access token for ' . $connected_account_for_term['channel_id'] );
474
-
475
- $sby_api_connect_channel = $this->make_api_connection( $connected_account_for_term, 'channels', $params );
476
- $sby_api_connect_channel->connect();
477
- if ( ! $sby_api_connect_channel->is_youtube_error() ) {
478
- $channel_data = $sby_api_connect_channel->get_data();
479
- $channel_id = SBY_Parse::get_channel_id( $channel_data );
480
- $this->set_channel_cache( $channel_id, $channel_data );
481
-
482
- if ( isset( $params['channel_name'] ) ) {
483
- sby_set_channel_id_from_channel_name( $params['channel_name'], $channel_id );
484
- $this->set_channel_cache( $params['channel_name'], $channel_data );
485
- }
486
-
487
- $this->channels_data[ $channel_id ] = $channel_data;
488
- $this->channels_data[ $term ] = $channel_data;
489
-
490
- }
491
- } else {
492
- $this->add_report( 'error connecting to channel' );
493
- }
494
- } else {
495
- $api_connect_channels->handle_wp_remote_get_error( $api_connect_channels->get_data() );
496
- }
497
- }
498
- }
499
-
500
- $playlist = isset( $this->channels_data[ $term ]['items'][0]['contentDetails']['relatedPlaylists']['uploads'] ) ? $this->channels_data[ $term ]['items'][0]['contentDetails']['relatedPlaylists']['uploads'] : false;
501
-
502
- return $playlist;
503
- }
504
-
505
- public function maybe_refresh_token( $term, $connected_account_for_term ) {
506
- return $connected_account_for_term;
507
- }
508
-
509
- public function is_efficient_type( $type ) {
510
- return true;
511
- }
512
-
513
- public function requires_workaround_connection( $type ) {
514
- return false;
515
- }
516
-
517
- public function make_workaround_connection( $connected_account_for_term, $type, $params ) {
518
- return $this->make_api_connection( $connected_account_for_term, $type, $params );
519
- }
520
-
521
-
522
- /**
523
- * Appends one filtered API request worth of posts for each feed term
524
- *
525
- * @param $settings
526
- * @param array $feed_types_and_terms organized settings related to feed data
527
- * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
528
- * @param array $connected_accounts_for_feed connected account data for the
529
- * feed types and terms
530
- *
531
- * @since 1.0
532
- */
533
-
534
- public function add_remote_posts( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
535
- $new_post_sets = array();
536
- $next_pages = $this->next_pages;
537
- global $sby_posts_manager;
538
- $api_requests_delayed = $sby_posts_manager->are_current_api_request_delays();
539
-
540
- /**
541
- * Number of posts to retrieve in each API call
542
- *
543
- * @param int Minimum number of posts needed in each API request
544
- * @param array $settings Settings for this feed
545
- *
546
- * @since 1.0
547
- */
548
- $num = apply_filters( 'sby_num_in_request', (int)$settings['minnum'], $settings );
549
-
550
- $params = array(
551
- 'num' => $num
552
- );
553
-
554
- $one_successful_connection = false;
555
- $next_page_found = false;
556
- $one_api_request_delayed = false;
557
-
558
-
559
-
560
- foreach ( $feed_types_and_terms as $type => $terms ) {
561
- if ( is_array( $terms ) && count( $terms ) > 5 ) {
562
- shuffle( $terms );
563
- }
564
- foreach ( $terms as $term_and_params ) {
565
-
566
- $term = $term_and_params['term'];
567
- $params = array_merge( $params, $term_and_params['params'] );
568
-
569
- $connected_accounts_for_feed[ $term ] = $this->maybe_refresh_token( $term, $connected_accounts_for_feed[ $term ] );
570
- $connected_account_for_term = $connected_accounts_for_feed[ $term ];
571
-
572
- $play_list = $this->get_play_list_for_term( $type, $term, $connected_account_for_term, $params );
573
-
574
- if ( ! empty( $next_pages[ $term . '_' . $type ] ) ) {
575
- $params['nextPageToken'] = $next_pages[ $term . '_' . $type ];
576
- }
577
-
578
- if ( $this->is_pageable() ) {
579
- $this->add_remote_pageable_posts( $settings, $feed_types_and_terms, $connected_accounts_for_feed );
580
- } else {
581
- $this->add_remote_non_pageable( $settings, $feed_types_and_terms, $connected_accounts_for_feed );
582
- }
583
-
584
- if ( ! $this->is_efficient_type( $type ) && $this->is_pageable() ) {
585
-
586
- if ( $this->requires_workaround_connection( $type ) ) {
587
- $api_connect_playlist_items = $this->make_workaround_connection( $connected_account_for_term, $type, $params );
588
- $this->add_report( 'Workaround API call made for ' . $term );
589
-
590
- } else {
591
- if ( $play_list ) {
592
- $params['playlist_id'] = $play_list;
593
- $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, 'playlistItems', $params );
594
- } else {
595
- $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, $type, $params );
596
- }
597
-
598
- $api_connect_playlist_items->connect();
599
- $this->add_report( 'API call made for ' . $term );
600
- }
601
-
602
-
603
- if ( ! $api_connect_playlist_items->is_wp_error() && ! $api_connect_playlist_items->is_youtube_error() ) {
604
- $one_successful_connection = true;
605
- $data = $api_connect_playlist_items->get_data();
606
-
607
- if ( isset( $data['items'][0] ) ) {
608
- $post_set = $this->filter_posts( $data['items'], $settings );
609
-
610
- $this->successful_video_api_request_made = true;
611
-
612
- $new_post_sets[] = $post_set;
613
- }
614
-
615
- $next_page = $api_connect_playlist_items->get_next_page( $params );
616
- $report = is_array( $next_page ) ? implode( ',', $next_page ) : $next_page;
617
- $this->add_report( 'Next Page ' . $report );
618
-
619
-
620
- if ( ! empty( $next_page ) ) {
621
- $next_pages[ $term . '_' . $type ] = $next_page;
622
- $next_page_found = true;
623
- } else {
624
- $next_pages[ $term . '_' . $type ] = false;
625
- }
626
- }
627
-
628
-
629
- $this->num_api_calls++;
630
-
631
- } else {
632
-
633
- if ( ! $this->is_pageable() && (int)self::get_channel_status( $term ) !== 1 ) {
634
- self::update_channel_status( $term, 1 );
635
- $this->do_page_cache_all = true;
636
- $play_list = $this->get_play_list_for_term( $type, $term, $connected_account_for_term, $params );
637
-
638
- $channel_id = isset( $this->channels_data[ $term ] ) ? SBY_Parse::get_channel_id( $this->channels_data[ $term ] ) : '';
639
- $params['channel_id'] = $channel_id;
640
- $params['num'] = 50;
641
-
642
- if ( $play_list ) {
643
-
644
- $params['playlist_id'] = $play_list;
645
- if ( ! empty( $next_pages[ $term . '_' . $type ] ) && $next_pages[ $term . '_' . $type ] !== 'rss' ) {
646
- $params['nextPageToken'] = $next_pages[ $term . '_' . $type ];
647
- }
648
-
649
- self::update_channel_status( $term, 1 );
650
- $this->do_page_cache_all = true;
651
- $this->add_report( 'using API request to get first 50 videos' );
652
-
653
- $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, 'playlistItems', $params );
654
-
655
- $api_connect_playlist_items->connect();
656
-
657
- if ( ! $api_connect_playlist_items->is_wp_error() && ! $api_connect_playlist_items->is_youtube_error() ) {
658
- $one_successful_connection = true;
659
- $data = $api_connect_playlist_items->get_data();
660
-
661
- if ( isset( $data['items'][0] ) ) {
662
- $post_set = $this->filter_posts( $data['items'], $settings );
663
-
664
- $this->successful_video_api_request_made = true;
665
-
666
- $new_post_sets[] = $post_set;
667
- }
668
-
669
- $next_pages[ $term . '_' . $type ] = false;
670
- }
671
- } else {
672
- $this->add_report( 'no first playlist' );
673
- }
674
-
675
- } elseif ( ! $this->is_pageable()
676
- && isset( $params['channel_id'] )
677
- && (! isset( $next_pages[ $term . '_' . $type ] ) || $next_pages[ $term . '_' . $type ] !== 'rss') ) {
678
-
679
- $rss_connect_playlist_items = new SBY_RSS_Connect( 'playlistItems', $params );
680
- $this->add_report( 'RSS call made for ' . $term );
681
-
682
- $rss_connect_playlist_items->connect();
683
-
684
- $one_successful_connection = true;
685
-
686
- $data = $rss_connect_playlist_items->get_data();
687
-
688
- if ( isset( $data[0] ) ) {
689
- $data = array(
690
- 'items' => $data
691
- );
692
- $post_set = $this->filter_posts( $data['items'], $settings );
693
-
694
- $this->successful_video_api_request_made = true;
695
-
696
- if ( count( $post_set ) > 14 ) {
697
- if ( (int)self::get_channel_status( $term ) !== 1 ) {
698
- $next_pages[ $term . '_' . $type ] = 'rss';
699
- $next_page_found = true;
700
- } else {
701
- $this->add_report( 'RSS update only for ' . $term );
702
- $post_set = $this->merge_cached_posts( $post_set, $term );
703
- $next_pages[ $term . '_' . $type ] = false;
704
- }
705
- } else {
706
- $next_pages[ $term . '_' . $type ] = false;
707
- }
708
-
709
- $new_post_sets[] = $post_set;
710
-
711
- }
712
- } elseif ( isset( $connected_account_for_term['rss_only'] ) ) {
713
- $rss_connect_playlist_items = new SBY_RSS_Connect( 'playlistItems', $params );
714
- $this->add_report( 'RSS Only call made for ' . $term );
715
-
716
- $rss_connect_playlist_items->connect();
717
-
718
- $one_successful_connection = true;
719
-
720
- $data = $rss_connect_playlist_items->get_data();
721
- $next_pages[ $term . '_' . $type ] = false;
722
-
723
- if ( isset( $data[0] ) ) {
724
- $data = array(
725
- 'items' => $data
726
- );
727
- $post_set = $this->filter_posts( $data['items'], $settings );
728
-
729
- $this->successful_video_api_request_made = true;
730
- $new_post_sets[] = $post_set;
731
- }
732
- } else {
733
-
734
- if ( ! $api_requests_delayed
735
- && (! isset( $next_pages[ $term . '_' . $type ] ) || $next_pages[ $term . '_' . $type ] !== false) ) {
736
-
737
- $play_list = $this->get_play_list_for_term( $type, $term, $connected_account_for_term, $params );
738
-
739
- $channel_id = isset( $this->channels_data[ $term ] ) ? SBY_Parse::get_channel_id( $this->channels_data[ $term ] ) : '';
740
- $params['channel_id'] = $channel_id;
741
-
742
- if ( $play_list ) {
743
-
744
- $params['playlist_id'] = $play_list;
745
- if ( ! empty( $next_pages[ $term . '_' . $type ] ) && $next_pages[ $term . '_' . $type ] !== 'rss' ) {
746
- $params['nextPageToken'] = $next_pages[ $term . '_' . $type ];
747
- }
748
-
749
- if ( isset( $next_pages[ $term . '_' . $type ] ) && $next_pages[ $term . '_' . $type ] === 'rss' ) {
750
- self::update_channel_status( $term, 1 );
751
- $this->do_page_cache_all = true;
752
- $this->add_report( 'using API request to get first 50 videos' );
753
- } else {
754
- $this->add_report( 'using API request to get more videos' );
755
- }
756
-
757
- $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, 'playlistItems', $params );
758
-
759
- $api_connect_playlist_items->connect();
760
-
761
- if ( ! $api_connect_playlist_items->is_wp_error() && ! $api_connect_playlist_items->is_youtube_error() ) {
762
- $one_successful_connection = true;
763
- $data = $api_connect_playlist_items->get_data();
764
-
765
- if ( isset( $data['items'][0] ) ) {
766
- $post_set = $this->filter_posts( $data['items'], $settings );
767
-
768
- $this->successful_video_api_request_made = true;
769
-
770
- $new_post_sets[] = $post_set;
771
- }
772
-
773
- $next_page = $this->is_pageable() ? $api_connect_playlist_items->get_next_page() : false;
774
- if ( ! empty( $next_page ) ) {
775
- $next_pages[ $term . '_' . $type ] = $next_page;
776
- $next_page_found = true;
777
- } else {
778
- $next_pages[ $term . '_' . $type ] = false;
779
- }
780
- }
781
- } else {
782
- $this->add_report( 'no first playlist' );
783
- }
784
-
785
- if ( ! $this->is_pageable()
786
- && empty( $next_pages[ $term . '_' . $type ] )
787
- && ! empty( $params['channel_id'] ) ) {
788
- $this->add_report( 'using RSS to get first 15' );
789
-
790
- $rss_connect_playlist_items = new SBY_RSS_Connect( 'playlistItems', $params );
791
-
792
- $rss_connect_playlist_items->connect();
793
-
794
- $one_successful_connection = true;
795
-
796
- $data = $rss_connect_playlist_items->get_data();
797
-
798
- if ( isset( $data[0] ) ) {
799
- $data = array(
800
- 'items' => $data
801
- );
802
- $post_set = $this->filter_posts( $data['items'], $settings );
803
-
804
- $this->successful_video_api_request_made = true;
805
-
806
-
807
- if ( count( $post_set ) > 14 ) {
808
- if ( (int)self::get_channel_status( $term ) !== 1 ) {
809
- $next_pages[ $term . '_' . $type ] = 'rss';
810
- $next_page_found = true;
811
- } else {
812
- $this->add_report( 'RSS Only' . $term );
813
- $post_set = $this->merge_cached_posts( $post_set, $term );
814
- $next_pages[ $term . '_' . $type ] = false;
815
- }
816
- } else {
817
- $next_pages[ $term . '_' . $type ] = false;
818
- }
819
-
820
- $new_post_sets[] = $post_set;
821
-
822
- }
823
- } else {
824
- $this->num_api_calls++;
825
- }
826
-
827
- }
828
- }
829
- }
830
-
831
- }
832
-
833
- }
834
-
835
- if ( ! $one_successful_connection || ($one_api_request_delayed && empty( $new_post_sets )) ) {
836
- $this->should_use_backup = true;
837
- }
838
- $posts = $this->merge_posts( $new_post_sets, $settings );
839
-
840
- $posts = $this->sort_posts( $posts, $settings );
841
-
842
- if ( ! empty( $this->post_data ) && is_array( $this->post_data ) ) {
843
- $posts = array_merge( $this->post_data, $posts );
844
- }
845
-
846
- $this->post_data = $posts;
847
-
848
- if ( isset( $next_page_found ) && $next_page_found ) {
849
- $this->next_pages = $next_pages;
850
- } else {
851
- $this->next_pages = false;
852
- }
853
- }
854
-
855
- public function add_remote_pageable_posts() {
856
-
857
- }
858
-
859
- public function add_remote_non_pageable() {
860
-
861
- }
862
-
863
- private function is_pageable() {
864
- global $sby_settings;
865
-
866
- return ! empty( $sby_settings['api_key'] );
867
- }
868
-
869
- public function merge_cached_posts( $current_posts, $channel_id ) {
870
- $args = array(
871
- 'post_type' => SBY_CPT,
872
- 'post_status' => array( 'publish', 'pending', 'draft' ),
873
- 'orderby' => 'date',
874
- 'order' => 'DESC',
875
- 'posts_per_page' => 80,
876
- 'meta_query' => array(
877
- array(
878
- 'value' => $channel_id,
879
- 'key' => 'sby_channel_id'
880
- )
881
- )
882
- );
883
- $feed_videos = new WP_Query( $args );
884
-
885
- if ( $feed_videos->have_posts() ) {
886
- $posts = array();
887
- while ( $feed_videos->have_posts() ) {
888
- $feed_videos->the_post();
889
- $json = get_post_meta( get_the_ID(), 'sby_json', true );
890
- if ( $json ) {
891
- $posts[] = json_decode( $json, true );
892
- }
893
- }
894
-
895
- wp_reset_postdata();
896
- $this->add_report( 'merging cached posts' );
897
-
898
- $posts = array_merge( $current_posts, $posts );
899
-
900
- return $posts;
901
- } else {
902
- $this->add_report( 'no cached posts found' );
903
- wp_reset_postdata();
904
-
905
- return $current_posts;
906
- }
907
- }
908
-
909
- /**
910
- * Connects to the YouTube API and records returned data. Will use channel data if already
911
- * set by the regular feed
912
- *
913
- * @param $settings
914
- * @param array $feed_types_and_terms organized settings related to feed data
915
- * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
916
- * @param array $connected_accounts_for_feed connected account data for the
917
- * feed types and terms
918
- *
919
- * @since 1.0
920
- */
921
- public function set_remote_header_data( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
922
- $first_user = $this->get_first_user( $feed_types_and_terms, $settings );
923
- $this->header_data = false;
924
- $existing_channel_cache = $this->get_channel_cache( $first_user );
925
-
926
- if ( $existing_channel_cache ) {
927
- $this->channels_data[ $first_user ] = $existing_channel_cache;
928
- $this->add_report( 'header data for ' . $first_user . ' exists in cache' );
929
- }
930
-
931
- if ( isset( $this->channels_data[ $first_user ] ) && ! $this->is_pageable() ) {
932
- $this->header_data = $this->channels_data[ $first_user ];
933
- } elseif ( ! empty( $first_user ) ) {
934
- $connected_account_for_term = sby_get_first_connected_account();
935
- if ( $connected_account_for_term['expires'] < time() + 5 ) {
936
- $error_message = '<p><b>' . __( 'Reconnect to YouTube to show this feed.', 'custom-facebook-feed' ) . '</b></p>';
937
- $error_message .= '<p>' . __( 'To create a new feed, first connect to YouTube using the "Connect to YouTube to Create a Feed" button on the settings page and connect any account.', SBY_TEXT_DOMAIN ) . '</p>';
938
-
939
- if ( current_user_can( 'manage_youtube_feed_options' ) ) {
940
- $error_message .= '<a href="' . admin_url( 'admin.php?page=youtube-feed' ) . '" target="blank" rel="noopener nofollow">' . __( 'Reconnect in the YouTube Feed Settings Area' ) . '</a>';
941
- }
942
- global $sby_posts_manager;
943
-
944
- $sby_posts_manager->add_frontend_error( 'accesstoken', $error_message );
945
- $sby_posts_manager->add_error( 'accesstoken', array( 'Trying to connect a new account', $error_message ) );
946
- } else {
947
- $channel_params_type = strpos( $first_user, 'UC' ) !== 0 ? 'channel_name' : 'channel_id';
948
- $params[ $channel_params_type ] = $first_user;
949
- $connection = $this->make_api_connection( $connected_account_for_term, 'channels', $params );
950
-
951
- $connection->connect();
952
- $this->add_report( 'api call made for header - ' . $first_user );
953
-
954
- if ( ! $connection->is_wp_error() && ! $connection->is_youtube_error() ) {
955
- $this->header_data = $connection->get_data();
956
- $channel_id = SBY_Parse::get_channel_id( $this->header_data );
957
- $this->set_channel_cache( $channel_id, $this->header_data );
958
- $this->channels_data[ $channel_id ] = $this->header_data;
959
- $this->channels_data[ $first_user ] = $this->header_data;
960
-
961
- if ( isset( $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) && $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) {
962
- $upload = wp_upload_dir();
963
- $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBY_UPLOADS_NAME );
964
-
965
- $full_file_name = $resized_url . $this->header_data['username'] . '.jpg';
966
- $this->header_data['local_avatar'] = $full_file_name;
967
- }
968
- } else {
969
- if ( $connection->is_wp_error() ) {
970
- SBY_API_Connect::handle_wp_remote_get_error( $connection->get_wp_error() );
971
- } else {
972
- SBY_API_Connect::handle_youtube_error( $connection->get_data(), $connected_accounts_for_feed[ $first_user ], 'header' );
973
- }
974
- }
975
- }
976
- }
977
- }
978
-
979
- /**
980
- * Stores feed data in a transient for a specified time
981
- *
982
- * @param int $cache_time
983
- *
984
- * @since 1.0
985
- */
986
- public function cache_feed_data( $cache_time ) {
987
- if ( ! empty( $this->post_data ) || ! empty( $this->next_pages ) ) {
988
- $this->remove_duplicate_posts();
989
- $this->trim_posts_to_max();
990
-
991
- $post_data = $this->post_data;
992
-
993
- if (! isset( $post_data[0]['iframe'] )) {
994
- $to_cache = array(
995
- 'data' => $this->post_data,
996
- 'pagination' => $this->next_pages
997
- );
998
-
999
- set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
1000
- } else {
1001
- $this->add_report( 'iframe not caching' );
1002
- }
1003
-
1004
-
1005
- } else {
1006
- $this->add_report( 'no data not caching' );
1007
- }
1008
- }
1009
-
1010
- /**
1011
- * Stores feed data with additional data specifically for cron caching
1012
- *
1013
- * @param array $to_cache feed data with additional things like the shortcode
1014
- * settings, when the cache was last requested, when new posts were last retrieved
1015
- * @param int $cache_time how long the cache will last
1016
- *
1017
- * @since 1.0
1018
- */
1019
- public function set_cron_cache( $to_cache, $cache_time ) {
1020
- if ( ! empty( $this->post_data )
1021
- || ! empty( $this->next_pages )
1022
- || ! empty( $to_cache['data'] ) ) {
1023
- $this->remove_duplicate_posts();
1024
- $this->trim_posts_to_max();
1025
-
1026
- $to_cache['data'] = isset( $to_cache['data'] ) ? $to_cache['data'] : $this->post_data;
1027
- $to_cache['pagination'] = isset( $to_cache['next_pages'] ) ? $to_cache['next_pages'] : $this->next_pages;
1028
- $to_cache['atts'] = isset( $to_cache['atts'] ) ? $to_cache['atts'] : $this->transient_atts;
1029
- $to_cache['last_requested'] = isset( $to_cache['last_requested'] ) ? $to_cache['last_requested'] : time();
1030
- $to_cache['last_retrieve'] = isset( $to_cache['last_retrieve'] ) ? $to_cache['last_retrieve'] : $this->last_retrieve;
1031
-
1032
- set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
1033
- } else {
1034
- $this->add_report( 'no data not caching' );
1035
- }
1036
-
1037
- }
1038
-
1039
- /**
1040
- * Stores header data for a specified time as a transient
1041
- *
1042
- * @param int $cache_time
1043
- * @param bool $save_backup
1044
- *
1045
- * @since 1.0
1046
- */
1047
- public function cache_header_data( $cache_time, $save_backup = true ) {
1048
- if ( $this->header_data ) {
1049
- set_transient( $this->header_transient_name, wp_json_encode( $this->header_data ), $cache_time );
1050
-
1051
- if ( $save_backup ) {
1052
- update_option( $this->backup_header_transient_name, wp_json_encode( $this->header_data ), false );
1053
- }
1054
- }
1055
- }
1056
-
1057
- /**
1058
- * Used to randomly trigger an updating of the last requested data for cron caching
1059
- *
1060
- * @return bool
1061
- *
1062
- * @since 1.0
1063
- */
1064
- public function should_update_last_requested() {
1065
- return (rand( 1, 20 ) === 20);
1066
- }
1067
-
1068
- /**
1069
- * Determines if pagination can and should be used based on settings and available feed data
1070
- *
1071
- * @param array $settings
1072
- * @param int $offset
1073
- *
1074
- * @return bool
1075
- *
1076
- * @since 1.0
1077
- */
1078
- public function should_use_pagination( $settings, $offset = 0 ) {
1079
- $posts_available = count( $this->post_data ) - ($offset + $settings['num']);
1080
- $show_loadmore_button_by_settings = ($settings['showbutton'] == 'on' || $settings['showbutton'] == 'true' || $settings['showbutton'] == true ) && $settings['showbutton'] !== 'false';
1081
-
1082
- if ( $show_loadmore_button_by_settings ) {
1083
- // used for permanent and whitelist feeds
1084
- if ( $this->feed_is_complete( $settings, $offset ) ) {
1085
- $this->add_report( 'no pagination, feed complete' );
1086
- return false;
1087
- }
1088
- if ( $posts_available > 0 ) {
1089
- $this->add_report( 'do pagination, posts available' );
1090
- return true;
1091
- }
1092
- $pages = $this->next_pages;
1093
-
1094
- if ( $pages && ! $this->should_use_backup() ) {
1095
- foreach ( $pages as $page ) {
1096
- if ( ! empty( $page ) ) {
1097
- return true;
1098
- }
1099
- }
1100
- }
1101
-
1102
- }
1103
-
1104
-
1105
- $this->add_report( 'no pagination, no posts available' );
1106
-
1107
- return false;
1108
- }
1109
-
1110
- public static function get_channel_status( $channel ) {
1111
- $channel_setting = get_option( 'sby_channel_status', array() );
1112
-
1113
- if ( isset( $channel_setting[ $channel ] ) ) {
1114
- return $channel_setting[ $channel ];
1115
- }
1116
-
1117
- return 0;
1118
- }
1119
-
1120
- public static function update_channel_status( $channel, $status ) {
1121
- $channel_setting = get_option( 'sby_channel_status', array() );
1122
-
1123
- $channel_setting[ $channel ] = $status;
1124
-
1125
- update_option( 'sby_channel_status', $channel_setting, false );
1126
- }
1127
-
1128
- /**
1129
- * Generates the HTML for the feed if post data is available. Although it seems
1130
- * some of the variables ar not used they are set here to hide where they
1131
- * come from when used in the feed templates.
1132
- *
1133
- * @param array $settings
1134
- * @param array $atts
1135
- * @param array $feed_types_and_terms organized settings related to feed data
1136
- * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
1137
- * @param array $connected_accounts_for_feed connected account data for the
1138
- * feed types and terms
1139
- *
1140
- * @return false|string
1141
- *
1142
- * @since 1.0
1143
- */
1144
- public function get_the_feed_html( $settings, $atts, $feed_types_and_terms, $connected_accounts_for_feed ) {
1145
- global $sby_posts_manager;
1146
-
1147
- if ( empty( $this->post_data ) && ! empty( $connected_accounts_for_feed ) ) {
1148
- $error = '<p><b>' . __( 'Error: No videos found.', SBY_TEXT_DOMAIN ) . '</b>';
1149
- $error .= '<p>' . __( 'Make sure this is a valid channel ID and that the channel has videos available on youtube.com.', SBY_TEXT_DOMAIN ) . '</p>';
1150
-
1151
- $sby_posts_manager->add_frontend_error( 'noposts', $error );
1152
- }
1153
-
1154
- $posts = array_slice( $this->post_data, 0, $settings['minnum'] );
1155
- $header_data = ! empty( $this->header_data ) ? $this->header_data : false;
1156
-
1157
- $first_username = false;
1158
- if ( $header_data ) {
1159
- $first_username = SBY_Parse::get_channel_id( $header_data );
1160
- } elseif ( isset( $this->post_data[0] ) ) { // in case no connected account for feed
1161
- $first_username = SBY_Parse::get_channel_id( $this->post_data[0] );
1162
- }
1163
-
1164
- $use_pagination = $this->should_use_pagination( $settings, 0 );
1165
-
1166
- $feed_id = $this->regular_feed_transient_name;
1167
- $shortcode_atts = ! empty( $atts ) ? wp_json_encode( $atts ) : '{}';
1168
-
1169
- $settings['header_outside'] = false;
1170
- $settings['header_inside'] = false;
1171
- if ( $header_data && $settings['showheader'] ) {
1172
- $settings['header_inside'] = true;
1173
- }
1174
-
1175
- $other_atts = '';
1176
-
1177
- $classes = array();
1178
- if ( empty( $settings['widthresp'] ) || $settings['widthresp'] == 'on' || $settings['widthresp'] == 'true' || $settings['widthresp'] === true ) {
1179
- if ( $settings['widthresp'] !== 'false' ) {
1180
- $classes[] = 'sby_width_resp';
1181
- }
1182
- }
1183
- if ( ! empty( $settings['class'] ) ) {
1184
- $classes[] = esc_attr( $settings['class'] );
1185
- }
1186
- if ( ! empty( $settings['height'] )
1187
- && (((int)$settings['height'] < 100 && $settings['heightunit'] === '%') || $settings['heightunit'] === 'px') ) {
1188
- $classes[] = 'sby_fixed_height';
1189
- }
1190
- if ( ! empty( $settings['disablemobile'] )
1191
- && ($settings['disablemobile'] == 'on' || $settings['disablemobile'] == 'true' || $settings['disablemobile'] == true) ) {
1192
- if ( $settings['disablemobile'] !== 'false' ) {
1193
- $classes[] = 'sby_disable_mobile';
1194
- }
1195
- }
1196
-
1197
- $additional_classes = '';
1198
- if ( ! empty( $classes ) ) {
1199
- $additional_classes = ' ' . implode( ' ', $classes );
1200
- }
1201
-
1202
- $other_atts = $this->add_other_atts( $other_atts, $settings );
1203
-
1204
- $flags = array();
1205
-
1206
- if ( $this->successful_video_api_request_made && ! empty( $posts ) ) {
1207
- if ( $settings['storage_process'] === 'page' ) {
1208
- $this_posts = $posts;
1209
- if ( $this->do_page_cache_all ) {
1210
- $this_posts = $this->post_data;
1211
- }
1212
- $this->add_report( 'Adding videos to wp_posts ' . count( $this_posts ) );
1213
-
1214
- sby_process_post_set_caching( $this_posts, $feed_id );
1215
- } elseif ( $settings['storage_process'] === 'background' ) {
1216
- $flags[] = 'checkWPPosts';
1217
- if ( $this->do_page_cache_all ) {
1218
- $this->add_report( 'Flagging videos to wp_posts ' . count( $this->post_data ) );
1219
- $flags[] = 'cacheAll';
1220
- }
1221
- }
1222
- }
1223
-
1224
- if ( $settings['disable_resize'] ) {
1225
- $flags[] = 'resizeDisable';
1226
- } elseif ( $settings['favor_local'] ) {
1227
- $flags[] = 'favorLocal';
1228
- }
1229
-
1230
- if ( $settings['disable_js_image_loading'] ) {
1231
- $flags[] = 'imageLoadDisable';
1232
- }
1233
- if ( $settings['ajax_post_load'] ) {
1234
- $flags[] = 'ajaxPostLoad';
1235
- }
1236
- if ( $settings['playerratio'] === '3:4' ) {
1237
- $flags[] = 'narrowPlayer';
1238
- }
1239
- if ( SBY_GDPR_Integrations::doing_gdpr( $settings ) ) {
1240
- $flags[] = 'gdpr';
1241
- }
1242
- if ( ! is_admin()
1243
- && SBY_Feed_Locator::should_do_ajax_locating( $this->regular_feed_transient_name, get_the_ID() ) ) {
1244
- $flags[] = 'locator';
1245
- }
1246
- if ( $settings['disablecdn'] ) {
1247
- $flags[] = 'disablecdn';
1248
- }
1249
- if ( isset( $_GET['sby_debug'] ) ) {
1250
- $flags[] = 'debug';
1251
- }
1252
-
1253
- if ( ! empty( $flags ) ) {
1254
- $other_atts .= ' data-sby-flags="' . implode(',', $flags ) . '"';
1255
- }
1256
- $other_atts .= ' data-postid="' . get_the_ID() . '"';
1257
- if ( $settings['layout'] === 'grid' || $settings['layout'] === 'carousel' ) {
1258
- $other_atts .= ' data-sby-supports-lightbox="1"';
1259
- }
1260
- $icon_type = $settings['font_method'];
1261
-
1262
- ob_start();
1263
- include sby_get_feed_template_part( 'feed', $settings );
1264
- $html = ob_get_contents();
1265
- ob_get_clean();
1266
-
1267
- if ( $settings['ajaxtheme'] ) {
1268
- $html .= $this->get_ajax_page_load_html();
1269
- }
1270
-
1271
- return $html;
1272
- }
1273
-
1274
- /**
1275
- * Generates HTML for individual sby_item elements
1276
- *
1277
- * @param array $settings
1278
- * @param int $offset
1279
- * @param array $feed_types_and_terms organized settings related to feed data
1280
- * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
1281
- * @param array $connected_accounts_for_feed connected account data for the
1282
- * feed types and terms
1283
- *
1284
- * @return false|string
1285
- *
1286
- * @since 1.0
1287
- */
1288
- public function get_the_items_html( $settings, $offset, $feed_types_and_terms = array(), $connected_accounts_for_feed = array() ) {
1289
- if ( empty( $this->post_data ) ) {
1290
- ob_start();
1291
- $html = ob_get_contents();
1292
- ob_get_clean(); ?>
1293
- <p><?php _e( 'No posts found.', SBY_TEXT_DOMAIN ); ?></p>
1294
- <?php
1295
- $html = ob_get_contents();
1296
- ob_get_clean();
1297
- return $html;
1298
- }
1299
-
1300
- $posts = array_slice( $this->post_data, $offset, $settings['num'] );
1301
-
1302
- ob_start();
1303
-
1304
- $this->posts_loop( $posts, $settings, $offset );
1305
-
1306
- $html = ob_get_contents();
1307
- ob_get_clean();
1308
-
1309
- return $html;
1310
- }
1311
-
1312
- /**
1313
- * Overwritten in the Pro version
1314
- *
1315
- * @return object
1316
- */
1317
- public function make_api_connection( $connected_account_or_page, $type = NULL, $params = NULL ) {
1318
- return new SBY_API_Connect( $connected_account_or_page, $type, $params );
1319
- }
1320
-
1321
- /**
1322
- * When the feed is loaded with AJAX, the JavaScript for the plugin
1323
- * needs to be triggered again. This function is a workaround that adds
1324
- * the file and settings to the page whenever the feed is generated.
1325
- *
1326
- * @return string
1327
- *
1328
- * @since 1.0
1329
- */
1330
- public static function get_ajax_page_load_html() {
1331
- global $sby_settings;
1332
-
1333
- $js_options = array(
1334
- 'adminAjaxUrl' => admin_url( 'admin-ajax.php' ),
1335
- 'placeholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png',
1336
- 'placeholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder-narrow.png',
1337
- 'lightboxPlaceholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder.png',
1338
- 'lightboxPlaceholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder-narrow.png',
1339
- 'autoplay' => $sby_settings['playvideo'] === 'automatically',
1340
- 'semiEagerload' => $sby_settings['eagerload'],
1341
- 'eagerload' => false
1342
- );
1343
-
1344
- $encoded_options = wp_json_encode( $js_options );
1345
-
1346
- $js_option_html = '<script type="text/javascript">if (typeof sbyOptions === "undefined") var sbyOptions = ' . $encoded_options . ';</script>';
1347
- $js_option_html .= "<script type='text/javascript' src='" . trailingslashit( SBY_PLUGIN_URL ) . 'js/sb-youtube.min.js?ver=' . SBYVER . "'></script>";
1348
-
1349
- return $js_option_html;
1350
- }
1351
-
1352
- /**
1353
- * Overwritten in the Pro version
1354
- *
1355
- * @param $feed_types_and_terms
1356
- *
1357
- * @return string
1358
- *
1359
- * @since 2.1/5.2
1360
- */
1361
- public function get_first_user( $feed_types_and_terms, $settings = array() ) {
1362
- if ( isset( $feed_types_and_terms['channels'][0] ) ) {
1363
- return $feed_types_and_terms['channels'][0]['term'];
1364
- } else {
1365
- return '';
1366
- }
1367
- }
1368
-
1369
- public function do_page_cache_all() {
1370
- return $this->do_page_cache_all;
1371
- }
1372
-
1373
- public function successful_video_api_request_made() {
1374
- return $this->successful_video_api_request_made;
1375
- }
1376
-
1377
- /**
1378
- * Adds recorded strings to an array
1379
- *
1380
- * @param $to_add
1381
- *
1382
- * @since 1.0
1383
- */
1384
- public function add_report( $to_add ) {
1385
- $this->report[] = $to_add;
1386
- }
1387
-
1388
- /**
1389
- * @return array
1390
- *
1391
- * @since 1.0
1392
- */
1393
- public function get_report() {
1394
- return $this->report;
1395
- }
1396
-
1397
- /**
1398
- * Additional options/settings added to the main div
1399
- * for the feed
1400
- *
1401
- * Overwritten in the Pro version
1402
- *
1403
- * @param $other_atts
1404
- * @param $settings
1405
- *
1406
- * @return string
1407
- */
1408
- protected function add_other_atts( $other_atts, $settings ) {
1409
- return '';
1410
- }
1411
-
1412
- /**
1413
- * Used for filtering a single API request worth of posts
1414
- *
1415
- * Overwritten in the Pro version
1416
- *
1417
- * @param array $post_set a single set of post data from the api
1418
- *
1419
- * @return mixed|array
1420
- *
1421
- * @since 1.0
1422
- */
1423
- protected function filter_posts( $post_set, $settings = array() ) {
1424
- // array_unique( $post_set, SORT_REGULAR);
1425
-
1426
- return $post_set;
1427
- }
1428
-
1429
- protected function remove_duplicate_posts() {
1430
- $posts = $this->post_data;
1431
- $ids_in_feed = array();
1432
- $non_duplicate_posts = array();
1433
- $removed = array();
1434
-
1435
- foreach ( $posts as $post ) {
1436
- $post_id = SBY_Parse::get_video_id( $post );
1437
- if ( ! in_array( $post_id, $ids_in_feed, true ) ) {
1438
- $ids_in_feed[] = $post_id;
1439
- $non_duplicate_posts[] = $post;
1440
- } else {
1441
- $removed[] = $post_id;
1442
- }
1443
- }
1444
-
1445
- $this->add_report( 'removed duplicates: ' . implode(', ', $removed ) );
1446
- $this->set_post_data( $non_duplicate_posts );
1447
- }
1448
-
1449
- /**
1450
- * Used for limiting the cache size
1451
- *
1452
- * @since 2.0/5.1.1
1453
- */
1454
- protected function trim_posts_to_max() {
1455
- if ( ! is_array( $this->post_data ) ) {
1456
- return;
1457
- }
1458
-
1459
- $max = apply_filters( 'sby_max_cache_size', 500 );
1460
- $this->set_post_data( array_slice( $this->post_data , 0, $max ) );
1461
-
1462
- }
1463
-
1464
- /**
1465
- * Used for permanent feeds or white list feeds to
1466
- * stop pagination if all posts are already added
1467
- *
1468
- * Overwritten in the Pro version
1469
- *
1470
- * @param array $settings
1471
- * @param int $offset
1472
- *
1473
- * @return bool
1474
- *
1475
- * @since 1.0
1476
- */
1477
- protected function feed_is_complete( $settings, $offset = 0 ) {
1478
- return false;
1479
- }
1480
-
1481
- /**
1482
- * Iterates through post data and tracks the index of the current post.
1483
- * The actual post ids of the posts are stored in an array so the plugin
1484
- * can search for local images that may be available.
1485
- *
1486
- * @param array $posts final filtered post data for the feed
1487
- * @param array $settings
1488
- * @param int $offset
1489
- *
1490
- * @since 1.0
1491
- */
1492
- protected function posts_loop( $posts, $settings, $offset = 0 ) {
1493
-
1494
- $image_ids = array();
1495
- $post_index = $offset;
1496
- if ( ! isset( $settings['feed_id'] ) ) {
1497
- $settings['feed_id'] = $this->regular_feed_transient_name;
1498
- }
1499
- $misc_data = $this->get_misc_data( $settings['feed_id'], $posts );
1500
- $icon_type = $settings['font_method'];
1501
-
1502
- foreach ( $posts as $post ) {
1503
- $image_ids[] = SBY_Parse::get_post_id( $post );
1504
- include sby_get_feed_template_part( 'item', $settings );
1505
- $post_index++;
1506
- }
1507
-
1508
- $this->image_ids_post_set = $image_ids;
1509
- }
1510
-
1511
- /**
1512
- * Uses array of API request results and merges them based on how
1513
- * the feed should be sorted. Mixed feeds are always sorted alternating
1514
- * since there is no post date for hashtag feeds.
1515
- *
1516
- * @param array $post_sets an array of single API request worth
1517
- * of posts
1518
- * @param array $settings
1519
- *
1520
- * @return array
1521
- *
1522
- * @since 1.0
1523
- */
1524
- private function merge_posts( $post_sets, $settings ) {
1525
-
1526
- $merged_posts = array();
1527
- if ( $settings['sortby'] === 'alternate' ) {
1528
- // don't bother merging posts if there is only one post set
1529
- if ( isset( $post_sets[1] ) ) {
1530
- $min_cycles = max( 1, (int)$settings['num'] );
1531
- for( $i = 0; $i <= $min_cycles; $i++ ) {
1532
- foreach ( $post_sets as $post_set ) {
1533
- if ( isset( $post_set[ $i ] ) && isset( $post_set[ $i ]['id'] ) ) {
1534
- $merged_posts[] = $post_set[ $i ];
1535
- }
1536
- }
1537
- }
1538
- } else {
1539
- $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1540
- }
1541
- } elseif ( $settings['sortby'] === 'api' ) {
1542
- if ( isset( $post_sets[0] ) ) {
1543
- foreach ( $post_sets as $post_set ) {
1544
- $merged_posts = array_merge( $merged_posts, $post_set );
1545
- }
1546
- }
1547
- } else {
1548
- // don't bother merging posts if there is only one post set
1549
- if ( isset( $post_sets[1] ) ) {
1550
- foreach ( $post_sets as $post_set ) {
1551
- if ( isset( $post_set[0]['id'] ) ) {
1552
- $merged_posts = array_merge( $merged_posts, $post_set );
1553
- }
1554
- }
1555
- } else {
1556
- $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1557
- }
1558
- }
1559
-
1560
-
1561
- return $merged_posts;
1562
- }
1563
-
1564
- /**
1565
- * Sorts a post set based on sorting settings. Sorting by "alternate"
1566
- * is done when merging posts for efficiency's sake so the post set is
1567
- * just returned as it is.
1568
- *
1569
- * @param array $post_set
1570
- * @param array $settings
1571
- *
1572
- * @return mixed|array
1573
- *
1574
- * @since 1.0
1575
- */
1576
- protected function sort_posts( $post_set, $settings ) {
1577
- if ( empty( $post_set ) ) {
1578
- return $post_set;
1579
- }
1580
-
1581
- // sorting done with "merge_posts" to be more efficient
1582
- if ( $settings['sortby'] === 'alternate' || $settings['sortby'] === 'api' ) {
1583
- $return_post_set = $post_set;
1584
- } elseif ( $settings['sortby'] === 'random' ) {
1585
- /*
1586
- * randomly selects posts in a random order. Cache saves posts
1587
- * in this random order so paginating does not cause some posts to show up
1588
- * twice or not at all
1589
- */
1590
- usort($post_set, 'sby_rand_sort' );
1591
- $return_post_set = $post_set;
1592
-
1593
- } else {
1594
- // compares posted on dates of posts
1595
- usort($post_set, 'sby_date_sort' );
1596
- $return_post_set = $post_set;
1597
- }
1598
-
1599
- /**
1600
- * Apply a custom sorting of posts
1601
- *
1602
- * @param array $return_post_set Ordered set of filtered posts
1603
- * @param array $settings Settings for this feed
1604
- *
1605
- * @since 1.0
1606
- */
1607
-
1608
- return apply_filters( 'sby_sorted_posts', $return_post_set, $settings );
1609
- }
1610
-
1611
- /**
1612
- * Can trigger a second attempt at getting posts from the API
1613
- *
1614
- * Overwritten in the Pro version
1615
- *
1616
- * @param string $type
1617
- * @param array $connected_account_with_error
1618
- * @param int $attempts
1619
- *
1620
- * @return bool
1621
- *
1622
- * @since 1.0
1623
- */
1624
- protected function can_try_another_request( $type, $connected_account_with_error, $attempts = 0 ) {
1625
- return false;
1626
- }
1627
-
1628
- /**
1629
- * returns a second connected account if it exists
1630
- *
1631
- * Overwritten in the Pro version
1632
- *
1633
- * @param string $type
1634
- * @param array $attempted_connected_accounts
1635
- *
1636
- * @return bool
1637
- *
1638
- * @since 1.0
1639
- */
1640
- protected function get_different_connected_account( $type, $attempted_connected_accounts ) {
1641
- return false;
1642
- }
1643
-
 
 
 
 
1644
  }
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ die( '-1' );
5
+ }
6
+
7
+ class SBY_Feed
8
+ {
9
+ /**
10
+ * @var string
11
+ */
12
+ protected $regular_feed_transient_name;
13
+
14
+ /**
15
+ * @var string
16
+ */
17
+ private $header_transient_name;
18
+
19
+ /**
20
+ * @var string
21
+ */
22
+ private $backup_feed_transient_name;
23
+
24
+ /**
25
+ * @var string
26
+ */
27
+ private $backup_header_transient_name;
28
+
29
+ protected $channels_data;
30
+
31
+ /**
32
+ * @var array
33
+ */
34
+ private $post_data;
35
+
36
+ /**
37
+ * @var
38
+ */
39
+ private $header_data;
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $next_pages;
45
+
46
+ /**
47
+ * @var array
48
+ */
49
+ private $transient_atts;
50
+
51
+ /**
52
+ * @var int
53
+ */
54
+ private $last_retrieve;
55
+
56
+ /**
57
+ * @var bool
58
+ */
59
+ private $should_paginate;
60
+
61
+ /**
62
+ * @var int
63
+ */
64
+ private $num_api_calls;
65
+
66
+ /**
67
+ * @var int
68
+ */
69
+ private $max_api_calls;
70
+
71
+ /**
72
+ * @var array
73
+ */
74
+ protected $image_ids_post_set;
75
+
76
+ /**
77
+ * @var array
78
+ */
79
+ public $post_ids_with_no_details;
80
+
81
+ /**
82
+ * @var bool
83
+ */
84
+ private $should_use_backup;
85
+
86
+ /**
87
+ * @var array
88
+ */
89
+ private $report;
90
+
91
+ private $successful_video_api_request_made;
92
+
93
+ private $do_page_cache_all;
94
+
95
+ /**
96
+ * SBY_Feed constructor.
97
+ *
98
+ * @param string $transient_name ID of this feed
99
+ * generated in the SBY_Settings class
100
+ */
101
+ public function __construct( $transient_name ) {
102
+ $this->regular_feed_transient_name = $transient_name;
103
+ $this->backup_feed_transient_name = SBY_BACKUP_PREFIX . $transient_name;
104
+
105
+ $sby_header_transient_name = str_replace( 'sby_', 'sby_header_', $transient_name );
106
+ $sby_header_transient_name = substr($sby_header_transient_name, 0, 44);
107
+ $this->header_transient_name = $sby_header_transient_name;
108
+ $this->backup_header_transient_name = SBY_BACKUP_PREFIX . $sby_header_transient_name;
109
+
110
+ $this->channels_data = array();
111
+
112
+ $this->post_data = array();
113
+ $this->next_pages = array();
114
+ $this->should_paginate = true;
115
+
116
+ // this is a count of how many api calls have been made for each feed
117
+ // type and term.
118
+ // By default the limit is 10
119
+ $this->num_api_calls = 0;
120
+ $this->max_api_calls = apply_filters( 'sby_max_concurrent_api_calls', 10 );
121
+ $this->should_use_backup = false;
122
+
123
+ // used for errors and the sby_debug report
124
+ $this->report = array();
125
+ $this->successful_video_api_request_made = false;
126
+ $this->post_ids_with_no_details = array();
127
+ $this->do_page_cache_all = false;
128
+ }
129
+
130
+ /**
131
+ * @return array
132
+ *
133
+ * @since 1.0
134
+ */
135
+ public function get_post_data() {
136
+ return $this->post_data;
137
+ }
138
+
139
+ /**
140
+ * @return array
141
+ *
142
+ * @since 1.0
143
+ */
144
+ public function set_post_data( $post_data ) {
145
+ $this->post_data = $post_data;
146
+ }
147
+
148
+ public function get_misc_data( $feed_id, $posts ) {
149
+ return array();
150
+ }
151
+
152
+ /**
153
+ * @return array
154
+ *
155
+ * @since 1.0
156
+ */
157
+ public function get_next_pages() {
158
+ return $this->next_pages;
159
+ }
160
+
161
+ /**
162
+ * Checks the database option related the transient expiration
163
+ * to ensure it will be available when the page loads
164
+ *
165
+ * @return bool
166
+ *
167
+ * @since 2.0/4.0
168
+ */
169
+ public function regular_cache_exists() {
170
+ //Check whether the cache transient exists in the database and is available for more than one more minute
171
+ $transient_exists = get_transient( $this->regular_feed_transient_name );
172
+
173
+ return $transient_exists;
174
+ }
175
+
176
+ /**
177
+ * Checks the database option related the header transient
178
+ * expiration to ensure it will be available when the page loads
179
+ *
180
+ * @return bool
181
+ *
182
+ * @since 1.0
183
+ */
184
+ public function regular_header_cache_exists() {
185
+ $header_transient = get_transient( $this->header_transient_name );
186
+
187
+ return $header_transient;
188
+ }
189
+
190
+ public function get_channel_cache( $channel, $force_get_cache = false ) {
191
+ if ( $this->is_pageable() && ! $force_get_cache ) {
192
+ return false;
193
+ }
194
+
195
+ $maybe_cache = get_option( SBY_CHANNEL_CACHE_PREFIX . $channel );
196
+ if ( $maybe_cache !== false ) {
197
+ $maybe_cache = json_decode( $maybe_cache, true );
198
+ }
199
+
200
+ return $maybe_cache;
201
+ }
202
+
203
+ public function set_channel_cache( $channel, $cache ) {
204
+ if ( is_array( $cache ) ) {
205
+ $cache = wp_json_encode( $cache );
206
+ }
207
+
208
+ update_option( SBY_CHANNEL_CACHE_PREFIX . $channel, $cache, false );
209
+ }
210
+
211
+ /**
212
+ * @return bool
213
+ *
214
+ * @since 1.0
215
+ */
216
+ public function should_use_backup() {
217
+ return $this->should_use_backup || empty( $this->post_data );
218
+ }
219
+
220
+ /**
221
+ * The header is only displayed when the setting is enabled and
222
+ * an account has been connected
223
+ *
224
+ * Overwritten in the Pro version
225
+ *
226
+ * @param array $settings settings specific to this feed
227
+ * @param array $feed_types_and_terms organized settings related to feed data
228
+ * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
229
+ *
230
+ * @return bool
231
+ *
232
+ * @since 1.0
233
+ */
234
+ public function need_header( $settings, $feed_types_and_terms ) {
235
+ $showheader = ($settings['showheader'] === 'on' || $settings['showheader'] === 'true' || $settings['showheader'] === true);
236
+ return ($showheader && isset( $feed_types_and_terms['channels'] ));
237
+ }
238
+
239
+ /**
240
+ * Use the transient name to retrieve cached data for header
241
+ *
242
+ * @since 1.0
243
+ */
244
+ public function set_header_data_from_cache() {
245
+ $header_cache = get_transient( $this->header_transient_name );
246
+
247
+ $header_cache = json_decode( $header_cache, true );
248
+
249
+ if ( ! empty( $header_cache ) ) {
250
+ $this->header_data = $header_cache;
251
+ }
252
+ }
253
+
254
+ public function set_header_data( $header_data ) {
255
+ $this->header_data = $header_data;
256
+ }
257
+
258
+ /**
259
+ * @since 1.0
260
+ */
261
+ public function get_header_data() {
262
+ return $this->header_data;
263
+ }
264
+
265
+ /**
266
+ * Sets the post data, pagination data, shortcode atts used (cron cache),
267
+ * and timestamp of last retrieval from transient (cron cache)
268
+ *
269
+ * @param array $atts available for cron caching
270
+ *
271
+ * @since 1.0
272
+ */
273
+ public function set_post_data_from_cache( $atts = array() ) {
274
+ $transient_data = get_transient( $this->regular_feed_transient_name );
275
+
276
+ $transient_data = json_decode( $transient_data, true );
277
+
278
+ if ( $transient_data ) {
279
+ $post_data = isset( $transient_data['data'] ) ? $transient_data['data'] : array();
280
+ $this->post_data = $post_data;
281
+ $this->next_pages = isset( $transient_data['pagination'] ) ? $transient_data['pagination'] : array();
282
+
283
+ if ( isset( $transient_data['atts'] ) ) {
284
+ $this->transient_atts = $transient_data['atts'];
285
+ $this->last_retrieve = $transient_data['last_retrieve'];
286
+ }
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Sets post data from a permanent database backup of feed
292
+ * if it was created
293
+ *
294
+ * @since 1.0
295
+ */
296
+ public function maybe_set_post_data_from_backup() {
297
+ $args = array(
298
+ 'post_type' => SBY_CPT,
299
+ 'post_status' => array( 'publish', 'pending', 'draft' ),
300
+ 'orderby' => 'date',
301
+ 'order' => 'DESC',
302
+ 'posts_per_page' => 50,
303
+ 'meta_query' => array(
304
+ array(
305
+ 'value' => sby_strip_after_hash( $this->regular_feed_transient_name ),
306
+ 'key' => 'sby_feed_id'
307
+ )
308
+ )
309
+ );
310
+ $feed_videos = new WP_Query( $args );
311
+
312
+ if ( $feed_videos->have_posts() ) {
313
+ $posts = array();
314
+ while ( $feed_videos->have_posts() ) {
315
+ $feed_videos->the_post();
316
+ $json = get_post_meta( get_the_ID(), 'sby_json', true );
317
+
318
+ if ( $json ) {
319
+ $posts[] = json_decode( $json, true );
320
+ }
321
+ }
322
+
323
+ wp_reset_postdata();
324
+
325
+ $this->post_data = $posts;
326
+ return true;
327
+ } else {
328
+ $this->add_report( 'no backup post data found' );
329
+ wp_reset_postdata();
330
+
331
+ return false;
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Sets header data from a permanent database backup of feed
337
+ * if it was created
338
+ *
339
+ * @since 1.0
340
+ */
341
+ public function maybe_set_header_data_from_backup() {
342
+ $backup_header_data = get_option( $this->backup_header_transient_name, false );
343
+
344
+ if ( ! empty( $backup_header_data ) ) {
345
+ $backup_header_data = json_decode( $backup_header_data, true );
346
+ $this->header_data = $backup_header_data;
347
+
348
+ return true;
349
+ } else {
350
+ $this->add_report( 'no backup header data found' );
351
+
352
+ return false;
353
+ }
354
+ }
355
+
356
+ /**
357
+ * Returns recorded image IDs for this post set
358
+ * for use with image resizing
359
+ *
360
+ * @return array
361
+ *
362
+ * @since 1.0
363
+ */
364
+ public function get_image_ids_post_set() {
365
+ return $this->image_ids_post_set;
366
+ }
367
+
368
+ /**
369
+ * Cron caching needs additional data saved in the transient
370
+ * to work properly. This function checks to make sure it's present
371
+ *
372
+ * @return bool
373
+ *
374
+ * @since 1.0
375
+ */
376
+ public function need_to_start_cron_job() {
377
+ return (( ! empty( $this->post_data ) && ! isset( $this->transient_atts )) || empty( $this->post_data ));
378
+ }
379
+
380
+ /**
381
+ * Checks to see if there are enough posts available to create
382
+ * the current page of the feed
383
+ *
384
+ * @param int $num
385
+ * @param int $offset
386
+ *
387
+ * @return bool
388
+ *
389
+ * @since 1.0
390
+ */
391
+ public function need_posts( $num, $offset = 0 ) {
392
+ $num_existing_posts = is_array( $this->post_data ) ? count( $this->post_data ) : 0;
393
+ $num_needed_for_page = (int)$num + (int)$offset;
394
+
395
+ ($num_existing_posts < $num_needed_for_page) ? $this->add_report( 'need more posts' ) : $this->add_report( 'have enough posts' );
396
+
397
+ return ($num_existing_posts < $num_needed_for_page);
398
+ }
399
+
400
+ /**
401
+ * Checks to see if there are additional pages available for any of the
402
+ * accounts in the feed and that the max conccurrent api request limit
403
+ * has not been reached
404
+ *
405
+ * @return bool
406
+ *
407
+ * @since 1.0
408
+ */
409
+ public function can_get_more_posts() {
410
+ $one_type_and_term_has_more_ages = $this->next_pages !== false;
411
+ $max_concurrent_api_calls_not_met = $this->num_api_calls < $this->max_api_calls;
412
+ $max_concurrent_api_calls_not_met ? $this->add_report( 'max conccurrent requests not met' ) : $this->add_report( 'max concurrent met' );
413
+ $one_type_and_term_has_more_ages ? $this->add_report( 'more pages available' ) : $this->add_report( 'no next page' );
414
+
415
+ return ($one_type_and_term_has_more_ages && $max_concurrent_api_calls_not_met);
416
+ }
417
+
418
+ public function get_play_list_for_term( $type, $term, $connected_account_for_term, $params ) {
419
+
420
+ if ( $type === 'search' || $type === 'live' ) {
421
+ return false;
422
+ }
423
+ $existing_channel_cache = $this->get_channel_cache( $term );
424
+
425
+ if ( $existing_channel_cache ) {
426
+ $this->channels_data[ $term ] = $existing_channel_cache;
427
+ }
428
+
429
+ if ( empty( $this->channels_data[ $term ] ) ) {
430
+ if ( $connected_account_for_term['expires'] < time() + 5 ) {
431
+ $error_message = '<p><b>' . __( 'Reconnect to YouTube to show this feed.', 'custom-facebook-feed' ) . '</b></p>';
432
+ $error_message .= '<p>' . __( 'To create a new feed, first connect to YouTube using the "Connect to YouTube to Create a Feed" button on the settings page and connect any account.', SBY_TEXT_DOMAIN ) . '</p>';
433
+
434
+ if ( current_user_can( 'manage_youtube_feed_options' ) ) {
435
+ $error_message .= '<a href="' . admin_url( 'admin.php?page=youtube-feed' ) . '" target="blank" rel="noopener nofollow">' . __( 'Reconnect in the YouTube Feed Settings Area' ) . '</a>';
436
+ }
437
+ global $sby_posts_manager;
438
+
439
+ $sby_posts_manager->add_frontend_error( 'accesstoken', $error_message );
440
+ $sby_posts_manager->add_error( 'accesstoken', array( 'Trying to connect a new account', $error_message ) );
441
+
442
+ return false;
443
+ }
444
+ $channel_data = array();
445
+ $api_connect_channels = $this->make_api_connection( $connected_account_for_term, 'channels', $params );
446
+
447
+ $this->add_report( 'channel api call made for ' . $term . ' - ' . $type );
448
+
449
+ $api_connect_channels->connect();
450
+ if ( ! $api_connect_channels->is_wp_error() && ! $api_connect_channels->is_youtube_error() ) {
451
+ $channel_data = $api_connect_channels->get_data();
452
+ $channel_id = SBY_Parse::get_channel_id( $channel_data );
453
+ $this->set_channel_cache( $channel_id, $channel_data );
454
+
455
+ if ( isset( $params['channel_name'] ) ) {
456
+ sby_set_channel_id_from_channel_name( $params['channel_name'], $channel_id );
457
+ $this->set_channel_cache( $params['channel_name'], $channel_data );
458
+ }
459
+
460
+ $params = array( 'channel_id' => $channel_id );
461
+ $this->channels_data[ $channel_id ] = $channel_data;
462
+ $this->channels_data[ $term ] = $channel_data;
463
+ } else {
464
+ if ( ! $api_connect_channels->is_wp_error() ) {
465
+ $return = SBY_API_Connect::handle_youtube_error( $api_connect_channels->get_data(), $connected_account_for_term );
466
+ if ( $return && isset( $return['access_token'] ) ) {
467
+ $connected_account_for_term['access_token'] = $return['access_token'];
468
+ $connected_accounts_for_feed[ $term ]['access_token'] = $return['access_token'];
469
+ $connected_account_for_term['expires'] = $return['expires_in'] + time();
470
+ $connected_accounts_for_feed[ $term ]['expires'] = $return['expires_in'] + time();
471
+
472
+ sby_update_or_connect_account( $connected_account_for_term );
473
+ $this->add_report( 'refreshing access token for ' . $connected_account_for_term['channel_id'] );
474
+
475
+ $sby_api_connect_channel = $this->make_api_connection( $connected_account_for_term, 'channels', $params );
476
+ $sby_api_connect_channel->connect();
477
+ if ( ! $sby_api_connect_channel->is_youtube_error() ) {
478
+ $channel_data = $sby_api_connect_channel->get_data();
479
+ $channel_id = SBY_Parse::get_channel_id( $channel_data );
480
+ $this->set_channel_cache( $channel_id, $channel_data );
481
+
482
+ if ( isset( $params['channel_name'] ) ) {
483
+ sby_set_channel_id_from_channel_name( $params['channel_name'], $channel_id );
484
+ $this->set_channel_cache( $params['channel_name'], $channel_data );
485
+ }
486
+
487
+ $this->channels_data[ $channel_id ] = $channel_data;
488
+ $this->channels_data[ $term ] = $channel_data;
489
+
490
+ }
491
+ } else {
492
+ $this->add_report( 'error connecting to channel' );
493
+ }
494
+ } else {
495
+ $api_connect_channels->handle_wp_remote_get_error( $api_connect_channels->get_data() );
496
+ }
497
+ }
498
+ }
499
+
500
+ $playlist = isset( $this->channels_data[ $term ]['items'][0]['contentDetails']['relatedPlaylists']['uploads'] ) ? $this->channels_data[ $term ]['items'][0]['contentDetails']['relatedPlaylists']['uploads'] : false;
501
+
502
+ return $playlist;
503
+ }
504
+
505
+ public function maybe_refresh_token( $term, $connected_account_for_term ) {
506
+ return $connected_account_for_term;
507
+ }
508
+
509
+ public function is_efficient_type( $type ) {
510
+ return true;
511
+ }
512
+
513
+ public function requires_workaround_connection( $type ) {
514
+ return false;
515
+ }
516
+
517
+ public function make_workaround_connection( $connected_account_for_term, $type, $params ) {
518
+ return $this->make_api_connection( $connected_account_for_term, $type, $params );
519
+ }
520
+
521
+
522
+ /**
523
+ * Appends one filtered API request worth of posts for each feed term
524
+ *
525
+ * @param $settings
526
+ * @param array $feed_types_and_terms organized settings related to feed data
527
+ * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
528
+ * @param array $connected_accounts_for_feed connected account data for the
529
+ * feed types and terms
530
+ *
531
+ * @since 1.0
532
+ */
533
+
534
+ public function add_remote_posts( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
535
+ $new_post_sets = array();
536
+ $next_pages = $this->next_pages;
537
+ global $sby_posts_manager;
538
+ $api_requests_delayed = $sby_posts_manager->are_current_api_request_delays();
539
+
540
+ /**
541
+ * Number of posts to retrieve in each API call
542
+ *
543
+ * @param int Minimum number of posts needed in each API request
544
+ * @param array $settings Settings for this feed
545
+ *
546
+ * @since 1.0
547
+ */
548
+ $num = apply_filters( 'sby_num_in_request', (int)$settings['minnum'], $settings );
549
+
550
+ $params = array(
551
+ 'num' => $num
552
+ );
553
+
554
+ $one_successful_connection = false;
555
+ $next_page_found = false;
556
+ $one_api_request_delayed = false;
557
+
558
+
559
+
560
+ foreach ( $feed_types_and_terms as $type => $terms ) {
561
+ if ( is_array( $terms ) && count( $terms ) > 5 ) {
562
+ shuffle( $terms );
563
+ }
564
+ foreach ( $terms as $term_and_params ) {
565
+
566
+ $term = $term_and_params['term'];
567
+ $params = array_merge( $params, $term_and_params['params'] );
568
+
569
+ $connected_accounts_for_feed[ $term ] = $this->maybe_refresh_token( $term, $connected_accounts_for_feed[ $term ] );
570
+ $connected_account_for_term = $connected_accounts_for_feed[ $term ];
571
+
572
+ $play_list = $this->get_play_list_for_term( $type, $term, $connected_account_for_term, $params );
573
+
574
+ if ( ! empty( $next_pages[ $term . '_' . $type ] ) ) {
575
+ $params['nextPageToken'] = $next_pages[ $term . '_' . $type ];
576
+ }
577
+
578
+ if ( $this->is_pageable() ) {
579
+ $this->add_remote_pageable_posts( $settings, $feed_types_and_terms, $connected_accounts_for_feed );
580
+ } else {
581
+ $this->add_remote_non_pageable( $settings, $feed_types_and_terms, $connected_accounts_for_feed );
582
+ }
583
+
584
+ if ( ! $this->is_efficient_type( $type ) && $this->is_pageable() ) {
585
+
586
+ if ( $this->requires_workaround_connection( $type ) ) {
587
+ $api_connect_playlist_items = $this->make_workaround_connection( $connected_account_for_term, $type, $params );
588
+ $this->add_report( 'Workaround API call made for ' . $term );
589
+
590
+ } else {
591
+ if ( $play_list ) {
592
+ $params['playlist_id'] = $play_list;
593
+ $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, 'playlistItems', $params );
594
+ } else {
595
+ $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, $type, $params );
596
+ }
597
+
598
+ $api_connect_playlist_items->connect();
599
+ $this->add_report( 'API call made for ' . $term );
600
+ }
601
+
602
+
603
+ if ( ! $api_connect_playlist_items->is_wp_error() && ! $api_connect_playlist_items->is_youtube_error() ) {
604
+ $one_successful_connection = true;
605
+ $data = $api_connect_playlist_items->get_data();
606
+
607
+ if ( isset( $data['items'][0] ) ) {
608
+ $post_set = $this->filter_posts( $data['items'], $settings );
609
+
610
+ $this->successful_video_api_request_made = true;
611
+
612
+ $new_post_sets[] = $post_set;
613
+ }
614
+
615
+ $next_page = $api_connect_playlist_items->get_next_page( $params );
616
+ $report = is_array( $next_page ) ? implode( ',', $next_page ) : $next_page;
617
+ $this->add_report( 'Next Page ' . $report );
618
+
619
+
620
+ if ( ! empty( $next_page ) ) {
621
+ $next_pages[ $term . '_' . $type ] = $next_page;
622
+ $next_page_found = true;
623
+ } else {
624
+ $next_pages[ $term . '_' . $type ] = false;
625
+ }
626
+ }
627
+
628
+
629
+ $this->num_api_calls++;
630
+
631
+ } else {
632
+
633
+ if ( ! $this->is_pageable() && (int)self::get_channel_status( $term ) !== 1 ) {
634
+ self::update_channel_status( $term, 1 );
635
+ $this->do_page_cache_all = true;
636
+ $play_list = $this->get_play_list_for_term( $type, $term, $connected_account_for_term, $params );
637
+
638
+ $channel_id = isset( $this->channels_data[ $term ] ) ? SBY_Parse::get_channel_id( $this->channels_data[ $term ] ) : '';
639
+ $params['channel_id'] = $channel_id;
640
+ $params['num'] = 50;
641
+
642
+ if ( $play_list ) {
643
+
644
+ $params['playlist_id'] = $play_list;
645
+ if ( ! empty( $next_pages[ $term . '_' . $type ] ) && $next_pages[ $term . '_' . $type ] !== 'rss' ) {
646
+ $params['nextPageToken'] = $next_pages[ $term . '_' . $type ];
647
+ }
648
+
649
+ self::update_channel_status( $term, 1 );
650
+ $this->do_page_cache_all = true;
651
+ $this->add_report( 'using API request to get first 50 videos' );
652
+
653
+ $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, 'playlistItems', $params );
654
+
655
+ $api_connect_playlist_items->connect();
656
+
657
+ if ( ! $api_connect_playlist_items->is_wp_error() && ! $api_connect_playlist_items->is_youtube_error() ) {
658
+ $one_successful_connection = true;
659
+ $data = $api_connect_playlist_items->get_data();
660
+
661
+ if ( isset( $data['items'][0] ) ) {
662
+ $post_set = $this->filter_posts( $data['items'], $settings );
663
+
664
+ $this->successful_video_api_request_made = true;
665
+
666
+ $new_post_sets[] = $post_set;
667
+ }
668
+
669
+ $next_pages[ $term . '_' . $type ] = false;
670
+ }
671
+ } else {
672
+ $this->add_report( 'no first playlist' );
673
+ }
674
+
675
+ } elseif ( ! $this->is_pageable()
676
+ && isset( $params['channel_id'] )
677
+ && (! isset( $next_pages[ $term . '_' . $type ] ) || $next_pages[ $term . '_' . $type ] !== 'rss') ) {
678
+
679
+ $rss_connect_playlist_items = new SBY_RSS_Connect( 'playlistItems', $params );
680
+ $this->add_report( 'RSS call made for ' . $term );
681
+
682
+ $rss_connect_playlist_items->connect();
683
+
684
+ $one_successful_connection = true;
685
+
686
+ $data = $rss_connect_playlist_items->get_data();
687
+
688
+ if ( isset( $data[0] ) ) {
689
+ $data = array(
690
+ 'items' => $data
691
+ );
692
+ $post_set = $this->filter_posts( $data['items'], $settings );
693
+
694
+ $this->successful_video_api_request_made = true;
695
+
696
+ if ( count( $post_set ) > 14 ) {
697
+ if ( (int)self::get_channel_status( $term ) !== 1 ) {
698
+ $next_pages[ $term . '_' . $type ] = 'rss';
699
+ $next_page_found = true;
700
+ } else {
701
+ $this->add_report( 'RSS update only for ' . $term );
702
+ $post_set = $this->merge_cached_posts( $post_set, $term );
703
+ $next_pages[ $term . '_' . $type ] = false;
704
+ }
705
+ } else {
706
+ $next_pages[ $term . '_' . $type ] = false;
707
+ }
708
+
709
+ $new_post_sets[] = $post_set;
710
+
711
+ }
712
+ } elseif ( isset( $connected_account_for_term['rss_only'] ) ) {
713
+ $rss_connect_playlist_items = new SBY_RSS_Connect( 'playlistItems', $params );
714
+ $this->add_report( 'RSS Only call made for ' . $term );
715
+
716
+ $rss_connect_playlist_items->connect();
717
+
718
+ $one_successful_connection = true;
719
+
720
+ $data = $rss_connect_playlist_items->get_data();
721
+ $next_pages[ $term . '_' . $type ] = false;
722
+
723
+ if ( isset( $data[0] ) ) {
724
+ $data = array(
725
+ 'items' => $data
726
+ );
727
+ $post_set = $this->filter_posts( $data['items'], $settings );
728
+
729
+ $this->successful_video_api_request_made = true;
730
+ $new_post_sets[] = $post_set;
731
+ }
732
+ } else {
733
+
734
+ if ( ! $api_requests_delayed
735
+ && (! isset( $next_pages[ $term . '_' . $type ] ) || $next_pages[ $term . '_' . $type ] !== false) ) {
736
+
737
+ $play_list = $this->get_play_list_for_term( $type, $term, $connected_account_for_term, $params );
738
+
739
+ $channel_id = isset( $this->channels_data[ $term ] ) ? SBY_Parse::get_channel_id( $this->channels_data[ $term ] ) : '';
740
+ $params['channel_id'] = $channel_id;
741
+
742
+ if ( $play_list ) {
743
+
744
+ $params['playlist_id'] = $play_list;
745
+ if ( ! empty( $next_pages[ $term . '_' . $type ] ) && $next_pages[ $term . '_' . $type ] !== 'rss' ) {
746
+ $params['nextPageToken'] = $next_pages[ $term . '_' . $type ];
747
+ }
748
+
749
+ if ( isset( $next_pages[ $term . '_' . $type ] ) && $next_pages[ $term . '_' . $type ] === 'rss' ) {
750
+ self::update_channel_status( $term, 1 );
751
+ $this->do_page_cache_all = true;
752
+ $this->add_report( 'using API request to get first 50 videos' );
753
+ } else {
754
+ $this->add_report( 'using API request to get more videos' );
755
+ }
756
+
757
+ $api_connect_playlist_items = $this->make_api_connection( $connected_account_for_term, 'playlistItems', $params );
758
+
759
+ $api_connect_playlist_items->connect();
760
+
761
+ if ( ! $api_connect_playlist_items->is_wp_error() && ! $api_connect_playlist_items->is_youtube_error() ) {
762
+ $one_successful_connection = true;
763
+ $data = $api_connect_playlist_items->get_data();
764
+
765
+ if ( isset( $data['items'][0] ) ) {
766
+ $post_set = $this->filter_posts( $data['items'], $settings );
767
+
768
+ $this->successful_video_api_request_made = true;
769
+
770
+ $new_post_sets[] = $post_set;
771
+ }
772
+
773
+ $next_page = $this->is_pageable() ? $api_connect_playlist_items->get_next_page() : false;
774
+ if ( ! empty( $next_page ) ) {
775
+ $next_pages[ $term . '_' . $type ] = $next_page;
776
+ $next_page_found = true;
777
+ } else {
778
+ $next_pages[ $term . '_' . $type ] = false;
779
+ }
780
+ }
781
+ } else {
782
+ $this->add_report( 'no first playlist' );
783
+ }
784
+
785
+ if ( ! $this->is_pageable()
786
+ && empty( $next_pages[ $term . '_' . $type ] )
787
+ && ! empty( $params['channel_id'] ) ) {
788
+ $this->add_report( 'using RSS to get first 15' );
789
+
790
+ $rss_connect_playlist_items = new SBY_RSS_Connect( 'playlistItems', $params );
791
+
792
+ $rss_connect_playlist_items->connect();
793
+
794
+ $one_successful_connection = true;
795
+
796
+ $data = $rss_connect_playlist_items->get_data();
797
+
798
+ if ( isset( $data[0] ) ) {
799
+ $data = array(
800
+ 'items' => $data
801
+ );
802
+ $post_set = $this->filter_posts( $data['items'], $settings );
803
+
804
+ $this->successful_video_api_request_made = true;
805
+
806
+
807
+ if ( count( $post_set ) > 14 ) {
808
+ if ( (int)self::get_channel_status( $term ) !== 1 ) {
809
+ $next_pages[ $term . '_' . $type ] = 'rss';
810
+ $next_page_found = true;
811
+ } else {
812
+ $this->add_report( 'RSS Only' . $term );
813
+ $post_set = $this->merge_cached_posts( $post_set, $term );
814
+ $next_pages[ $term . '_' . $type ] = false;
815
+ }
816
+ } else {
817
+ $next_pages[ $term . '_' . $type ] = false;
818
+ }
819
+
820
+ $new_post_sets[] = $post_set;
821
+
822
+ }
823
+ } else {
824
+ $this->num_api_calls++;
825
+ }
826
+
827
+ }
828
+ }
829
+ }
830
+
831
+ }
832
+
833
+ }
834
+
835
+ if ( ! $one_successful_connection || ($one_api_request_delayed && empty( $new_post_sets )) ) {
836
+ $this->should_use_backup = true;
837
+ }
838
+ $posts = $this->merge_posts( $new_post_sets, $settings );
839
+
840
+ $posts = $this->sort_posts( $posts, $settings );
841
+
842
+ if ( ! empty( $this->post_data ) && is_array( $this->post_data ) ) {
843
+ $posts = array_merge( $this->post_data, $posts );
844
+ }
845
+
846
+ $this->post_data = $posts;
847
+
848
+ if ( isset( $next_page_found ) && $next_page_found ) {
849
+ $this->next_pages = $next_pages;
850
+ } else {
851
+ $this->next_pages = false;
852
+ }
853
+ }
854
+
855
+ public function add_remote_pageable_posts() {
856
+
857
+ }
858
+
859
+ public function add_remote_non_pageable() {
860
+
861
+ }
862
+
863
+ private function is_pageable() {
864
+ global $sby_settings;
865
+
866
+ return ! empty( $sby_settings['api_key'] );
867
+ }
868
+
869
+ public function merge_cached_posts( $current_posts, $channel_id ) {
870
+ $args = array(
871
+ 'post_type' => SBY_CPT,
872
+ 'post_status' => array( 'publish', 'pending', 'draft' ),
873
+ 'orderby' => 'date',
874
+ 'order' => 'DESC',
875
+ 'posts_per_page' => 80,
876
+ 'meta_query' => array(
877
+ array(
878
+ 'value' => $channel_id,
879
+ 'key' => 'sby_channel_id'
880
+ )
881
+ )
882
+ );
883
+ $feed_videos = new WP_Query( $args );
884
+
885
+ if ( $feed_videos->have_posts() ) {
886
+ $posts = array();
887
+ while ( $feed_videos->have_posts() ) {
888
+ $feed_videos->the_post();
889
+ $json = get_post_meta( get_the_ID(), 'sby_json', true );
890
+ if ( $json ) {
891
+ $posts[] = json_decode( $json, true );
892
+ }
893
+ }
894
+
895
+ wp_reset_postdata();
896
+ $this->add_report( 'merging cached posts' );
897
+
898
+ $posts = array_merge( $current_posts, $posts );
899
+
900
+ return $posts;
901
+ } else {
902
+ $this->add_report( 'no cached posts found' );
903
+ wp_reset_postdata();
904
+
905
+ return $current_posts;
906
+ }
907
+ }
908
+
909
+ /**
910
+ * Connects to the YouTube API and records returned data. Will use channel data if already
911
+ * set by the regular feed
912
+ *
913
+ * @param $settings
914
+ * @param array $feed_types_and_terms organized settings related to feed data
915
+ * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
916
+ * @param array $connected_accounts_for_feed connected account data for the
917
+ * feed types and terms
918
+ *
919
+ * @since 1.0
920
+ */
921
+ public function set_remote_header_data( $settings, $feed_types_and_terms, $connected_accounts_for_feed ) {
922
+ $first_user = $this->get_first_user( $feed_types_and_terms, $settings );
923
+ $this->header_data = false;
924
+ $existing_channel_cache = $this->get_channel_cache( $first_user );
925
+
926
+ if ( $existing_channel_cache ) {
927
+ $this->channels_data[ $first_user ] = $existing_channel_cache;
928
+ $this->add_report( 'header data for ' . $first_user . ' exists in cache' );
929
+ }
930
+
931
+ if ( isset( $this->channels_data[ $first_user ] ) && ! $this->is_pageable() ) {
932
+ $this->header_data = $this->channels_data[ $first_user ];
933
+ } elseif ( ! empty( $first_user ) ) {
934
+ $connected_account_for_term = sby_get_first_connected_account();
935
+ if ( $connected_account_for_term['expires'] < time() + 5 ) {
936
+ $error_message = '<p><b>' . __( 'Reconnect to YouTube to show this feed.', 'custom-facebook-feed' ) . '</b></p>';
937
+ $error_message .= '<p>' . __( 'To create a new feed, first connect to YouTube using the "Connect to YouTube to Create a Feed" button on the settings page and connect any account.', SBY_TEXT_DOMAIN ) . '</p>';
938
+
939
+ if ( current_user_can( 'manage_youtube_feed_options' ) ) {
940
+ $error_message .= '<a href="' . admin_url( 'admin.php?page=youtube-feed' ) . '" target="blank" rel="noopener nofollow">' . __( 'Reconnect in the YouTube Feed Settings Area' ) . '</a>';
941
+ }
942
+ global $sby_posts_manager;
943
+
944
+ $sby_posts_manager->add_frontend_error( 'accesstoken', $error_message );
945
+ $sby_posts_manager->add_error( 'accesstoken', array( 'Trying to connect a new account', $error_message ) );
946
+ } else {
947
+ $channel_params_type = strpos( $first_user, 'UC' ) !== 0 ? 'channel_name' : 'channel_id';
948
+ $params[ $channel_params_type ] = $first_user;
949
+ $connection = $this->make_api_connection( $connected_account_for_term, 'channels', $params );
950
+
951
+ $connection->connect();
952
+ $this->add_report( 'api call made for header - ' . $first_user );
953
+
954
+ if ( ! $connection->is_wp_error() && ! $connection->is_youtube_error() ) {
955
+ $this->header_data = $connection->get_data();
956
+ $channel_id = SBY_Parse::get_channel_id( $this->header_data );
957
+ $this->set_channel_cache( $channel_id, $this->header_data );
958
+ $this->channels_data[ $channel_id ] = $this->header_data;
959
+ $this->channels_data[ $first_user ] = $this->header_data;
960
+
961
+ if ( isset( $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) && $connected_accounts_for_feed[ $first_user ]['local_avatar'] ) {
962
+ $upload = wp_upload_dir();
963
+ $resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBY_UPLOADS_NAME );
964
+
965
+ $full_file_name = $resized_url . $this->header_data['username'] . '.jpg';
966
+ $this->header_data['local_avatar'] = $full_file_name;
967
+ }
968
+ } else {
969
+ if ( $connection->is_wp_error() ) {
970
+ SBY_API_Connect::handle_wp_remote_get_error( $connection->get_wp_error() );
971
+ } else {
972
+ SBY_API_Connect::handle_youtube_error( $connection->get_data(), $connected_accounts_for_feed[ $first_user ], 'header' );
973
+ }
974
+ }
975
+ }
976
+ }
977
+ }
978
+
979
+ /**
980
+ * Stores feed data in a transient for a specified time
981
+ *
982
+ * @param int $cache_time
983
+ *
984
+ * @since 1.0
985
+ */
986
+ public function cache_feed_data( $cache_time ) {
987
+ if ( ! empty( $this->post_data ) || ! empty( $this->next_pages ) ) {
988
+ $this->remove_duplicate_posts();
989
+ $this->trim_posts_to_max();
990
+
991
+ $post_data = $this->post_data;
992
+
993
+ if (! isset( $post_data[0]['iframe'] )) {
994
+ $to_cache = array(
995
+ 'data' => $this->post_data,
996
+ 'pagination' => $this->next_pages
997
+ );
998
+
999
+ set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
1000
+ } else {
1001
+ $this->add_report( 'iframe not caching' );
1002
+ }
1003
+
1004
+
1005
+ } else {
1006
+ $this->add_report( 'no data not caching' );
1007
+ }
1008
+ }
1009
+
1010
+ /**
1011
+ * Stores feed data with additional data specifically for cron caching
1012
+ *
1013
+ * @param array $to_cache feed data with additional things like the shortcode
1014
+ * settings, when the cache was last requested, when new posts were last retrieved
1015
+ * @param int $cache_time how long the cache will last
1016
+ *
1017
+ * @since 1.0
1018
+ */
1019
+ public function set_cron_cache( $to_cache, $cache_time ) {
1020
+ if ( ! empty( $this->post_data )
1021
+ || ! empty( $this->next_pages )
1022
+ || ! empty( $to_cache['data'] ) ) {
1023
+ $this->remove_duplicate_posts();
1024
+ $this->trim_posts_to_max();
1025
+
1026
+ $to_cache['data'] = isset( $to_cache['data'] ) ? $to_cache['data'] : $this->post_data;
1027
+ $to_cache['pagination'] = isset( $to_cache['next_pages'] ) ? $to_cache['next_pages'] : $this->next_pages;
1028
+ $to_cache['atts'] = isset( $to_cache['atts'] ) ? $to_cache['atts'] : $this->transient_atts;
1029
+ $to_cache['last_requested'] = isset( $to_cache['last_requested'] ) ? $to_cache['last_requested'] : time();
1030
+ $to_cache['last_retrieve'] = isset( $to_cache['last_retrieve'] ) ? $to_cache['last_retrieve'] : $this->last_retrieve;
1031
+
1032
+ set_transient( $this->regular_feed_transient_name, wp_json_encode( $to_cache ), $cache_time );
1033
+ } else {
1034
+ $this->add_report( 'no data not caching' );
1035
+ }
1036
+
1037
+ }
1038
+
1039
+ /**
1040
+ * Stores header data for a specified time as a transient
1041
+ *
1042
+ * @param int $cache_time
1043
+ * @param bool $save_backup
1044
+ *
1045
+ * @since 1.0
1046
+ */
1047
+ public function cache_header_data( $cache_time, $save_backup = true ) {
1048
+ if ( $this->header_data ) {
1049
+ set_transient( $this->header_transient_name, wp_json_encode( $this->header_data ), $cache_time );
1050
+
1051
+ if ( $save_backup ) {
1052
+ update_option( $this->backup_header_transient_name, wp_json_encode( $this->header_data ), false );
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
+ /**
1058
+ * Used to randomly trigger an updating of the last requested data for cron caching
1059
+ *
1060
+ * @return bool
1061
+ *
1062
+ * @since 1.0
1063
+ */
1064
+ public function should_update_last_requested() {
1065
+ return (rand( 1, 20 ) === 20);
1066
+ }
1067
+
1068
+ /**
1069
+ * Determines if pagination can and should be used based on settings and available feed data
1070
+ *
1071
+ * @param array $settings
1072
+ * @param int $offset
1073
+ *
1074
+ * @return bool
1075
+ *
1076
+ * @since 1.0
1077
+ */
1078
+ public function should_use_pagination( $settings, $offset = 0 ) {
1079
+ $posts_available = count( $this->post_data ) - ($offset + $settings['num']);
1080
+ $show_loadmore_button_by_settings = ($settings['showbutton'] == 'on' || $settings['showbutton'] == 'true' || $settings['showbutton'] == true ) && $settings['showbutton'] !== 'false';
1081
+
1082
+ if ( $show_loadmore_button_by_settings ) {
1083
+ // used for permanent and whitelist feeds
1084
+ if ( $this->feed_is_complete( $settings, $offset ) ) {
1085
+ $this->add_report( 'no pagination, feed complete' );
1086
+ return false;
1087
+ }
1088
+ if ( $posts_available > 0 ) {
1089
+ $this->add_report( 'do pagination, posts available' );
1090
+ return true;
1091
+ }
1092
+ $pages = $this->next_pages;
1093
+
1094
+ if ( $pages && ! $this->should_use_backup() ) {
1095
+ foreach ( $pages as $page ) {
1096
+ if ( ! empty( $page ) ) {
1097
+ return true;
1098
+ }
1099
+ }
1100
+ }
1101
+
1102
+ }
1103
+
1104
+
1105
+ $this->add_report( 'no pagination, no posts available' );
1106
+
1107
+ return false;
1108
+ }
1109
+
1110
+ public static function get_channel_status( $channel ) {
1111
+ $channel_setting = get_option( 'sby_channel_status', array() );
1112
+
1113
+ if ( isset( $channel_setting[ $channel ] ) ) {
1114
+ return $channel_setting[ $channel ];
1115
+ }
1116
+
1117
+ return 0;
1118
+ }
1119
+
1120
+ public static function update_channel_status( $channel, $status ) {
1121
+ $channel_setting = get_option( 'sby_channel_status', array() );
1122
+
1123
+ $channel_setting[ $channel ] = $status;
1124
+
1125
+ update_option( 'sby_channel_status', $channel_setting, false );
1126
+ }
1127
+
1128
+ /**
1129
+ * Generates the HTML for the feed if post data is available. Although it seems
1130
+ * some of the variables ar not used they are set here to hide where they
1131
+ * come from when used in the feed templates.
1132
+ *
1133
+ * @param array $settings
1134
+ * @param array $atts
1135
+ * @param array $feed_types_and_terms organized settings related to feed data
1136
+ * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
1137
+ * @param array $connected_accounts_for_feed connected account data for the
1138
+ * feed types and terms
1139
+ *
1140
+ * @return false|string
1141
+ *
1142
+ * @since 1.0
1143
+ */
1144
+ public function get_the_feed_html( $settings, $atts, $feed_types_and_terms, $connected_accounts_for_feed ) {
1145
+ global $sby_posts_manager;
1146
+
1147
+ if ( empty( $this->post_data ) && ! empty( $connected_accounts_for_feed ) ) {
1148
+ $error = '<p><b>' . __( 'Error: No videos found.', SBY_TEXT_DOMAIN ) . '</b>';
1149
+ $error .= '<p>' . __( 'Make sure this is a valid channel ID and that the channel has videos available on youtube.com.', SBY_TEXT_DOMAIN ) . '</p>';
1150
+
1151
+ $sby_posts_manager->add_frontend_error( 'noposts', $error );
1152
+ }
1153
+
1154
+ $posts = array_slice( $this->post_data, 0, $settings['minnum'] );
1155
+ $header_data = ! empty( $this->header_data ) ? $this->header_data : false;
1156
+
1157
+ $first_username = false;
1158
+ if ( $header_data ) {
1159
+ $first_username = SBY_Parse::get_channel_id( $header_data );
1160
+ } elseif ( isset( $this->post_data[0] ) ) { // in case no connected account for feed
1161
+ $first_username = SBY_Parse::get_channel_id( $this->post_data[0] );
1162
+ }
1163
+
1164
+ $use_pagination = $this->should_use_pagination( $settings, 0 );
1165
+
1166
+ $feed_id = $this->regular_feed_transient_name;
1167
+ $shortcode_atts = ! empty( $atts ) ? wp_json_encode( $atts ) : '{}';
1168
+
1169
+ $settings['header_outside'] = false;
1170
+ $settings['header_inside'] = false;
1171
+ if ( $header_data && $settings['showheader'] ) {
1172
+ $settings['header_inside'] = true;
1173
+ }
1174
+
1175
+ $other_atts = '';
1176
+
1177
+ // The plugin settings did not mention heightunit but instead accepts px or % in the height option directly. This is a check for this to make sure heightunit is assigned properly.
1178
+ $settings['heightunit'] = ( strpos( $settings['height'], 'px' ) === false && strpos( $settings['height'], '%' ) === false ) ? $settings['heightunit'] : (strpos( $settings['height'], 'px' ) !== false ? 'px' : '%' );
1179
+
1180
+
1181
+ $classes = array();
1182
+ if ( empty( $settings['widthresp'] ) || $settings['widthresp'] == 'on' || $settings['widthresp'] == 'true' || $settings['widthresp'] === true ) {
1183
+ if ( $settings['widthresp'] !== 'false' ) {
1184
+ $classes[] = 'sby_width_resp';
1185
+ }
1186
+ }
1187
+ if ( ! empty( $settings['class'] ) ) {
1188
+ $classes[] = esc_attr( $settings['class'] );
1189
+ }
1190
+ if ( ! empty( $settings['height'] )
1191
+ && (((int)$settings['height'] < 100 && $settings['heightunit'] === '%') || $settings['heightunit'] === 'px') ) {
1192
+ $classes[] = 'sby_fixed_height';
1193
+ }
1194
+ if ( ! empty( $settings['disablemobile'] )
1195
+ && ($settings['disablemobile'] == 'on' || $settings['disablemobile'] == 'true' || $settings['disablemobile'] == true) ) {
1196
+ if ( $settings['disablemobile'] !== 'false' ) {
1197
+ $classes[] = 'sby_disable_mobile';
1198
+ }
1199
+ }
1200
+
1201
+ $additional_classes = '';
1202
+ if ( ! empty( $classes ) ) {
1203
+ $additional_classes = ' ' . implode( ' ', $classes );
1204
+ }
1205
+
1206
+ $other_atts = $this->add_other_atts( $other_atts, $settings );
1207
+
1208
+ $flags = array();
1209
+
1210
+ if ( $this->successful_video_api_request_made && ! empty( $posts ) ) {
1211
+ if ( $settings['storage_process'] === 'page' ) {
1212
+ $this_posts = $posts;
1213
+ if ( $this->do_page_cache_all ) {
1214
+ $this_posts = $this->post_data;
1215
+ }
1216
+ $this->add_report( 'Adding videos to wp_posts ' . count( $this_posts ) );
1217
+
1218
+ sby_process_post_set_caching( $this_posts, $feed_id );
1219
+ } elseif ( $settings['storage_process'] === 'background' ) {
1220
+ $flags[] = 'checkWPPosts';
1221
+ if ( $this->do_page_cache_all ) {
1222
+ $this->add_report( 'Flagging videos to wp_posts ' . count( $this->post_data ) );
1223
+ $flags[] = 'cacheAll';
1224
+ }
1225
+ }
1226
+ }
1227
+
1228
+ if ( $settings['disable_resize'] ) {
1229
+ $flags[] = 'resizeDisable';
1230
+ } elseif ( $settings['favor_local'] ) {
1231
+ $flags[] = 'favorLocal';
1232
+ }
1233
+
1234
+ if ( $settings['disable_js_image_loading'] ) {
1235
+ $flags[] = 'imageLoadDisable';
1236
+ }
1237
+ if ( $settings['ajax_post_load'] ) {
1238
+ $flags[] = 'ajaxPostLoad';
1239
+ }
1240
+ if ( $settings['playerratio'] === '3:4' ) {
1241
+ $flags[] = 'narrowPlayer';
1242
+ }
1243
+ if ( SBY_GDPR_Integrations::doing_gdpr( $settings ) ) {
1244
+ $flags[] = 'gdpr';
1245
+ }
1246
+ if ( ! is_admin()
1247
+ && SBY_Feed_Locator::should_do_ajax_locating( $this->regular_feed_transient_name, get_the_ID() ) ) {
1248
+ $flags[] = 'locator';
1249
+ }
1250
+ if ( $settings['disablecdn'] ) {
1251
+ $flags[] = 'disablecdn';
1252
+ }
1253
+ if ( isset( $_GET['sby_debug'] ) ) {
1254
+ $flags[] = 'debug';
1255
+ }
1256
+
1257
+ if ( ! empty( $flags ) ) {
1258
+ $other_atts .= ' data-sby-flags="' . implode(',', $flags ) . '"';
1259
+ }
1260
+ $other_atts .= ' data-postid="' . get_the_ID() . '"';
1261
+ if ( $settings['layout'] === 'grid' || $settings['layout'] === 'carousel' ) {
1262
+ $other_atts .= ' data-sby-supports-lightbox="1"';
1263
+ }
1264
+ $icon_type = $settings['font_method'];
1265
+
1266
+ ob_start();
1267
+ include sby_get_feed_template_part( 'feed', $settings );
1268
+ $html = ob_get_contents();
1269
+ ob_get_clean();
1270
+
1271
+ if ( $settings['ajaxtheme'] ) {
1272
+ $html .= $this->get_ajax_page_load_html();
1273
+ }
1274
+
1275
+ return $html;
1276
+ }
1277
+
1278
+ /**
1279
+ * Generates HTML for individual sby_item elements
1280
+ *
1281
+ * @param array $settings
1282
+ * @param int $offset
1283
+ * @param array $feed_types_and_terms organized settings related to feed data
1284
+ * (ex. 'user' => array( 'smashballoon', 'customyoutubefeed' )
1285
+ * @param array $connected_accounts_for_feed connected account data for the
1286
+ * feed types and terms
1287
+ *
1288
+ * @return false|string
1289
+ *
1290
+ * @since 1.0
1291
+ */
1292
+ public function get_the_items_html( $settings, $offset, $feed_types_and_terms = array(), $connected_accounts_for_feed = array() ) {
1293
+ if ( empty( $this->post_data ) ) {
1294
+ ob_start();
1295
+ $html = ob_get_contents();
1296
+ ob_get_clean(); ?>
1297
+ <p><?php _e( 'No posts found.', SBY_TEXT_DOMAIN ); ?></p>
1298
+ <?php
1299
+ $html = ob_get_contents();
1300
+ ob_get_clean();
1301
+ return $html;
1302
+ }
1303
+
1304
+ $posts = array_slice( $this->post_data, $offset, $settings['num'] );
1305
+
1306
+ ob_start();
1307
+
1308
+ $this->posts_loop( $posts, $settings, $offset );
1309
+
1310
+ $html = ob_get_contents();
1311
+ ob_get_clean();
1312
+
1313
+ return $html;
1314
+ }
1315
+
1316
+ /**
1317
+ * Overwritten in the Pro version
1318
+ *
1319
+ * @return object
1320
+ */
1321
+ public function make_api_connection( $connected_account_or_page, $type = NULL, $params = NULL ) {
1322
+ return new SBY_API_Connect( $connected_account_or_page, $type, $params );
1323
+ }
1324
+
1325
+ /**
1326
+ * When the feed is loaded with AJAX, the JavaScript for the plugin
1327
+ * needs to be triggered again. This function is a workaround that adds
1328
+ * the file and settings to the page whenever the feed is generated.
1329
+ *
1330
+ * @return string
1331
+ *
1332
+ * @since 1.0
1333
+ */
1334
+ public static function get_ajax_page_load_html() {
1335
+ global $sby_settings;
1336
+
1337
+ $js_options = array(
1338
+ 'adminAjaxUrl' => admin_url( 'admin-ajax.php' ),
1339
+ 'placeholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png',
1340
+ 'placeholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder-narrow.png',
1341
+ 'lightboxPlaceholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder.png',
1342
+ 'lightboxPlaceholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder-narrow.png',
1343
+ 'autoplay' => $sby_settings['playvideo'] === 'automatically',
1344
+ 'semiEagerload' => $sby_settings['eagerload'],
1345
+ 'eagerload' => false
1346
+ );
1347
+
1348
+ $encoded_options = wp_json_encode( $js_options );
1349
+
1350
+ $js_option_html = '<script type="text/javascript">if (typeof sbyOptions === "undefined") var sbyOptions = ' . $encoded_options . ';</script>';
1351
+ $js_option_html .= "<script type='text/javascript' src='" . trailingslashit( SBY_PLUGIN_URL ) . 'js/sb-youtube.min.js?ver=' . SBYVER . "'></script>";
1352
+
1353
+ return $js_option_html;
1354
+ }
1355
+
1356
+ /**
1357
+ * Overwritten in the Pro version
1358
+ *
1359
+ * @param $feed_types_and_terms
1360
+ *
1361
+ * @return string
1362
+ *
1363
+ * @since 2.1/5.2
1364
+ */
1365
+ public function get_first_user( $feed_types_and_terms, $settings = array() ) {
1366
+ if ( isset( $feed_types_and_terms['channels'][0] ) ) {
1367
+ return $feed_types_and_terms['channels'][0]['term'];
1368
+ } else {
1369
+ return '';
1370
+ }
1371
+ }
1372
+
1373
+ public function do_page_cache_all() {
1374
+ return $this->do_page_cache_all;
1375
+ }
1376
+
1377
+ public function successful_video_api_request_made() {
1378
+ return $this->successful_video_api_request_made;
1379
+ }
1380
+
1381
+ /**
1382
+ * Adds recorded strings to an array
1383
+ *
1384
+ * @param $to_add
1385
+ *
1386
+ * @since 1.0
1387
+ */
1388
+ public function add_report( $to_add ) {
1389
+ $this->report[] = $to_add;
1390
+ }
1391
+
1392
+ /**
1393
+ * @return array
1394
+ *
1395
+ * @since 1.0
1396
+ */
1397
+ public function get_report() {
1398
+ return $this->report;
1399
+ }
1400
+
1401
+ /**
1402
+ * Additional options/settings added to the main div
1403
+ * for the feed
1404
+ *
1405
+ * Overwritten in the Pro version
1406
+ *
1407
+ * @param $other_atts
1408
+ * @param $settings
1409
+ *
1410
+ * @return string
1411
+ */
1412
+ protected function add_other_atts( $other_atts, $settings ) {
1413
+ return '';
1414
+ }
1415
+
1416
+ /**
1417
+ * Used for filtering a single API request worth of posts
1418
+ *
1419
+ * Overwritten in the Pro version
1420
+ *
1421
+ * @param array $post_set a single set of post data from the api
1422
+ *
1423
+ * @return mixed|array
1424
+ *
1425
+ * @since 1.0
1426
+ */
1427
+ protected function filter_posts( $post_set, $settings = array() ) {
1428
+ // array_unique( $post_set, SORT_REGULAR);
1429
+
1430
+ return $post_set;
1431
+ }
1432
+
1433
+ protected function remove_duplicate_posts() {
1434
+ $posts = $this->post_data;
1435
+ $ids_in_feed = array();
1436
+ $non_duplicate_posts = array();
1437
+ $removed = array();
1438
+
1439
+ foreach ( $posts as $post ) {
1440
+ $post_id = SBY_Parse::get_video_id( $post );
1441
+ if ( ! in_array( $post_id, $ids_in_feed, true ) ) {
1442
+ $ids_in_feed[] = $post_id;
1443
+ $non_duplicate_posts[] = $post;
1444
+ } else {
1445
+ $removed[] = $post_id;
1446
+ }
1447
+ }
1448
+
1449
+ $this->add_report( 'removed duplicates: ' . implode(', ', $removed ) );
1450
+ $this->set_post_data( $non_duplicate_posts );
1451
+ }
1452
+
1453
+ /**
1454
+ * Used for limiting the cache size
1455
+ *
1456
+ * @since 2.0/5.1.1
1457
+ */
1458
+ protected function trim_posts_to_max() {
1459
+ if ( ! is_array( $this->post_data ) ) {
1460
+ return;
1461
+ }
1462
+
1463
+ $max = apply_filters( 'sby_max_cache_size', 500 );
1464
+ $this->set_post_data( array_slice( $this->post_data , 0, $max ) );
1465
+
1466
+ }
1467
+
1468
+ /**
1469
+ * Used for permanent feeds or white list feeds to
1470
+ * stop pagination if all posts are already added
1471
+ *
1472
+ * Overwritten in the Pro version
1473
+ *
1474
+ * @param array $settings
1475
+ * @param int $offset
1476
+ *
1477
+ * @return bool
1478
+ *
1479
+ * @since 1.0
1480
+ */
1481
+ protected function feed_is_complete( $settings, $offset = 0 ) {
1482
+ return false;
1483
+ }
1484
+
1485
+ /**
1486
+ * Iterates through post data and tracks the index of the current post.
1487
+ * The actual post ids of the posts are stored in an array so the plugin
1488
+ * can search for local images that may be available.
1489
+ *
1490
+ * @param array $posts final filtered post data for the feed
1491
+ * @param array $settings
1492
+ * @param int $offset
1493
+ *
1494
+ * @since 1.0
1495
+ */
1496
+ protected function posts_loop( $posts, $settings, $offset = 0 ) {
1497
+
1498
+ $image_ids = array();
1499
+ $post_index = $offset;
1500
+ if ( ! isset( $settings['feed_id'] ) ) {
1501
+ $settings['feed_id'] = $this->regular_feed_transient_name;
1502
+ }
1503
+ $misc_data = $this->get_misc_data( $settings['feed_id'], $posts );
1504
+ $icon_type = $settings['font_method'];
1505
+
1506
+ foreach ( $posts as $post ) {
1507
+ $image_ids[] = SBY_Parse::get_post_id( $post );
1508
+ include sby_get_feed_template_part( 'item', $settings );
1509
+ $post_index++;
1510
+ }
1511
+
1512
+ $this->image_ids_post_set = $image_ids;
1513
+ }
1514
+
1515
+ /**
1516
+ * Uses array of API request results and merges them based on how
1517
+ * the feed should be sorted. Mixed feeds are always sorted alternating
1518
+ * since there is no post date for hashtag feeds.
1519
+ *
1520
+ * @param array $post_sets an array of single API request worth
1521
+ * of posts
1522
+ * @param array $settings
1523
+ *
1524
+ * @return array
1525
+ *
1526
+ * @since 1.0
1527
+ */
1528
+ private function merge_posts( $post_sets, $settings ) {
1529
+
1530
+ $merged_posts = array();
1531
+ if ( $settings['sortby'] === 'alternate' ) {
1532
+ // don't bother merging posts if there is only one post set
1533
+ if ( isset( $post_sets[1] ) ) {
1534
+ $min_cycles = max( 1, (int)$settings['num'] );
1535
+ for( $i = 0; $i <= $min_cycles; $i++ ) {
1536
+ foreach ( $post_sets as $post_set ) {
1537
+ if ( isset( $post_set[ $i ] ) && isset( $post_set[ $i ]['id'] ) ) {
1538
+ $merged_posts[] = $post_set[ $i ];
1539
+ }
1540
+ }
1541
+ }
1542
+ } else {
1543
+ $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1544
+ }
1545
+ } elseif ( $settings['sortby'] === 'api' ) {
1546
+ if ( isset( $post_sets[0] ) ) {
1547
+ foreach ( $post_sets as $post_set ) {
1548
+ $merged_posts = array_merge( $merged_posts, $post_set );
1549
+ }
1550
+ }
1551
+ } else {
1552
+ // don't bother merging posts if there is only one post set
1553
+ if ( isset( $post_sets[1] ) ) {
1554
+ foreach ( $post_sets as $post_set ) {
1555
+ if ( isset( $post_set[0]['id'] ) ) {
1556
+ $merged_posts = array_merge( $merged_posts, $post_set );
1557
+ }
1558
+ }
1559
+ } else {
1560
+ $merged_posts = isset( $post_sets[0] ) ? $post_sets[0] : array();
1561
+ }
1562
+ }
1563
+
1564
+
1565
+ return $merged_posts;
1566
+ }
1567
+
1568
+ /**
1569
+ * Sorts a post set based on sorting settings. Sorting by "alternate"
1570
+ * is done when merging posts for efficiency's sake so the post set is
1571
+ * just returned as it is.
1572
+ *
1573
+ * @param array $post_set
1574
+ * @param array $settings
1575
+ *
1576
+ * @return mixed|array
1577
+ *
1578
+ * @since 1.0
1579
+ */
1580
+ protected function sort_posts( $post_set, $settings ) {
1581
+ if ( empty( $post_set ) ) {
1582
+ return $post_set;
1583
+ }
1584
+
1585
+ // sorting done with "merge_posts" to be more efficient
1586
+ if ( $settings['sortby'] === 'alternate' || $settings['sortby'] === 'api' ) {
1587
+ $return_post_set = $post_set;
1588
+ } elseif ( $settings['sortby'] === 'random' ) {
1589
+ /*
1590
+ * randomly selects posts in a random order. Cache saves posts
1591
+ * in this random order so paginating does not cause some posts to show up
1592
+ * twice or not at all
1593
+ */
1594
+ usort($post_set, 'sby_rand_sort' );
1595
+ $return_post_set = $post_set;
1596
+
1597
+ } else {
1598
+ // compares posted on dates of posts
1599
+ usort($post_set, 'sby_date_sort' );
1600
+ $return_post_set = $post_set;
1601
+ }
1602
+
1603
+ /**
1604
+ * Apply a custom sorting of posts
1605
+ *
1606
+ * @param array $return_post_set Ordered set of filtered posts
1607
+ * @param array $settings Settings for this feed
1608
+ *
1609
+ * @since 1.0
1610
+ */
1611
+
1612
+ return apply_filters( 'sby_sorted_posts', $return_post_set, $settings );
1613
+ }
1614
+
1615
+ /**
1616
+ * Can trigger a second attempt at getting posts from the API
1617
+ *
1618
+ * Overwritten in the Pro version
1619
+ *
1620
+ * @param string $type
1621
+ * @param array $connected_account_with_error
1622
+ * @param int $attempts
1623
+ *
1624
+ * @return bool
1625
+ *
1626
+ * @since 1.0
1627
+ */
1628
+ protected function can_try_another_request( $type, $connected_account_with_error, $attempts = 0 ) {
1629
+ return false;
1630
+ }
1631
+
1632
+ /**
1633
+ * returns a second connected account if it exists
1634
+ *
1635
+ * Overwritten in the Pro version
1636
+ *
1637
+ * @param string $type
1638
+ * @param array $attempted_connected_accounts
1639
+ *
1640
+ * @return bool
1641
+ *
1642
+ * @since 1.0
1643
+ */
1644
+ protected function get_different_connected_account( $type, $attempted_connected_accounts ) {
1645
+ return false;
1646
+ }
1647
+
1648
  }
inc/class-sby-gdpr-integrations.php CHANGED
@@ -1,84 +1,84 @@
1
- <?php
2
- /**
3
- * Class SBY_GDPR_Integrations
4
- *
5
- * Adds GDPR related workarounds for third-party plugins:
6
- * https://wordpress.org/plugins/cookie-law-info/
7
- *
8
- * @since 2.6/5.9
9
- */
10
-
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- die( '-1' );
13
- }
14
-
15
- class SBY_GDPR_Integrations {
16
-
17
- /**
18
- * Undoing of Cookie Notice's Twitter Feed related code
19
- * needs to be done late.
20
- */
21
- public static function init() {
22
- }
23
-
24
- /**
25
- * Whether or not consent plugins that Twitter Feed
26
- * is compatible with are active.
27
- *
28
- * @return bool|string
29
- */
30
- public static function gdpr_plugins_active() {
31
- if ( class_exists( 'Cookie_Notice' ) ) {
32
- return 'Cookie Notice by dFactory';
33
- }
34
- if ( function_exists( 'run_cookie_law_info' ) || class_exists( 'Cookie_Law_Info' ) ) {
35
- return 'GDPR Cookie Consent by WebToffee';
36
- }
37
- if ( class_exists( 'Cookiebot_WP' ) ) {
38
- return 'Cookiebot by Cybot A/S';
39
- }
40
- if ( class_exists( 'COMPLIANZ' ) ) {
41
- return 'Complianz by Really Simple Plugins';
42
- }
43
- if ( function_exists('BorlabsCookieHelper') ) {
44
- return 'Borlabs Cookie by Borlabs';
45
- }
46
-
47
- return false;
48
- }
49
-
50
- /**
51
- * GDPR features can be added automatically, forced enabled,
52
- * or forced disabled.
53
- *
54
- * @param $settings
55
- *
56
- * @return bool
57
- */
58
- public static function doing_gdpr( $settings ) {
59
- $gdpr = isset( $settings['gdpr'] ) ? $settings['gdpr'] : 'auto';
60
- if ( $gdpr === 'no' ) {
61
- return false;
62
- }
63
- if ( $gdpr === 'yes' ) {
64
- return true;
65
- }
66
- return (SBY_GDPR_Integrations::gdpr_plugins_active() !== false);
67
- }
68
-
69
- /**
70
- * GDPR features are reliant on the image resizing features
71
- *
72
- * @param bool $retest
73
- *
74
- * @return bool
75
- */
76
- public static function gdpr_tests_successful( $retest = false ) {
77
- return true;
78
- }
79
-
80
- public static function gdpr_tests_error_message() {
81
- return '';
82
- }
83
-
84
  }
1
+ <?php
2
+ /**
3
+ * Class SBY_GDPR_Integrations
4
+ *
5
+ * Adds GDPR related workarounds for third-party plugins:
6
+ * https://wordpress.org/plugins/cookie-law-info/
7
+ *
8
+ * @since 2.6/5.9
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ die( '-1' );
13
+ }
14
+
15
+ class SBY_GDPR_Integrations {
16
+
17
+ /**
18
+ * Undoing of Cookie Notice's Twitter Feed related code
19
+ * needs to be done late.
20
+ */
21
+ public static function init() {
22
+ }
23
+
24
+ /**
25
+ * Whether or not consent plugins that Twitter Feed
26
+ * is compatible with are active.
27
+ *
28
+ * @return bool|string
29
+ */
30
+ public static function gdpr_plugins_active() {
31
+ if ( class_exists( 'Cookie_Notice' ) ) {
32
+ return 'Cookie Notice by dFactory';
33
+ }
34
+ if ( function_exists( 'run_cookie_law_info' ) || class_exists( 'Cookie_Law_Info' ) ) {
35
+ return 'GDPR Cookie Consent by WebToffee';
36
+ }
37
+ if ( class_exists( 'Cookiebot_WP' ) ) {
38
+ return 'Cookiebot by Cybot A/S';
39
+ }
40
+ if ( class_exists( 'COMPLIANZ' ) ) {
41
+ return 'Complianz by Really Simple Plugins';
42
+ }
43
+ if ( function_exists('BorlabsCookieHelper') ) {
44
+ return 'Borlabs Cookie by Borlabs';
45
+ }
46
+
47
+ return false;
48
+ }
49
+
50
+ /**
51
+ * GDPR features can be added automatically, forced enabled,
52
+ * or forced disabled.
53
+ *
54
+ * @param $settings
55
+ *
56
+ * @return bool
57
+ */
58
+ public static function doing_gdpr( $settings ) {
59
+ $gdpr = isset( $settings['gdpr'] ) ? $settings['gdpr'] : 'auto';
60
+ if ( $gdpr === 'no' ) {
61
+ return false;
62
+ }
63
+ if ( $gdpr === 'yes' ) {
64
+ return true;
65
+ }
66
+ return (SBY_GDPR_Integrations::gdpr_plugins_active() !== false);
67
+ }
68
+
69
+ /**
70
+ * GDPR features are reliant on the image resizing features
71
+ *
72
+ * @param bool $retest
73
+ *
74
+ * @return bool
75
+ */
76
+ public static function gdpr_tests_successful( $retest = false ) {
77
+ return true;
78
+ }
79
+
80
+ public static function gdpr_tests_error_message() {
81
+ return '';
82
+ }
83
+
84
  }
inc/class-sby-parse.php CHANGED
@@ -1,265 +1,265 @@
1
- <?php
2
-
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- die( '-1' );
5
- }
6
-
7
- class SBY_Parse
8
- {
9
- /**
10
- * @param $post array
11
- *
12
- * @return mixed
13
- *
14
- * @since 1.0
15
- */
16
- public static function get_post_id( $post ) {
17
- if ( isset( $post['id'] ) && ! is_array( $post['id'] ) ) {
18
- return $post['id'];
19
- } else {
20
- return SBY_Parse::get_channel_id( $post ) . '_' . SBY_Parse::get_video_id( $post );
21
- }
22
- }
23
-
24
- public static function get_video_id( $post ) {
25
- if ( isset( $post['snippet']['resourceId']['videoId'] ) ) {
26
- return $post['snippet']['resourceId']['videoId'];
27
- } elseif ( isset( $post['id']['videoId'] ) ) {
28
- return $post['id']['videoId'];
29
- } elseif ( isset( $post['id']) ) {
30
- return $post['id'];
31
- }
32
-
33
- return '';
34
- }
35
-
36
- /**
37
- * @param $post array
38
- *
39
- * @return false|int
40
- *
41
- * @since 1.0
42
- */
43
- public static function get_timestamp( $post ) {
44
- $timestamp = 0;
45
-
46
- if ( isset( $post['contentDetails']['videoPublishedAt'] ) ) {
47
- $data = $post['contentDetails']['videoPublishedAt'];
48
- } elseif ( isset( $post['snippet']['publishedAt'] ) ) {
49
- $data = $post['snippet']['publishedAt'];
50
- }
51
- if ( isset( $data ) ) {
52
- $remove_extra = str_replace( array( 'T', '+00:00', '.000Z', '+' ), ' ', $data );
53
- $timestamp = strtotime( $remove_extra );
54
- }
55
-
56
-
57
- return $timestamp;
58
- }
59
-
60
- /**
61
- * @param $post array
62
- *
63
- * @return mixed
64
- *
65
- * @since 1.0
66
- */
67
- public static function get_permalink( $post ) {
68
- if ( isset( $post['snippet']['resourceId']['videoId'] ) ) {
69
- return 'https://www.youtube.com/watch?v=' . $post['snippet']['resourceId']['videoId'];
70
- } elseif ( isset( $post['snippet']['channelId'] ) ) {
71
- return 'https://www.youtube.com/channel/' . $post['snippet']['channelId'];
72
- }
73
-
74
- return 'https://www.youtube.com/';
75
- }
76
-
77
- /**
78
- * @param array $post
79
- * @param string $resolution
80
- *
81
- * @return string
82
- *
83
- * @since 1.0
84
- */
85
- public static function get_media_url( $post, $resolution = 'lightbox' ) {
86
- $thumbnail_key = 'standard';
87
- switch ( $resolution ) {
88
- case 'thumb' :
89
- $thumbnail_key = 'default';
90
- break;
91
- case 'medium' :
92
- $thumbnail_key = 'medium';
93
- break;
94
- case 'high' :
95
- $thumbnail_key = 'high';
96
- break;
97
- case 'lightbox' :
98
- $thumbnail_key = 'maxres';
99
- break;
100
- }
101
-
102
- if ( isset( $post['snippet']['thumbnails'][ $thumbnail_key ]['url'] ) ) {
103
- return $post['snippet']['thumbnails'][ $thumbnail_key ]['url'];
104
- } elseif ( isset( $post['snippet']['thumbnails']['high']['url'] ) ) {
105
- return $post['snippet']['thumbnails']['high']['url'];
106
- } elseif ( isset( $post['snippet']['thumbnails']['medium']['url'] ) ) {
107
- return $post['snippet']['thumbnails']['medium']['url'];
108
- }
109
-
110
- return '';
111
- }
112
-
113
- /**
114
- * Uses the existing data for the individual YouTube post to
115
- * set the best image sources for each resolution size. Due to
116
- * random bugs or just how the API works, different post types
117
- * need special treatment.
118
- *
119
- * @param array $post
120
- * @param array $resized_images
121
- *
122
- * @return array
123
- *
124
- * @since 1.0
125
- */
126
- public static function get_media_src_set( $post, $resized_images = array() ) {
127
- $media_urls = array();
128
- $thumbnails = isset( $post['snippet']['thumbnails'] ) ? $post['snippet']['thumbnails'] : false;
129
- $largest_found = '';
130
-
131
- if ( $thumbnails ) {
132
- if ( isset( $thumbnails['default']['url'] ) ) {
133
- $media_urls['120'] = $thumbnails['default']['url'];
134
- $largest_found = $thumbnails['default']['url'];
135
- } else {
136
- $media_urls['120'] = $largest_found;
137
- }
138
- if ( isset( $thumbnails['medium']['url'] ) ) {
139
- $media_urls['320'] = $thumbnails['medium']['url'];
140
- $largest_found = $thumbnails['medium']['url'];
141
- } else {
142
- $media_urls['320'] = $largest_found;
143
- }
144
- if ( isset( $thumbnails['high']['url'] ) ) {
145
- $media_urls['480'] = $thumbnails['high']['url'];
146
- $largest_found = $thumbnails['high']['url'];
147
- } else {
148
- $media_urls['480'] = $largest_found;
149
- }
150
- if ( isset( $thumbnails['standard']['url'] ) ) {
151
- $media_urls['640'] = $thumbnails['standard']['url'];
152
- } else {
153
- $media_urls['640'] = $largest_found;
154
- }
155
- }
156
-
157
-
158
- return $media_urls;
159
- }
160
-
161
- /**
162
- * A default can be set in the case that the user doesn't use captions
163
- * for posts as this is also used as the alt text for the image.
164
- *
165
- * @param $post
166
- * @param string $default
167
- *
168
- * @return string
169
- *
170
- * @since 1.0
171
- */
172
- public static function get_caption( $post, $default = '' ) {
173
- $caption = $default;
174
- if ( isset( $post['snippet']['description'] ) ) {
175
- $caption = $post['snippet']['description'];
176
- }
177
-
178
- return $caption;
179
- }
180
-
181
- public static function get_video_title( $channel_or_playlist_item_data ) {
182
- if ( isset( $channel_or_playlist_item_data['items'][0]['snippet']['title'] ) ) {
183
- return $channel_or_playlist_item_data['items'][0]['snippet']['title'];
184
- } else if ( isset( $channel_or_playlist_item_data['snippet']['title'] ) ) {
185
- return $channel_or_playlist_item_data['snippet']['title'];
186
- }
187
- return '';
188
- }
189
-
190
- public static function get_channel_id( $channel_or_playlist_item_data ) {
191
- if ( isset( $channel_or_playlist_item_data['items'][0]['id'] ) ) {
192
- return $channel_or_playlist_item_data['items'][0]['id'];
193
- } elseif ( isset( $channel_or_playlist_item_data['snippet']['channelId'] ) ) {
194
- return $channel_or_playlist_item_data['snippet']['channelId'];
195
- }
196
- return '';
197
- }
198
-
199
- public static function get_channel_title( $channel_or_playlist_item_data ) {
200
- if ( isset( $channel_or_playlist_item_data['items'][0]['snippet']['title'] ) ) {
201
- return $channel_or_playlist_item_data['items'][0]['snippet']['title'];
202
- } elseif ( isset( $channel_or_playlist_item_data['snippet']['channelTitle'] ) ) {
203
- return $channel_or_playlist_item_data['snippet']['channelTitle'];
204
- }
205
- return '';
206
- }
207
-
208
- public static function get_channel_permalink( $channel_data ) {
209
- return 'https://www.youtube.com/channel/' . SBY_Parse::get_channel_id( $channel_data ) . '/';
210
- }
211
-
212
- /**
213
- * @param array $header_data
214
- * @param array $settings
215
- *
216
- * @return string
217
- *
218
- * @since 1.0
219
- */
220
- public static function get_avatar( $header_data, $settings = array( 'favor_local' => false ) ) {
221
- if ( $settings['favor_local'] && ! empty( $header_data['local_avatar'] ) ) {
222
- return $header_data['local_avatar'];
223
- } else {
224
- if ( isset( $header_data['items'][0]['snippet']['thumbnails'] ) ) {
225
- $header_size = isset( $settings['headersize'] ) ? $settings['headersize'] : '';
226
- if ( $header_size === 'large' ) {
227
- return $header_data['items'][0]['snippet']['thumbnails']['high']['url'];
228
- } elseif ( $header_size === 'medium' ) {
229
- return $header_data['items'][0]['snippet']['thumbnails']['medium']['url'];
230
- } else {
231
- return $header_data['items'][0]['snippet']['thumbnails']['default']['url'];
232
- }
233
- }
234
- }
235
- return '';
236
- }
237
-
238
- public static function get_item_avatar( $post, $avatars ) {
239
- if ( empty ( $avatars ) ) {
240
- return '';
241
- } else {
242
- $username = SBY_Parse::get_channel_id( $post );
243
- if ( isset( $avatars[ $username ] ) ) {
244
- return $avatars[ $username ];
245
- }
246
- }
247
- return '';
248
- }
249
-
250
- /**
251
- * Account bio/description used in header
252
- *
253
- * @param $header_data
254
- *
255
- * @return string
256
- *
257
- * @since 1.0
258
- */
259
- public static function get_channel_description( $header_data ) {
260
- if ( isset( $header_data['items'][0]['snippet']['description'] ) ) {
261
- return $header_data['items'][0]['snippet']['description'];
262
- }
263
- return '';
264
- }
265
  }
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ die( '-1' );
5
+ }
6
+
7
+ class SBY_Parse
8
+ {
9
+ /**
10
+ * @param $post array
11
+ *
12
+ * @return mixed
13
+ *
14
+ * @since 1.0
15
+ */
16
+ public static function get_post_id( $post ) {
17
+ if ( isset( $post['id'] ) && ! is_array( $post['id'] ) ) {
18
+ return $post['id'];
19
+ } else {
20
+ return SBY_Parse::get_channel_id( $post ) . '_' . SBY_Parse::get_video_id( $post );
21
+ }
22
+ }
23
+
24
+ public static function get_video_id( $post ) {
25
+ if ( isset( $post['snippet']['resourceId']['videoId'] ) ) {
26
+ return $post['snippet']['resourceId']['videoId'];
27
+ } elseif ( isset( $post['id']['videoId'] ) ) {
28
+ return $post['id']['videoId'];
29
+ } elseif ( isset( $post['id']) ) {
30
+ return $post['id'];
31
+ }
32
+
33
+ return '';
34
+ }
35
+
36
+ /**
37
+ * @param $post array
38
+ *
39
+ * @return false|int
40
+ *
41
+ * @since 1.0
42
+ */
43
+ public static function get_timestamp( $post ) {
44
+ $timestamp = 0;
45
+
46
+ if ( isset( $post['contentDetails']['videoPublishedAt'] ) ) {
47
+ $data = $post['contentDetails']['videoPublishedAt'];
48
+ } elseif ( isset( $post['snippet']['publishedAt'] ) ) {
49
+ $data = $post['snippet']['publishedAt'];
50
+ }
51
+ if ( isset( $data ) ) {
52
+ $remove_extra = str_replace( array( 'T', '+00:00', '.000Z', '+' ), ' ', $data );
53
+ $timestamp = strtotime( $remove_extra );
54
+ }
55
+
56
+
57
+ return $timestamp;
58
+ }
59
+
60
+ /**
61
+ * @param $post array
62
+ *
63
+ * @return mixed
64
+ *
65
+ * @since 1.0
66
+ */
67
+ public static function get_permalink( $post ) {
68
+ if ( isset( $post['snippet']['resourceId']['videoId'] ) ) {
69
+ return 'https://www.youtube.com/watch?v=' . $post['snippet']['resourceId']['videoId'];
70
+ } elseif ( isset( $post['snippet']['channelId'] ) ) {
71
+ return 'https://www.youtube.com/channel/' . $post['snippet']['channelId'];
72
+ }
73
+
74
+ return 'https://www.youtube.com/';
75
+ }
76
+
77
+ /**
78
+ * @param array $post
79
+ * @param string $resolution
80
+ *
81
+ * @return string
82
+ *
83
+ * @since 1.0
84
+ */
85
+ public static function get_media_url( $post, $resolution = 'lightbox' ) {
86
+ $thumbnail_key = 'standard';
87
+ switch ( $resolution ) {
88
+ case 'thumb' :
89
+ $thumbnail_key = 'default';
90
+ break;
91
+ case 'medium' :
92
+ $thumbnail_key = 'medium';
93
+ break;
94
+ case 'high' :
95
+ $thumbnail_key = 'high';
96
+ break;
97
+ case 'lightbox' :
98
+ $thumbnail_key = 'maxres';
99
+ break;
100
+ }
101
+
102
+ if ( isset( $post['snippet']['thumbnails'][ $thumbnail_key ]['url'] ) ) {
103
+ return $post['snippet']['thumbnails'][ $thumbnail_key ]['url'];
104
+ } elseif ( isset( $post['snippet']['thumbnails']['high']['url'] ) ) {
105
+ return $post['snippet']['thumbnails']['high']['url'];
106
+ } elseif ( isset( $post['snippet']['thumbnails']['medium']['url'] ) ) {
107
+ return $post['snippet']['thumbnails']['medium']['url'];
108
+ }
109
+
110
+ return '';
111
+ }
112
+
113
+ /**
114
+ * Uses the existing data for the individual YouTube post to
115
+ * set the best image sources for each resolution size. Due to
116
+ * random bugs or just how the API works, different post types
117
+ * need special treatment.
118
+ *
119
+ * @param array $post
120
+ * @param array $resized_images
121
+ *
122
+ * @return array
123
+ *
124
+ * @since 1.0
125
+ */
126
+ public static function get_media_src_set( $post, $resized_images = array() ) {
127
+ $media_urls = array();
128
+ $thumbnails = isset( $post['snippet']['thumbnails'] ) ? $post['snippet']['thumbnails'] : false;
129
+ $largest_found = '';
130
+
131
+ if ( $thumbnails ) {
132
+ if ( isset( $thumbnails['default']['url'] ) ) {
133
+ $media_urls['120'] = $thumbnails['default']['url'];
134
+ $largest_found = $thumbnails['default']['url'];
135
+ } else {
136
+ $media_urls['120'] = $largest_found;
137
+ }
138
+ if ( isset( $thumbnails['medium']['url'] ) ) {
139
+ $media_urls['320'] = $thumbnails['medium']['url'];
140
+ $largest_found = $thumbnails['medium']['url'];
141
+ } else {
142
+ $media_urls['320'] = $largest_found;
143
+ }
144
+ if ( isset( $thumbnails['high']['url'] ) ) {
145
+ $media_urls['480'] = $thumbnails['high']['url'];
146
+ $largest_found = $thumbnails['high']['url'];
147
+ } else {
148
+ $media_urls['480'] = $largest_found;
149
+ }
150
+ if ( isset( $thumbnails['standard']['url'] ) ) {
151
+ $media_urls['640'] = $thumbnails['standard']['url'];
152
+ } else {
153
+ $media_urls['640'] = $largest_found;
154
+ }
155
+ }
156
+
157
+
158
+ return $media_urls;
159
+ }
160
+
161
+ /**
162
+ * A default can be set in the case that the user doesn't use captions
163
+ * for posts as this is also used as the alt text for the image.
164
+ *
165
+ * @param $post
166
+ * @param string $default
167
+ *
168
+ * @return string
169
+ *
170
+ * @since 1.0
171
+ */
172
+ public static function get_caption( $post, $default = '' ) {
173
+ $caption = $default;
174
+ if ( isset( $post['snippet']['description'] ) ) {
175
+ $caption = $post['snippet']['description'];
176
+ }
177
+
178
+ return $caption;
179
+ }
180
+
181
+ public static function get_video_title( $channel_or_playlist_item_data ) {
182
+ if ( isset( $channel_or_playlist_item_data['items'][0]['snippet']['title'] ) ) {
183
+ return $channel_or_playlist_item_data['items'][0]['snippet']['title'];
184
+ } else if ( isset( $channel_or_playlist_item_data['snippet']['title'] ) ) {
185
+ return $channel_or_playlist_item_data['snippet']['title'];
186
+ }
187
+ return '';
188
+ }
189
+
190
+ public static function get_channel_id( $channel_or_playlist_item_data ) {
191
+ if ( isset( $channel_or_playlist_item_data['items'][0]['id'] ) ) {
192
+ return $channel_or_playlist_item_data['items'][0]['id'];
193
+ } elseif ( isset( $channel_or_playlist_item_data['snippet']['channelId'] ) ) {
194
+ return $channel_or_playlist_item_data['snippet']['channelId'];
195
+ }
196
+ return '';
197
+ }
198
+
199
+ public static function get_channel_title( $channel_or_playlist_item_data ) {
200
+ if ( isset( $channel_or_playlist_item_data['items'][0]['snippet']['title'] ) ) {
201
+ return $channel_or_playlist_item_data['items'][0]['snippet']['title'];
202
+ } elseif ( isset( $channel_or_playlist_item_data['snippet']['channelTitle'] ) ) {
203
+ return $channel_or_playlist_item_data['snippet']['channelTitle'];
204
+ }
205
+ return '';
206
+ }
207
+
208
+ public static function get_channel_permalink( $channel_data ) {
209
+ return 'https://www.youtube.com/channel/' . SBY_Parse::get_channel_id( $channel_data ) . '/';
210
+ }
211
+
212
+ /**
213
+ * @param array $header_data
214
+ * @param array $settings
215
+ *
216
+ * @return string
217
+ *
218
+ * @since 1.0
219
+ */
220
+ public static function get_avatar( $header_data, $settings = array( 'favor_local' => false ) ) {
221
+ if ( $settings['favor_local'] && ! empty( $header_data['local_avatar'] ) ) {
222
+ return $header_data['local_avatar'];
223
+ } else {
224
+ if ( isset( $header_data['items'][0]['snippet']['thumbnails'] ) ) {
225
+ $header_size = isset( $settings['headersize'] ) ? $settings['headersize'] : '';
226
+ if ( $header_size === 'large' ) {
227
+ return $header_data['items'][0]['snippet']['thumbnails']['high']['url'];
228
+ } elseif ( $header_size === 'medium' ) {
229
+ return $header_data['items'][0]['snippet']['thumbnails']['medium']['url'];
230
+ } else {
231
+ return $header_data['items'][0]['snippet']['thumbnails']['default']['url'];
232
+ }
233
+ }
234
+ }
235
+ return '';
236
+ }
237
+
238
+ public static function get_item_avatar( $post, $avatars ) {
239
+ if ( empty ( $avatars ) ) {
240
+ return '';
241
+ } else {
242
+ $username = SBY_Parse::get_channel_id( $post );
243
+ if ( isset( $avatars[ $username ] ) ) {
244
+ return $avatars[ $username ];
245
+ }
246
+ }
247
+ return '';
248
+ }
249
+
250
+ /**
251
+ * Account bio/description used in header
252
+ *
253
+ * @param $header_data
254
+ *
255
+ * @return string
256
+ *
257
+ * @since 1.0
258
+ */
259
+ public static function get_channel_description( $header_data ) {
260
+ if ( isset( $header_data['items'][0]['snippet']['description'] ) ) {
261
+ return $header_data['items'][0]['snippet']['description'];
262
+ }
263
+ return '';
264
+ }
265
  }
inc/class-sby-posts-manager.php CHANGED
@@ -1,328 +1,328 @@
1
- <?php
2
-
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- die( '-1' );
5
- }
6
-
7
- class SBY_Posts_Manager
8
- {
9
- var $options_prefix;
10
-
11
- /**
12
- * @var int
13
- */
14
- var $limit;
15
-
16
- /**
17
- * @var array
18
- */
19
- var $errors;
20
-
21
- var $ajax_status;
22
-
23
- /**
24
- * @var array
25
- */
26
- var $frontend_errors;
27
-
28
- /**
29
- * @var bool
30
- */
31
- var $resizing_tables_exist;
32
-
33
- /**
34
- * SBY_Posts_Manager constructor.
35
- */
36
- public function __construct( $options_prefix, $errors, $ajax_status ) {
37
- $this->options_prefix = $options_prefix;
38
- $this->errors = $errors;
39
- $this->ajax_status = $ajax_status;
40
- $this->frontend_errors = array();
41
- }
42
-
43
- /**
44
- * @return array
45
- *
46
- * @since 1.0
47
- */
48
- public function get_ajax_status() {
49
- return $this->ajax_status;
50
- }
51
-
52
- /**
53
- * @param $to_update
54
- *
55
- * @since 1.0
56
- */
57
- public function update_ajax_status( $to_update ) {
58
- foreach ( $to_update as $key => $value ) {
59
- $this->ajax_status[ $key ] = $value;
60
- }
61
-
62
- update_option( $this->options_prefix . '_ajax_status', $this->ajax_status );
63
- }
64
-
65
- /**
66
- * When the plugin is first installed and used, an AJAX call to admin-ajax.php
67
- * is made to verify that it's available
68
- *
69
- * @param bool $force_check
70
- *
71
- * @return bool
72
- *
73
- * @since 1.0
74
- */
75
- public function maybe_start_ajax_test( $force_check = false ) {
76
- if ( ! $this->ajax_status['tested'] || $force_check ) {
77
- set_transient( $this->options_prefix . '_doing_ajax_test', 'yes', 60*60 );
78
- $this->update_ajax_status( array( 'tested' => true ) );
79
- return true;
80
- }
81
-
82
- return false;
83
- }
84
-
85
- /**
86
- * Called if a successful admin ajax request is made
87
- *
88
- * @since 1.0
89
- */
90
- public function update_successful_ajax_test() {
91
- $this->update_ajax_status( array( 'successful' => true ) );
92
- }
93
-
94
- /**
95
- * @return bool
96
- *
97
- * @since 1.0
98
- */
99
- public function should_add_ajax_test_notice() {
100
- return ($this->ajax_status['tested'] && ! $this->ajax_status['successful'] && get_transient( $this->options_prefix . '_doing_ajax_test' ) !== 'yes');
101
- }
102
-
103
- /**
104
- * The plugin has a limit on how many post records can be stored and
105
- * images resized to avoid overloading servers. This function deletes the post that
106
- * has the longest time passed since it was retrieved.
107
- *
108
- * @since 1.0
109
- */
110
- public function delete_least_used_image() {
111
-
112
- }
113
-
114
- /**
115
- * Calculates how many records are in the database and whether or not it exceeds the limit
116
- *
117
- * @return bool
118
- *
119
- * @since 1.0
120
- */
121
- public function max_total_records_reached() {
122
- global $wpdb;
123
- $table_name = $wpdb->prefix . SBY_ITEMS;
124
-
125
- $num_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
126
-
127
- if ( !isset( $this->limit ) && (int)$num_records > SBY_MAX_RECORDS ) {
128
- $this->limit = (int)$num_records - SBY_MAX_RECORDS;
129
- }
130
-
131
- return ((int)$num_records > SBY_MAX_RECORDS);
132
- }
133
-
134
- /**
135
- * The plugin caps how many new images are created in a 15 minute window to
136
- * avoid overloading servers
137
- *
138
- * @return bool
139
- *
140
- * @since 1.0
141
- */
142
- public function max_resizing_per_time_period_reached() {
143
- global $wpdb;
144
- $table_name = $wpdb->prefix . SBY_ITEMS;
145
-
146
- $fifteen_minutes_ago = date( 'Y-m-d H:i:s', time() - 15 * 60 );
147
-
148
- $num_new_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE created_on > '$fifteen_minutes_ago'" );
149
-
150
- return ((int)$num_new_records > 100);
151
- }
152
-
153
- /**
154
- * @return bool
155
- *
156
- * @since 1.0
157
- */
158
- public function image_resizing_disabled() {
159
- global $sby_settings;
160
-
161
- $disable_resizing = isset( $sby_settings['disable_resize'] ) ? $sby_settings['disable_resize'] === 'on' || $sby_settings['disable_resize'] === true : false;
162
-
163
- if ( ! $disable_resizing ) {
164
- $disable_resizing = isset( $this->resizing_tables_exist ) ? ! $this->resizing_tables_exist : ! $this->does_resizing_tables_exist();
165
- }
166
-
167
- return $disable_resizing;
168
- }
169
-
170
- /**
171
- * Used to skip image resizing if the tables were never successfully
172
- * created
173
- *
174
- * @return bool
175
- *
176
- * @since 1.0
177
- */
178
- public function does_resizing_tables_exist() {
179
- return true;
180
- }
181
-
182
- /**
183
- * Resets the custom tables and deletes all image files
184
- *
185
- * @since 1.0
186
- */
187
- public function delete_all_sby_posts() {
188
- $upload = wp_upload_dir();
189
-
190
- global $wpdb;
191
-
192
- $image_files = glob( trailingslashit( $upload['basedir'] ) . trailingslashit( SBY_UPLOADS_NAME ) . '*' ); // get all file names
193
- foreach ( $image_files as $file ) { // iterate files
194
- if ( is_file( $file ) ) {
195
- unlink( $file );
196
- }
197
- }
198
-
199
- $options = get_option( $this->options_prefix . '_settings', array() );
200
- $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
201
-
202
- foreach ( $connected_accounts as $account_id => $data ) {
203
-
204
- if ( isset( $data['local_avatar'] ) ) {
205
- $connected_accounts[ $account_id ]['local_avatar'] = false;
206
- }
207
-
208
- }
209
-
210
- $options['connected_accounts'] = $connected_accounts;
211
-
212
- update_option( $this->options_prefix . '_settings', $options );
213
-
214
- $table_name = $wpdb->prefix . "options";
215
-
216
- $wpdb->query( "
217
- DELETE
218
- FROM $table_name
219
- WHERE `option_name` LIKE ('%\_transient\_\$sby\_%')
220
- " );
221
- $wpdb->query( "
222
- DELETE
223
- FROM $table_name
224
- WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sby\_%')
225
- " );
226
-
227
- $upload = wp_upload_dir();
228
- $upload_dir = $upload['basedir'];
229
- $upload_dir = trailingslashit( $upload_dir ) . SBY_UPLOADS_NAME;
230
- if ( ! file_exists( $upload_dir ) ) {
231
- $created = wp_mkdir_p( $upload_dir );
232
- if ( $created ) {
233
- $this->remove_error( 'upload_dir' );
234
- } else {
235
- $this->add_error( 'upload_dir', array( __( 'There was an error creating the folder for storing resized images.', SBY_TEXT_DOMAIN ), $upload_dir ) );
236
- }
237
- } else {
238
- $this->remove_error( 'upload_dir' );
239
- }
240
-
241
- }
242
-
243
- /**
244
- * @return array
245
- *
246
- * @since 1.0
247
- */
248
- public function get_errors() {
249
- return $this->errors;
250
- }
251
-
252
- /**
253
- * @param $type
254
- * @param $message_array
255
- *
256
- * @since 1.0
257
- */
258
- public function add_error( $type, $message_array ) {
259
- $this->errors[ $type ] = $message_array;
260
-
261
- update_option( 'sby_errors', $this->errors, false );
262
- }
263
-
264
- /**
265
- * @param $type
266
- *
267
- * @since 1.0
268
- */
269
- public function remove_error( $type ) {
270
- if ( isset( $this->errors[ $type ] ) ) {
271
- unset( $this->errors[ $type ] );
272
-
273
- update_option( $this->options_prefix . '_errors', $this->errors, false );
274
- }
275
- }
276
-
277
- public function remove_all_errors() {
278
- delete_option( $this->options_prefix . '_errors' );
279
- }
280
-
281
- /**
282
- * @param $type
283
- * @param $message
284
- *
285
- * @since 1.0
286
- */
287
- public function add_frontend_error( $type, $message ) {
288
- $this->frontend_errors[ $type ] = $message;
289
- }
290
-
291
- /**
292
- * @return array
293
- *
294
- * @since 1.0
295
- */
296
- public function get_frontend_errors() {
297
- return $this->frontend_errors;
298
- }
299
-
300
- /**
301
- * @return array
302
- *
303
- * @since 1.0
304
- */
305
- public function reset_frontend_errors() {
306
- return $this->frontend_errors = array();
307
- }
308
-
309
- /**
310
- * @since 1.0
311
- */
312
- public function add_api_request_delay( $time_in_seconds = 300, $account_id = false ) {
313
- if ( $account_id ) {
314
- set_transient( SBY_USE_BACKUP_PREFIX . $this->options_prefix . '_' . $account_id, '1', $time_in_seconds );
315
- } else {
316
- set_transient( SBY_USE_BACKUP_PREFIX . $this->options_prefix . '_delay_requests', '1', $time_in_seconds );
317
- }
318
- }
319
-
320
- /**
321
- * @since 1.0
322
- */
323
- public function are_current_api_request_delays( $account_id = false ) {
324
- $is_delay = (get_transient( SBY_USE_BACKUP_PREFIX . $this->options_prefix . '_delay_requests' ) !== false);
325
-
326
- return $is_delay;
327
- }
328
  }
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ die( '-1' );
5
+ }
6
+
7
+ class SBY_Posts_Manager
8
+ {
9
+ var $options_prefix;
10
+
11
+ /**
12
+ * @var int
13
+ */
14
+ var $limit;
15
+
16
+ /**
17
+ * @var array
18
+ */
19
+ var $errors;
20
+
21
+ var $ajax_status;
22
+
23
+ /**
24
+ * @var array
25
+ */
26
+ var $frontend_errors;
27
+
28
+ /**
29
+ * @var bool
30
+ */
31
+ var $resizing_tables_exist;
32
+
33
+ /**
34
+ * SBY_Posts_Manager constructor.
35
+ */
36
+ public function __construct( $options_prefix, $errors, $ajax_status ) {
37
+ $this->options_prefix = $options_prefix;
38
+ $this->errors = $errors;
39
+ $this->ajax_status = $ajax_status;
40
+ $this->frontend_errors = array();
41
+ }
42
+
43
+ /**
44
+ * @return array
45
+ *
46
+ * @since 1.0
47
+ */
48
+ public function get_ajax_status() {
49
+ return $this->ajax_status;
50
+ }
51
+
52
+ /**
53
+ * @param $to_update
54
+ *
55
+ * @since 1.0
56
+ */
57
+ public function update_ajax_status( $to_update ) {
58
+ foreach ( $to_update as $key => $value ) {
59
+ $this->ajax_status[ $key ] = $value;
60
+ }
61
+
62
+ update_option( $this->options_prefix . '_ajax_status', $this->ajax_status );
63
+ }
64
+
65
+ /**
66
+ * When the plugin is first installed and used, an AJAX call to admin-ajax.php
67
+ * is made to verify that it's available
68
+ *
69
+ * @param bool $force_check
70
+ *
71
+ * @return bool
72
+ *
73
+ * @since 1.0
74
+ */
75
+ public function maybe_start_ajax_test( $force_check = false ) {
76
+ if ( ! $this->ajax_status['tested'] || $force_check ) {
77
+ set_transient( $this->options_prefix . '_doing_ajax_test', 'yes', 60*60 );
78
+ $this->update_ajax_status( array( 'tested' => true ) );
79
+ return true;
80
+ }
81
+
82
+ return false;
83
+ }
84
+
85
+ /**
86
+ * Called if a successful admin ajax request is made
87
+ *
88
+ * @since 1.0
89
+ */
90
+ public function update_successful_ajax_test() {
91
+ $this->update_ajax_status( array( 'successful' => true ) );
92
+ }
93
+
94
+ /**
95
+ * @return bool
96
+ *
97
+ * @since 1.0
98
+ */
99
+ public function should_add_ajax_test_notice() {
100
+ return ($this->ajax_status['tested'] && ! $this->ajax_status['successful'] && get_transient( $this->options_prefix . '_doing_ajax_test' ) !== 'yes');
101
+ }
102
+
103
+ /**
104
+ * The plugin has a limit on how many post records can be stored and
105
+ * images resized to avoid overloading servers. This function deletes the post that
106
+ * has the longest time passed since it was retrieved.
107
+ *
108
+ * @since 1.0
109
+ */
110
+ public function delete_least_used_image() {
111
+
112
+ }
113
+
114
+ /**
115
+ * Calculates how many records are in the database and whether or not it exceeds the limit
116
+ *
117
+ * @return bool
118
+ *
119
+ * @since 1.0
120
+ */
121
+ public function max_total_records_reached() {
122
+ global $wpdb;
123
+ $table_name = $wpdb->prefix . SBY_ITEMS;
124
+
125
+ $num_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
126
+
127
+ if ( !isset( $this->limit ) && (int)$num_records > SBY_MAX_RECORDS ) {
128
+ $this->limit = (int)$num_records - SBY_MAX_RECORDS;
129
+ }
130
+
131
+ return ((int)$num_records > SBY_MAX_RECORDS);
132
+ }
133
+
134
+ /**
135
+ * The plugin caps how many new images are created in a 15 minute window to
136
+ * avoid overloading servers
137
+ *
138
+ * @return bool
139
+ *
140
+ * @since 1.0
141
+ */
142
+ public function max_resizing_per_time_period_reached() {
143
+ global $wpdb;
144
+ $table_name = $wpdb->prefix . SBY_ITEMS;
145
+
146
+ $fifteen_minutes_ago = date( 'Y-m-d H:i:s', time() - 15 * 60 );
147
+
148
+ $num_new_records = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE created_on > '$fifteen_minutes_ago'" );
149
+
150
+ return ((int)$num_new_records > 100);
151
+ }
152
+
153
+ /**
154
+ * @return bool
155
+ *
156
+ * @since 1.0
157
+ */
158
+ public function image_resizing_disabled() {
159
+ global $sby_settings;
160
+
161
+ $disable_resizing = isset( $sby_settings['disable_resize'] ) ? $sby_settings['disable_resize'] === 'on' || $sby_settings['disable_resize'] === true : false;
162
+
163
+ if ( ! $disable_resizing ) {
164
+ $disable_resizing = isset( $this->resizing_tables_exist ) ? ! $this->resizing_tables_exist : ! $this->does_resizing_tables_exist();
165
+ }
166
+
167
+ return $disable_resizing;
168
+ }
169
+
170
+ /**
171
+ * Used to skip image resizing if the tables were never successfully
172
+ * created
173
+ *
174
+ * @return bool
175
+ *
176
+ * @since 1.0
177
+ */
178
+ public function does_resizing_tables_exist() {
179
+ return true;
180
+ }
181
+
182
+ /**
183
+ * Resets the custom tables and deletes all image files
184
+ *
185
+ * @since 1.0
186
+ */
187
+ public function delete_all_sby_posts() {
188
+ $upload = wp_upload_dir();
189
+
190
+ global $wpdb;
191
+
192
+ $image_files = glob( trailingslashit( $upload['basedir'] ) . trailingslashit( SBY_UPLOADS_NAME ) . '*' ); // get all file names
193
+ foreach ( $image_files as $file ) { // iterate files
194
+ if ( is_file( $file ) ) {
195
+ unlink( $file );
196
+ }
197
+ }
198
+
199
+ $options = get_option( $this->options_prefix . '_settings', array() );
200
+ $connected_accounts = isset( $options['connected_accounts'] ) ? $options['connected_accounts'] : array();
201
+
202
+ foreach ( $connected_accounts as $account_id => $data ) {
203
+
204
+ if ( isset( $data['local_avatar'] ) ) {
205
+ $connected_accounts[ $account_id ]['local_avatar'] = false;
206
+ }
207
+
208
+ }
209
+
210
+ $options['connected_accounts'] = $connected_accounts;
211
+
212
+ update_option( $this->options_prefix . '_settings', $options );
213
+
214
+ $table_name = $wpdb->prefix . "options";
215
+
216
+ $wpdb->query( "
217
+ DELETE
218
+ FROM $table_name
219
+ WHERE `option_name` LIKE ('%\_transient\_\$sby\_%')
220
+ " );
221
+ $wpdb->query( "
222
+ DELETE
223
+ FROM $table_name
224
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sby\_%')
225
+ " );
226
+
227
+ $upload = wp_upload_dir();
228
+ $upload_dir = $upload['basedir'];
229
+ $upload_dir = trailingslashit( $upload_dir ) . SBY_UPLOADS_NAME;
230
+ if ( ! file_exists( $upload_dir ) ) {
231
+ $created = wp_mkdir_p( $upload_dir );
232
+ if ( $created ) {
233
+ $this->remove_error( 'upload_dir' );
234
+ } else {
235
+ $this->add_error( 'upload_dir', array( __( 'There was an error creating the folder for storing resized images.', SBY_TEXT_DOMAIN ), $upload_dir ) );
236
+ }
237
+ } else {
238
+ $this->remove_error( 'upload_dir' );
239
+ }
240
+
241
+ }
242
+
243
+ /**
244
+ * @return array
245
+ *
246
+ * @since 1.0
247
+ */
248
+ public function get_errors() {
249
+ return $this->errors;
250
+ }
251
+
252
+ /**
253
+ * @param $type
254
+ * @param $message_array
255
+ *
256
+ * @since 1.0
257
+ */
258
+ public function add_error( $type, $message_array ) {
259
+ $this->errors[ $type ] = $message_array;
260
+
261
+ update_option( 'sby_errors', $this->errors, false );
262
+ }
263
+
264
+ /**
265
+ * @param $type
266
+ *
267
+ * @since 1.0
268
+ */
269
+ public function remove_error( $type ) {
270
+ if ( isset( $this->errors[ $type ] ) ) {
271
+ unset( $this->errors[ $type ] );
272
+
273
+ update_option( $this->options_prefix . '_errors', $this->errors, false );
274
+ }
275
+ }
276
+
277
+ public function remove_all_errors() {
278
+ delete_option( $this->options_prefix . '_errors' );
279
+ }
280
+
281
+ /**
282
+ * @param $type
283
+ * @param $message
284
+ *
285
+ * @since 1.0
286
+ */
287
+ public function add_frontend_error( $type, $message ) {
288
+ $this->frontend_errors[ $type ] = $message;
289
+ }
290
+
291
+ /**
292
+ * @return array
293
+ *
294
+ * @since 1.0
295
+ */
296
+ public function get_frontend_errors() {
297
+ return $this->frontend_errors;
298
+ }
299
+
300
+ /**
301
+ * @return array
302
+ *
303
+ * @since 1.0
304
+ */
305
+ public function reset_frontend_errors() {
306
+ return $this->frontend_errors = array();
307
+ }
308
+
309
+ /**
310
+ * @since 1.0
311
+ */
312
+ public function add_api_request_delay( $time_in_seconds = 300, $account_id = false ) {
313
+ if ( $account_id ) {
314
+ set_transient( SBY_USE_BACKUP_PREFIX . $this->options_prefix . '_' . $account_id, '1', $time_in_seconds );
315
+ } else {
316
+ set_transient( SBY_USE_BACKUP_PREFIX . $this->options_prefix . '_delay_requests', '1', $time_in_seconds );
317
+ }
318
+ }
319
+
320
+ /**
321
+ * @since 1.0
322
+ */
323
+ public function are_current_api_request_delays( $account_id = false ) {
324
+ $is_delay = (get_transient( SBY_USE_BACKUP_PREFIX . $this->options_prefix . '_delay_requests' ) !== false);
325
+
326
+ return $is_delay;
327
+ }
328
  }
inc/class-sby-rss-connect.php CHANGED
@@ -1,137 +1,137 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SBY_RSS_Connect
7
- {
8
- /**
9
- * @var string
10
- */
11
- private $url;
12
-
13
- /**
14
- * @var object
15
- */
16
- private $response;
17
-
18
- private $is_live_stream;
19
-
20
- public function __construct( $endpoint = '', $params = array() ) {
21
- $this->is_live_stream = false;
22
- if ( isset( $params['livestream'] ) ) {
23
- $this->is_live_stream = true;
24
- }
25
- $this->set_url( $endpoint, $params );
26
- }
27
-
28
- public function get_data() {
29
- return $this->response;
30
- }
31
-
32
- public function set_url_from_args( $url ) {
33
- $this->url = $url;
34
- }
35
-
36
- public function get_url() {
37
- return $this->url;
38
- }
39
-
40
- public function connect() {
41
-
42
- if ( ! ini_get( 'allow_url_fopen' ) ) {
43
- if ( ! $this->is_live_stream ) {
44
- $error_message = '<p><b>'. __( 'Unable to retrieve new videos without an API key.', 'youtube-feed' ) .'</b></p>';
45
- if ( current_user_can( 'manage_youtube_feed_options' ) ) {
46
- $error_message .= '<p>' . sprintf( __( 'Due to your server configuration, an API key is required to update your feed. See %sthis FAQ%s to set up an API key.', 'youtube-feed' ), '<a href="https://smashballoon.com/youtube-api-key/" target="_blank" rel="noopener nofollow">', '</a>' ) . '</p>';
47
- }
48
- } else {
49
- $error_message = '<p><b>'. __( 'Unable to retrieve new videos due to server configuration.', 'youtube-feed' ) .'</b></p>';
50
- if ( current_user_can( 'manage_youtube_feed_options' ) ) {
51
- $error_message .= '<p>' . sprintf( __( 'You must have the allow_url_fopen directive enabled in your server\'s php.ini file to retrieve live streams.', 'youtube-feed' ), '<a href="https://smashballoon.com/youtube-api-key/" target="_blank" rel="noopener nofollow">', '</a>' ) . '</p>';
52
- }
53
- }
54
-
55
- global $sby_posts_manager;
56
-
57
- $sby_posts_manager->add_frontend_error( 'api', $error_message );
58
- $sby_posts_manager->add_error( 'api', array( 'Error connecting', $error_message ) );
59
-
60
- $sby_posts_manager->add_api_request_delay( 300 );
61
-
62
- return array();
63
- }
64
-
65
- if ( wp_remote_retrieve_response_code( wp_remote_get( $this->url ) ) === 404 ) {
66
- $error_message = '<p><b>'. __( 'Cannot collect videos from this channel. Please make sure this is a valid channel ID.', 'youtube-feed' ) .'</b></p>';
67
-
68
- global $sby_posts_manager;
69
-
70
- $sby_posts_manager->add_frontend_error( 'api', $error_message );
71
- $sby_posts_manager->add_error( 'api', array( 'Error connecting', $error_message ) );
72
-
73
- $sby_posts_manager->add_api_request_delay( 300 );
74
-
75
- return array();
76
- }
77
-
78
- $parsed_obj = new SimpleXMLElement( $this->url, null, true );
79
-
80
- $items_array = array();
81
- if ( isset( $parsed_obj->entry ) ) {
82
- foreach ( $parsed_obj->entry as $video_xml ) {
83
-
84
- $this_item_array = array();
85
-
86
- $high_thumbnail_url = (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->thumbnail->attributes()->url;
87
-
88
- $this_item_array['snippet'] = array(
89
- 'publishedAt' => (string) $video_xml->published,
90
- 'channelId' => (string) $video_xml->children( 'http://www.youtube.com/xml/schemas/2015' )->channelId,
91
- 'title' => (string) $video_xml->title,
92
- 'description' => (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->description,
93
- 'thumbnails' => array(
94
- 'default' => array(
95
- 'url' => (string) str_replace( 'hqdefault.jpg', 'default.jpg', $high_thumbnail_url ),
96
- ),
97
- 'medium' => array(
98
- 'url' => str_replace( 'hqdefault.jpg', 'mqdefault.jpg', $high_thumbnail_url ),
99
- ),
100
- 'high' => array(
101
- 'url' => $high_thumbnail_url,
102
- 'width' => (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->thumbnail->attributes()->width,
103
- 'height' => (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->thumbnail->attributes()->height,
104
- ),
105
- 'standard' => array(
106
- 'url' => str_replace( 'hqdefault.jpg', 'sddefault.jpg', $high_thumbnail_url ),
107
- ),
108
- 'maxres' => array(
109
- 'url' => str_replace( 'hqdefault.jpg', 'maxresdefault.jpg', $high_thumbnail_url ),
110
- ),
111
- ),
112
- 'channelTitle' => (string) $video_xml->author->name,
113
- 'resourceId' => array(
114
- 'videoId' => (string) $video_xml->children( 'http://www.youtube.com/xml/schemas/2015' )->videoId
115
- ),
116
- );
117
- $this_item_array['statistics'] = array(
118
- 'viewCount' => (int) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->community->statistics->attributes()->views,
119
- 'starRating' => (float) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->community->starRating->attributes()->average,
120
- );
121
- $items_array[] = $this_item_array;
122
-
123
- }
124
- }
125
-
126
-
127
- $this->response = $items_array;
128
-
129
- }
130
-
131
- protected function set_url( $endpoint_slug, $params ) {
132
- $url = 'https://www.youtube.com/feeds/videos.xml?channel_id=' . $params['channel_id'];
133
-
134
- $this->set_url_from_args( $url );
135
- }
136
-
137
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SBY_RSS_Connect
7
+ {
8
+ /**
9
+ * @var string
10
+ */
11
+ private $url;
12
+
13
+ /**
14
+ * @var object
15
+ */
16
+ private $response;
17
+
18
+ private $is_live_stream;
19
+
20
+ public function __construct( $endpoint = '', $params = array() ) {
21
+ $this->is_live_stream = false;
22
+ if ( isset( $params['livestream'] ) ) {
23
+ $this->is_live_stream = true;
24
+ }
25
+ $this->set_url( $endpoint, $params );
26
+ }
27
+
28
+ public function get_data() {
29
+ return $this->response;
30
+ }
31
+
32
+ public function set_url_from_args( $url ) {
33
+ $this->url = $url;
34
+ }
35
+
36
+ public function get_url() {
37
+ return $this->url;
38
+ }
39
+
40
+ public function connect() {
41
+
42
+ if ( ! ini_get( 'allow_url_fopen' ) ) {
43
+ if ( ! $this->is_live_stream ) {
44
+ $error_message = '<p><b>'. __( 'Unable to retrieve new videos without an API key.', 'youtube-feed' ) .'</b></p>';
45
+ if ( current_user_can( 'manage_youtube_feed_options' ) ) {
46
+ $error_message .= '<p>' . sprintf( __( 'Due to your server configuration, an API key is required to update your feed. See %sthis FAQ%s to set up an API key.', 'youtube-feed' ), '<a href="https://smashballoon.com/youtube-api-key/" target="_blank" rel="noopener nofollow">', '</a>' ) . '</p>';
47
+ }
48
+ } else {
49
+ $error_message = '<p><b>'. __( 'Unable to retrieve new videos due to server configuration.', 'youtube-feed' ) .'</b></p>';
50
+ if ( current_user_can( 'manage_youtube_feed_options' ) ) {
51
+ $error_message .= '<p>' . sprintf( __( 'You must have the allow_url_fopen directive enabled in your server\'s php.ini file to retrieve live streams.', 'youtube-feed' ), '<a href="https://smashballoon.com/youtube-api-key/" target="_blank" rel="noopener nofollow">', '</a>' ) . '</p>';
52
+ }
53
+ }
54
+
55
+ global $sby_posts_manager;
56
+
57
+ $sby_posts_manager->add_frontend_error( 'api', $error_message );
58
+ $sby_posts_manager->add_error( 'api', array( 'Error connecting', $error_message ) );
59
+
60
+ $sby_posts_manager->add_api_request_delay( 300 );
61
+
62
+ return array();
63
+ }
64
+
65
+ if ( wp_remote_retrieve_response_code( wp_remote_get( $this->url ) ) === 404 ) {
66
+ $error_message = '<p><b>'. __( 'Cannot collect videos from this channel. Please make sure this is a valid channel ID.', 'youtube-feed' ) .'</b></p>';
67
+
68
+ global $sby_posts_manager;
69
+
70
+ $sby_posts_manager->add_frontend_error( 'api', $error_message );
71
+ $sby_posts_manager->add_error( 'api', array( 'Error connecting', $error_message ) );
72
+
73
+ $sby_posts_manager->add_api_request_delay( 300 );
74
+
75
+ return array();
76
+ }
77
+
78
+ $parsed_obj = new SimpleXMLElement( $this->url, null, true );
79
+
80
+ $items_array = array();
81
+ if ( isset( $parsed_obj->entry ) ) {
82
+ foreach ( $parsed_obj->entry as $video_xml ) {
83
+
84
+ $this_item_array = array();
85
+
86
+ $high_thumbnail_url = (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->thumbnail->attributes()->url;
87
+
88
+ $this_item_array['snippet'] = array(
89
+ 'publishedAt' => (string) $video_xml->published,
90
+ 'channelId' => (string) $video_xml->children( 'http://www.youtube.com/xml/schemas/2015' )->channelId,
91
+ 'title' => (string) $video_xml->title,
92
+ 'description' => (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->description,
93
+ 'thumbnails' => array(
94
+ 'default' => array(
95
+ 'url' => (string) str_replace( 'hqdefault.jpg', 'default.jpg', $high_thumbnail_url ),
96
+ ),
97
+ 'medium' => array(
98
+ 'url' => str_replace( 'hqdefault.jpg', 'mqdefault.jpg', $high_thumbnail_url ),
99
+ ),
100
+ 'high' => array(
101
+ 'url' => $high_thumbnail_url,
102
+ 'width' => (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->thumbnail->attributes()->width,
103
+ 'height' => (string) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->thumbnail->attributes()->height,
104
+ ),
105
+ 'standard' => array(
106
+ 'url' => str_replace( 'hqdefault.jpg', 'sddefault.jpg', $high_thumbnail_url ),
107
+ ),
108
+ 'maxres' => array(
109
+ 'url' => str_replace( 'hqdefault.jpg', 'maxresdefault.jpg', $high_thumbnail_url ),
110
+ ),
111
+ ),
112
+ 'channelTitle' => (string) $video_xml->author->name,
113
+ 'resourceId' => array(
114
+ 'videoId' => (string) $video_xml->children( 'http://www.youtube.com/xml/schemas/2015' )->videoId
115
+ ),
116
+ );
117
+ $this_item_array['statistics'] = array(
118
+ 'viewCount' => (int) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->community->statistics->attributes()->views,
119
+ 'starRating' => (float) $video_xml->children( 'http://search.yahoo.com/mrss/' )->group->community->starRating->attributes()->average,
120
+ );
121
+ $items_array[] = $this_item_array;
122
+
123
+ }
124
+ }
125
+
126
+
127
+ $this->response = $items_array;
128
+
129
+ }
130
+
131
+ protected function set_url( $endpoint_slug, $params ) {
132
+ $url = 'https://www.youtube.com/feeds/videos.xml?channel_id=' . $params['channel_id'];
133
+
134
+ $this->set_url_from_args( $url );
135
+ }
136
+
137
  }
inc/class-sby-settings.php CHANGED
@@ -1,367 +1,367 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SBY_Settings {
7
- /**
8
- * @var array
9
- */
10
- protected $atts;
11
-
12
- /**
13
- * @var array
14
- */
15
- protected $db;
16
-
17
- /**
18
- * @var array
19
- */
20
- protected $settings;
21
-
22
- /**
23
- * @var array
24
- */
25
- protected $feed_type_and_terms;
26
-
27
- /**
28
- * @var array
29
- */
30
- protected $connected_accounts;
31
-
32
- /**
33
- * @var array
34
- */
35
- protected $connected_accounts_in_feed;
36
-
37
- /**
38
- * @var string
39
- */
40
- protected $transient_name;
41
-
42
- /**
43
- * SBY_Settings constructor.
44
- *
45
- * Overwritten in the Pro version.
46
- *
47
- * @param array $atts shortcode settings
48
- * @param array $db settings from the wp_options table
49
- */
50
- public function __construct( $atts, $db ) {
51
- $atts = is_array( $atts ) ? $atts : array();
52
-
53
- // convert string 'false' and 'true' to booleans
54
- foreach ( $atts as $key => $value ) {
55
- if ( $value === 'false' ) {
56
- $atts[ $key ] = false;
57
- } elseif ( $value === 'true' ) {
58
- $atts[ $key ] = true;
59
- }
60
- }
61
-
62
- $this->atts = $atts;
63
- $this->db = $db;
64
-
65
- $this->connected_accounts = isset( $db['connected_accounts'] ) ? $db['connected_accounts'] : array();
66
-
67
- if ( ! empty( $this->db['api_key'] ) ) {
68
- $this->connected_accounts = array(
69
- 'own' => array(
70
- 'access_token' => '',
71
- 'refresh_token' => '',
72
- 'channel_id' => '',
73
- 'username' => '',
74
- 'is_valid' => true,
75
- 'last_checked' => '',
76
- 'profile_picture' => '',
77
- 'privacy' => '',
78
- 'expires' => '2574196927',
79
- 'api_key' => $this->db['api_key']
80
- )
81
- );
82
- }
83
-
84
- $this->settings = wp_parse_args( $atts, $db );
85
-
86
- if ( empty( $this->connected_accounts ) ) {
87
- $this->settings['showheader'] = false;
88
- $this->connected_accounts = array( 'rss_only' => true );
89
- }
90
-
91
- $this->settings['nummobile'] = $this->settings['num'];
92
- $this->settings['minnum'] = $this->settings['num'];
93
-
94
- $this->after_settings_set();
95
- }
96
-
97
- protected function after_settings_set() {
98
-
99
- }
100
-
101
- /**
102
- * @return array
103
- *
104
- * @since 1.0
105
- */
106
- public function get_settings() {
107
- return $this->settings;
108
- }
109
-
110
- /**
111
- * The plugin will output settings on the frontend for debugging purposes.
112
- * Safe settings to display are added here.
113
- *
114
- * Overwritten in the Pro version.
115
- *
116
- * @return array
117
- *
118
- * @since 1.0
119
- */
120
- public static function get_public_db_settings_keys() {
121
- $public = array(
122
- );
123
-
124
- return $public;
125
- }
126
-
127
- /**
128
- * @return array
129
- *
130
- * @since 1.0
131
- */
132
- public function get_connected_accounts() {
133
- return $this->connected_accounts;
134
- }
135
-
136
- /**
137
- * @return array|bool
138
- *
139
- * @since 1.0
140
- */
141
- public function get_connected_accounts_in_feed() {
142
- if ( isset( $this->connected_accounts_in_feed ) ) {
143
- return $this->connected_accounts_in_feed;
144
- } else {
145
- return false;
146
- }
147
- }
148
-
149
- /**
150
- * @return bool|string
151
- *
152
- * @since 1.0
153
- */
154
- public function get_transient_name() {
155
- if ( isset( $this->transient_name ) ) {
156
- return $this->transient_name;
157
- } else {
158
- return false;
159
- }
160
- }
161
-
162
- /**
163
- * Uses the feed types and terms as well as as some
164
- * settings to create a semi-unique feed id used for
165
- * caching and other features.
166
- *
167
- * Overwritten in the Pro version.
168
- *
169
- * @param string $transient_name
170
- *
171
- * @since 1.0
172
- */
173
- public function set_transient_name( $transient_name = '' ) {
174
-
175
- if ( ! empty( $transient_name ) ) {
176
- $this->transient_name = $transient_name;
177
- } elseif ( ! empty( $this->settings['feedid'] ) ) {
178
- $this->transient_name = 'sby_' . $this->settings['feedid'];
179
- } else {
180
- $feed_type_and_terms = $this->feed_type_and_terms;
181
-
182
- $sby_transient_name = 'sby_';
183
-
184
- if ( isset( $feed_type_and_terms['channels'] ) ) {
185
- foreach ( $feed_type_and_terms['channels'] as $term_and_params ) {
186
- $channel = $term_and_params['term'];
187
- $sby_transient_name .= $channel;
188
- }
189
- }
190
-
191
- $num = $this->settings['num'];
192
-
193
- $num_length = strlen( $num ) + 1;
194
-
195
- //Add both parts of the caching string together and make sure it doesn't exceed 45
196
- $sby_transient_name = substr( $sby_transient_name, 0, 45 - $num_length );
197
-
198
- $sby_transient_name .= '#' . $num;
199
-
200
- $this->transient_name = $sby_transient_name;
201
- }
202
-
203
- }
204
-
205
- /**
206
- * @return array|bool
207
- *
208
- * @since 1.0
209
- */
210
- public function get_feed_type_and_terms() {
211
- if ( isset( $this->feed_type_and_terms ) ) {
212
- return $this->feed_type_and_terms;
213
- } else {
214
- return false;
215
- }
216
- }
217
-
218
- public function feed_type_and_terms_display() {
219
-
220
- if ( ! isset( $this->feed_type_and_terms ) ) {
221
- return array();
222
- }
223
- $return = array();
224
- foreach ( $this->feed_type_and_terms as $feed_type => $type_terms ) {
225
- foreach ( $type_terms as $term ) {
226
- $return[] = $term['term'];
227
- }
228
- }
229
- return $return;
230
-
231
- }
232
-
233
- /**
234
- * Based on the settings related to retrieving post data from the API,
235
- * this setting is used to make sure all endpoints needed for the feed are
236
- * connected and stored for easily looping through when adding posts
237
- *
238
- * Overwritten in the Pro version.
239
- *
240
- * @since 1.0
241
- */
242
- public function set_feed_type_and_terms() {
243
- //global $sby_posts_manager;
244
-
245
- $connected_accounts_in_feed = array();
246
- $feed_type_and_terms = array(
247
- 'channels' => array()
248
- );
249
-
250
- if ( ! empty( $this->settings['id'] ) ) {
251
- $channel_array = is_array( $this->settings['id'] ) ? $this->settings['id'] : explode( ',', str_replace( ' ', '', $this->settings['id'] ) );
252
- foreach ( $channel_array as $channel ) {
253
- if ( isset( $this->connected_accounts[ $channel ] ) ) {
254
- $feed_type_and_terms['channels'][] = array(
255
- 'term' => $this->connected_accounts[ $channel ]['channel_id'],
256
- 'params' => array(
257
- 'channel_id' => $this->connected_accounts[ $channel ]['channel_id']
258
- )
259
- );
260
- $connected_accounts_in_feed[ $this->connected_accounts[ $channel ]['channel_id'] ] = $this->connected_accounts[ $channel ];
261
- }
262
- }
263
-
264
- if ( empty( $connected_accounts_in_feed ) ) {
265
- $an_account = array();
266
- foreach ( $this->connected_accounts as $account ) {
267
- if ( empty( $an_account ) ) {
268
- $an_account = $account;
269
- }
270
- }
271
-
272
- foreach ( $channel_array as $channel ) {
273
- $feed_type_and_terms['channels'][] = array(
274
- 'term' => $channel,
275
- 'params' => array(
276
- 'channel_id' => $channel
277
- )
278
- );
279
- $connected_accounts_in_feed[ $channel ] = $an_account;
280
- }
281
- }
282
-
283
- } elseif ( ! empty( $this->settings['channel'] ) ) {
284
- $channel_array = is_array( $this->settings['channel'] ) ? $this->settings['channel'] : explode( ',', str_replace( ' ', '', $this->settings['channel'] ) );
285
-
286
- $an_account = array();
287
- foreach ( $this->connected_accounts as $account ) {
288
- if ( empty( $an_account ) ) {
289
- $an_account = $account;
290
- }
291
- }
292
-
293
- foreach ( $channel_array as $channel ) {
294
- if ( strpos( $channel, 'UC' ) !== 0 ) {
295
- $channel_id = sby_get_channel_id_from_channel_name( $channel );
296
- if ( $channel_id ) {
297
- $feed_type_and_terms['channels'][] = array(
298
- 'term' => $channel_id,
299
- 'params' => array(
300
- 'channel_id' => $channel_id
301
- )
302
- );
303
- $connected_accounts_in_feed[ $channel_id ] = $an_account;
304
- } else {
305
- $feed_type_and_terms['channels'][] = array(
306
- 'term' => $channel,
307
- 'params' => array(
308
- 'channel_name' => $channel
309
- )
310
- );
311
- $connected_accounts_in_feed[ $channel ] = $an_account;
312
- }
313
-
314
- } else {
315
- $feed_type_and_terms['channels'][] = array(
316
- 'term' => $channel,
317
- 'params' => array(
318
- 'channel_id' => $channel
319
- )
320
- );
321
- $connected_accounts_in_feed[ $channel ] = $an_account;
322
- }
323
- }
324
-
325
- } else {
326
- foreach ( $this->connected_accounts as $connected_account ) {
327
- if ( empty( $feed_type_and_terms['channels'] ) ) {
328
- $feed_type_and_terms['channels'][] = array(
329
- 'term' => $connected_account['channel_id'],
330
- 'params' => array(
331
- 'channel_id' => $connected_account['channel_id']
332
- )
333
- );
334
- $connected_accounts_in_feed[ $connected_account['channel_id'] ] = $connected_account;
335
- }
336
-
337
- }
338
- }
339
-
340
- $this->connected_accounts_in_feed = $connected_accounts_in_feed;
341
- $this->feed_type_and_terms = $feed_type_and_terms;
342
- }
343
-
344
- /**
345
- * @return float|int
346
- *
347
- * @since 1.0
348
- */
349
- public function get_cache_time_in_seconds() {
350
- if ( $this->db['caching_type'] === 'background' ) {
351
- return SBY_CRON_UPDATE_CACHE_TIME;
352
- } else {
353
- //If the caching time doesn't exist in the database then set it to be 1 hour
354
- $cache_time = isset( $this->settings['cache_time'] ) ? (int)$this->settings['cache_time'] : 1;
355
- $cache_time_unit = isset( $this->settings['cache_time_unit'] ) ? $this->settings['cache_time_unit'] : 'hours';
356
-
357
- //Calculate the cache time in seconds
358
- if ( $cache_time_unit == 'minutes' ) $cache_time_unit = 60;
359
- if ( $cache_time_unit == 'hours' ) $cache_time_unit = 60*60;
360
- if ( $cache_time_unit == 'days' ) $cache_time_unit = 60*60*24;
361
-
362
- $cache_time = max( 900, $cache_time * $cache_time_unit );
363
-
364
- return $cache_time;
365
- }
366
- }
367
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SBY_Settings {
7
+ /**
8
+ * @var array
9
+ */
10
+ protected $atts;
11
+
12
+ /**
13
+ * @var array
14
+ */
15
+ protected $db;
16
+
17
+ /**
18
+ * @var array
19
+ */
20
+ protected $settings;
21
+
22
+ /**
23
+ * @var array
24
+ */
25
+ protected $feed_type_and_terms;
26
+
27
+ /**
28
+ * @var array
29
+ */
30
+ protected $connected_accounts;
31
+
32
+ /**
33
+ * @var array
34
+ */
35
+ protected $connected_accounts_in_feed;
36
+
37
+ /**
38
+ * @var string
39
+ */
40
+ protected $transient_name;
41
+
42
+ /**
43
+ * SBY_Settings constructor.
44
+ *
45
+ * Overwritten in the Pro version.
46
+ *
47
+ * @param array $atts shortcode settings
48
+ * @param array $db settings from the wp_options table
49
+ */
50
+ public function __construct( $atts, $db ) {
51
+ $atts = is_array( $atts ) ? $atts : array();
52
+
53
+ // convert string 'false' and 'true' to booleans
54
+ foreach ( $atts as $key => $value ) {
55
+ if ( $value === 'false' ) {
56
+ $atts[ $key ] = false;
57
+ } elseif ( $value === 'true' ) {
58
+ $atts[ $key ] = true;
59
+ }
60
+ }
61
+
62
+ $this->atts = $atts;
63
+ $this->db = $db;
64
+
65
+ $this->connected_accounts = isset( $db['connected_accounts'] ) ? $db['connected_accounts'] : array();
66
+
67
+ if ( ! empty( $this->db['api_key'] ) ) {
68
+ $this->connected_accounts = array(
69
+ 'own' => array(
70
+ 'access_token' => '',
71
+ 'refresh_token' => '',
72
+ 'channel_id' => '',
73
+ 'username' => '',
74
+ 'is_valid' => true,
75
+ 'last_checked' => '',
76
+ 'profile_picture' => '',
77
+ 'privacy' => '',
78
+ 'expires' => '2574196927',
79
+ 'api_key' => $this->db['api_key']
80
+ )
81
+ );
82
+ }
83
+
84
+ $this->settings = wp_parse_args( $atts, $db );
85
+
86
+ if ( empty( $this->connected_accounts ) ) {
87
+ $this->settings['showheader'] = false;
88
+ $this->connected_accounts = array( 'rss_only' => true );
89
+ }
90
+
91
+ $this->settings['nummobile'] = $this->settings['num'];
92
+ $this->settings['minnum'] = $this->settings['num'];
93
+
94
+ $this->after_settings_set();
95
+ }
96
+
97
+ protected function after_settings_set() {
98
+
99
+ }
100
+
101
+ /**
102
+ * @return array
103
+ *
104
+ * @since 1.0
105
+ */
106
+ public function get_settings() {
107
+ return $this->settings;
108
+ }
109
+
110
+ /**
111
+ * The plugin will output settings on the frontend for debugging purposes.
112
+ * Safe settings to display are added here.
113
+ *
114
+ * Overwritten in the Pro version.
115
+ *
116
+ * @return array
117
+ *
118
+ * @since 1.0
119
+ */
120
+ public static function get_public_db_settings_keys() {
121
+ $public = array(
122
+ );
123
+
124
+ return $public;
125
+ }
126
+
127
+ /**
128
+ * @return array
129
+ *
130
+ * @since 1.0
131
+ */
132
+ public function get_connected_accounts() {
133
+ return $this->connected_accounts;
134
+ }
135
+
136
+ /**
137
+ * @return array|bool
138
+ *
139
+ * @since 1.0
140
+ */
141
+ public function get_connected_accounts_in_feed() {
142
+ if ( isset( $this->connected_accounts_in_feed ) ) {
143
+ return $this->connected_accounts_in_feed;
144
+ } else {
145
+ return false;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * @return bool|string
151
+ *
152
+ * @since 1.0
153
+ */
154
+ public function get_transient_name() {
155
+ if ( isset( $this->transient_name ) ) {
156
+ return $this->transient_name;
157
+ } else {
158
+ return false;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Uses the feed types and terms as well as as some
164
+ * settings to create a semi-unique feed id used for
165
+ * caching and other features.
166
+ *
167
+ * Overwritten in the Pro version.
168
+ *
169
+ * @param string $transient_name
170
+ *
171
+ * @since 1.0
172
+ */
173
+ public function set_transient_name( $transient_name = '' ) {
174
+
175
+ if ( ! empty( $transient_name ) ) {
176
+ $this->transient_name = $transient_name;
177
+ } elseif ( ! empty( $this->settings['feedid'] ) ) {
178
+ $this->transient_name = 'sby_' . $this->settings['feedid'];
179
+ } else {
180
+ $feed_type_and_terms = $this->feed_type_and_terms;
181
+
182
+ $sby_transient_name = 'sby_';
183
+
184
+ if ( isset( $feed_type_and_terms['channels'] ) ) {
185
+ foreach ( $feed_type_and_terms['channels'] as $term_and_params ) {
186
+ $channel = $term_and_params['term'];
187
+ $sby_transient_name .= $channel;
188
+ }
189
+ }
190
+
191
+ $num = $this->settings['num'];
192
+
193
+ $num_length = strlen( $num ) + 1;
194
+
195
+ //Add both parts of the caching string together and make sure it doesn't exceed 45
196
+ $sby_transient_name = substr( $sby_transient_name, 0, 45 - $num_length );
197
+
198
+ $sby_transient_name .= '#' . $num;
199
+
200
+ $this->transient_name = $sby_transient_name;
201
+ }
202
+
203
+ }
204
+
205
+ /**
206
+ * @return array|bool
207
+ *
208
+ * @since 1.0
209
+ */
210
+ public function get_feed_type_and_terms() {
211
+ if ( isset( $this->feed_type_and_terms ) ) {
212
+ return $this->feed_type_and_terms;
213
+ } else {
214
+ return false;
215
+ }
216
+ }
217
+
218
+ public function feed_type_and_terms_display() {
219
+
220
+ if ( ! isset( $this->feed_type_and_terms ) ) {
221
+ return array();
222
+ }
223
+ $return = array();
224
+ foreach ( $this->feed_type_and_terms as $feed_type => $type_terms ) {
225
+ foreach ( $type_terms as $term ) {
226
+ $return[] = $term['term'];
227
+ }
228
+ }
229
+ return $return;
230
+
231
+ }
232
+
233
+ /**
234
+ * Based on the settings related to retrieving post data from the API,
235
+ * this setting is used to make sure all endpoints needed for the feed are
236
+ * connected and stored for easily looping through when adding posts
237
+ *
238
+ * Overwritten in the Pro version.
239
+ *
240
+ * @since 1.0
241
+ */
242
+ public function set_feed_type_and_terms() {
243
+ //global $sby_posts_manager;
244
+
245
+ $connected_accounts_in_feed = array();
246
+ $feed_type_and_terms = array(
247
+ 'channels' => array()
248
+ );
249
+
250
+ if ( ! empty( $this->settings['id'] ) ) {
251
+ $channel_array = is_array( $this->settings['id'] ) ? $this->settings['id'] : explode( ',', str_replace( ' ', '', $this->settings['id'] ) );
252
+ foreach ( $channel_array as $channel ) {
253
+ if ( isset( $this->connected_accounts[ $channel ] ) ) {
254
+ $feed_type_and_terms['channels'][] = array(
255
+ 'term' => $this->connected_accounts[ $channel ]['channel_id'],
256
+ 'params' => array(
257
+ 'channel_id' => $this->connected_accounts[ $channel ]['channel_id']
258
+ )
259
+ );
260
+ $connected_accounts_in_feed[ $this->connected_accounts[ $channel ]['channel_id'] ] = $this->connected_accounts[ $channel ];
261
+ }
262
+ }
263
+
264
+ if ( empty( $connected_accounts_in_feed ) ) {
265
+ $an_account = array();
266
+ foreach ( $this->connected_accounts as $account ) {
267
+ if ( empty( $an_account ) ) {
268
+ $an_account = $account;
269
+ }
270
+ }
271
+
272
+ foreach ( $channel_array as $channel ) {
273
+ $feed_type_and_terms['channels'][] = array(
274
+ 'term' => $channel,
275
+ 'params' => array(
276
+ 'channel_id' => $channel
277
+ )
278
+ );
279
+ $connected_accounts_in_feed[ $channel ] = $an_account;
280
+ }
281
+ }
282
+
283
+ } elseif ( ! empty( $this->settings['channel'] ) ) {
284
+ $channel_array = is_array( $this->settings['channel'] ) ? $this->settings['channel'] : explode( ',', str_replace( ' ', '', $this->settings['channel'] ) );
285
+
286
+ $an_account = array();
287
+ foreach ( $this->connected_accounts as $account ) {
288
+ if ( empty( $an_account ) ) {
289
+ $an_account = $account;
290
+ }
291
+ }
292
+
293
+ foreach ( $channel_array as $channel ) {
294
+ if ( strpos( $channel, 'UC' ) !== 0 ) {
295
+ $channel_id = sby_get_channel_id_from_channel_name( $channel );
296
+ if ( $channel_id ) {
297
+ $feed_type_and_terms['channels'][] = array(
298
+ 'term' => $channel_id,
299
+ 'params' => array(
300
+ 'channel_id' => $channel_id
301
+ )
302
+ );
303
+ $connected_accounts_in_feed[ $channel_id ] = $an_account;
304
+ } else {
305
+ $feed_type_and_terms['channels'][] = array(
306
+ 'term' => $channel,
307
+ 'params' => array(
308
+ 'channel_name' => $channel
309
+ )
310
+ );
311
+ $connected_accounts_in_feed[ $channel ] = $an_account;
312
+ }
313
+
314
+ } else {
315
+ $feed_type_and_terms['channels'][] = array(
316
+ 'term' => $channel,
317
+ 'params' => array(
318
+ 'channel_id' => $channel
319
+ )
320
+ );
321
+ $connected_accounts_in_feed[ $channel ] = $an_account;
322
+ }
323
+ }
324
+
325
+ } else {
326
+ foreach ( $this->connected_accounts as $connected_account ) {
327
+ if ( empty( $feed_type_and_terms['channels'] ) ) {
328
+ $feed_type_and_terms['channels'][] = array(
329
+ 'term' => $connected_account['channel_id'],
330
+ 'params' => array(
331
+ 'channel_id' => $connected_account['channel_id']
332
+ )
333
+ );
334
+ $connected_accounts_in_feed[ $connected_account['channel_id'] ] = $connected_account;
335
+ }
336
+
337
+ }
338
+ }
339
+
340
+ $this->connected_accounts_in_feed = $connected_accounts_in_feed;
341
+ $this->feed_type_and_terms = $feed_type_and_terms;
342
+ }
343
+
344
+ /**
345
+ * @return float|int
346
+ *
347
+ * @since 1.0
348
+ */
349
+ public function get_cache_time_in_seconds() {
350
+ if ( $this->db['caching_type'] === 'background' ) {
351
+ return SBY_CRON_UPDATE_CACHE_TIME;
352
+ } else {
353
+ //If the caching time doesn't exist in the database then set it to be 1 hour
354
+ $cache_time = isset( $this->settings['cache_time'] ) ? (int)$this->settings['cache_time'] : 1;
355
+ $cache_time_unit = isset( $this->settings['cache_time_unit'] ) ? $this->settings['cache_time_unit'] : 'hours';
356
+
357
+ //Calculate the cache time in seconds
358
+ if ( $cache_time_unit == 'minutes' ) $cache_time_unit = 60;
359
+ if ( $cache_time_unit == 'hours' ) $cache_time_unit = 60*60;
360
+ if ( $cache_time_unit == 'days' ) $cache_time_unit = 60*60*24;
361
+
362
+ $cache_time = max( 900, $cache_time * $cache_time_unit );
363
+
364
+ return $cache_time;
365
+ }
366
+ }
367
  }
inc/class-sby-vars.php CHANGED
@@ -1,36 +1,36 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SBY_Vars {
7
- public function version() { return SBYVER; }
8
-
9
- public function plugin_dir() { return SBY_PLUGIN_DIR; }
10
-
11
- public function plugin_url() { return SBY_PLUGIN_URL; }
12
-
13
- public function plugin_basename() { return SBY_PLUGIN_BASENAME; }
14
-
15
- public function cron_update_cache_time() { return SBY_CRON_UPDATE_CACHE_TIME; }
16
-
17
- public function max_records() { return SBY_MAX_RECORDS; }
18
-
19
- public function text_domain() { return SBY_TEXT_DOMAIN; }
20
-
21
- public function slug() { return SBY_SLUG; }
22
-
23
- public function plugin_name( $with_a_an = false ) { if ( $with_a_an ) { return SBY_INDEF_ART . ' ' . SBY_PLUGIN_NAME; } return SBY_PLUGIN_NAME; }
24
-
25
- public function social_network() { return SBY_SOCIAL_NETWORK; }
26
-
27
- public function setup_url() { return SBY_SETUP_URL; }
28
-
29
- public function support_url() { return SBY_SUPPORT_URL; }
30
-
31
- public function oauth_processor_url() { return SBY_OAUTH_PROCESSOR_URL; }
32
-
33
- public function demo_url() { return SBY_DEMO_URL; }
34
-
35
- public function pro_logo() { return SBY_PRO_LOGO; }
36
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SBY_Vars {
7
+ public function version() { return SBYVER; }
8
+
9
+ public function plugin_dir() { return SBY_PLUGIN_DIR; }
10
+
11
+ public function plugin_url() { return SBY_PLUGIN_URL; }
12
+
13
+ public function plugin_basename() { return SBY_PLUGIN_BASENAME; }
14
+
15
+ public function cron_update_cache_time() { return SBY_CRON_UPDATE_CACHE_TIME; }
16
+
17
+ public function max_records() { return SBY_MAX_RECORDS; }
18
+
19
+ public function text_domain() { return SBY_TEXT_DOMAIN; }
20
+
21
+ public function slug() { return SBY_SLUG; }
22
+
23
+ public function plugin_name( $with_a_an = false ) { if ( $with_a_an ) { return SBY_INDEF_ART . ' ' . SBY_PLUGIN_NAME; } return SBY_PLUGIN_NAME; }
24
+
25
+ public function social_network() { return SBY_SOCIAL_NETWORK; }
26
+
27
+ public function setup_url() { return SBY_SETUP_URL; }
28
+
29
+ public function support_url() { return SBY_SUPPORT_URL; }
30
+
31
+ public function oauth_processor_url() { return SBY_OAUTH_PROCESSOR_URL; }
32
+
33
+ public function demo_url() { return SBY_DEMO_URL; }
34
+
35
+ public function pro_logo() { return SBY_PRO_LOGO; }
36
  }
inc/class-sby-wp-post.php CHANGED
@@ -1,166 +1,166 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- die( '-1' );
4
- }
5
-
6
- class SBY_WP_Post
7
- {
8
- private $youtube_api_data;
9
-
10
- private $feed_id;
11
-
12
- private $wp_post_id;
13
-
14
- public function __construct( $json_or_array, $feed_id ) {
15
- $this->youtube_api_data = $json_or_array;
16
- $this->feed_id = $feed_id;
17
- }
18
-
19
- public function update_post( $status = 'draft' ) {
20
- if ( ! $this->get_wp_post_id() ) {
21
- $postarr = array(
22
- 'post_title' => SBY_Parse::get_video_title( $this->youtube_api_data ),
23
- 'post_content' => $this->get_post_content(),
24
- 'post_type' => SBY_CPT,
25
- 'post_date' => date( 'Y-m-d H:i:s', SBY_Parse::get_timestamp( $this->youtube_api_data ) + sby_get_utc_offset() ),
26
- 'post_date_gmt' => date( 'Y-m-d H:i:s', SBY_Parse::get_timestamp( $this->youtube_api_data ) ),
27
- 'post_status' => $status
28
- );
29
- $wp_post_id = wp_insert_post( $postarr );
30
-
31
- if ( (int)$wp_post_id > 0 ) {
32
- $this->wp_post_id = $wp_post_id;
33
-
34
- $success = $this->update_meta();
35
- }
36
- }
37
-
38
- }
39
-
40
- public function update_meta() {
41
- if ( ! isset( $this->wp_post_id ) ) {
42
- return false;
43
- }
44
-
45
- $prefix = 'sby_';
46
-
47
- update_post_meta( $this->wp_post_id, $prefix . 'video_id', SBY_Parse::get_video_id( $this->youtube_api_data ) );
48
- update_post_meta( $this->wp_post_id, $prefix . 'feed_id', sby_strip_after_hash( $this->feed_id ) );
49
- update_post_meta( $this->wp_post_id, $prefix . 'channel_id', SBY_Parse::get_channel_id( $this->youtube_api_data ) );
50
- update_post_meta( $this->wp_post_id, $prefix . 'channel_title', SBY_Parse::get_channel_title( $this->youtube_api_data ) );
51
- update_post_meta( $this->wp_post_id, $prefix . 'description', SBY_Parse::get_caption( $this->youtube_api_data ) );
52
- update_post_meta( $this->wp_post_id, $prefix . 'last_updated', date( 'Y-m-d H:i:s' ) );
53
- update_post_meta( $this->wp_post_id, $prefix . 'thumbnails', SBY_Parse::get_media_src_set( $this->youtube_api_data ) );
54
- update_post_meta( $this->wp_post_id, $prefix . 'youtube_publish_date', date( 'Y-m-d H:i:s', SBY_Parse::get_timestamp( $this->youtube_api_data ) ) );
55
-
56
- if ( class_exists( 'SBY_Parse_Pro' ) ) {
57
- update_post_meta( $this->wp_post_id, $prefix . 'live_broadcast_content', SBY_Parse_Pro::get_live_broadcast_content( $this->youtube_api_data ) );
58
- }
59
-
60
- $post_array = $this->youtube_api_data;
61
-
62
- array_walk_recursive( $post_array, 'sby_replace_double_quotes' );
63
-
64
- update_post_meta( $this->wp_post_id, $prefix . 'json', esc_sql( wp_json_encode( $post_array ) ) );
65
-
66
- return true;
67
- }
68
-
69
- public function post_content_description_is_incomplete() {
70
- $content = get_the_content( '', false, $this->get_wp_post_id() );
71
-
72
- return (strpos( $content, '<!-- sby:description-incomplete -->' ) !== false);
73
- }
74
-
75
- public function update_video_details() {
76
- if ( empty( $this->youtube_api_data['statistics'] ) ) {
77
- return false;
78
- }
79
-
80
- $post_id = $this->get_wp_post_id();
81
-
82
- if ( $post_id ) {
83
- $prefix = 'sby_';
84
-
85
- if ( class_exists( 'SBY_Parse_Pro' ) ) {
86
- update_post_meta( $post_id, $prefix . 'comment_count', SBY_Parse_Pro::get_comment_count( $this->youtube_api_data ) );
87
- update_post_meta( $post_id, $prefix . 'view_count', SBY_Parse_Pro::get_view_count( $this->youtube_api_data ) );
88
- update_post_meta( $post_id, $prefix . 'like_count', SBY_Parse_Pro::get_like_count( $this->youtube_api_data ) );
89
- update_post_meta( $post_id, $prefix . 'scheduled_start_time', date( 'Y-m-d H:i:s', SBY_Parse_Pro::get_scheduled_start_timestamp( $this->youtube_api_data ) ) );
90
- update_post_meta( $post_id, $prefix . 'actual_start_time', date( 'Y-m-d H:i:s', SBY_Parse_Pro::get_actual_start_timestamp( $this->youtube_api_data ) ) );
91
- update_post_meta( $post_id, $prefix . 'actual_end_time', date( 'Y-m-d H:i:s', SBY_Parse_Pro::get_actual_end_timestamp( $this->youtube_api_data ) ) );
92
- }
93
-
94
- update_post_meta( $post_id, $prefix . 'last_details_check_time', date( 'Y-m-d H:i:s' ) );
95
- $description = SBY_Parse::get_caption( $this->youtube_api_data );
96
- if ( ! empty( $description ) ) {
97
- update_post_meta( $post_id, $prefix . 'description', $description );
98
- if ( $this->post_content_description_is_incomplete() ) {
99
- $this->update_content();
100
- }
101
- }
102
- return true;
103
- }
104
-
105
- return false;
106
- }
107
- public function update_content() {
108
- $my_post = array();
109
- $my_post['ID'] = $this->get_wp_post_id();
110
- $my_post['post_content'] = $this->get_post_content( true );
111
-
112
- wp_update_post( $my_post );
113
- }
114
-
115
- public static function maybe_get_channel_id_for_name( $name ) {
116
-
117
- }
118
-
119
- public static function maybe_get_channel_id_for_channel_title( $title ) {
120
- global $wpdb;
121
-
122
- $channel_id = $wpdb->get_col( $wpdb->prepare( "
123
- SELECT Max(CASE
124
- WHEN m.meta_key = 'sby_channel_id' THEN m.meta_value
125
- ELSE NULL
126
- END) AS sby_channel_id
127
- FROM $wpdb->postmeta as m
128
- WHERE m.post_id IN (SELECT m2.post_id FROM $wpdb->postmeta as m2 WHERE m2.meta_key = 'sby_channel_title' AND m2.meta_value = %s )
129
- GROUP BY m.post_id
130
- LIMIT 1", $title ) );
131
-
132
- if ( isset( $channel_id[0] ) ) {
133
- return $channel_id[0];
134
- }
135
- return false;
136
- }
137
-
138
- public function get_wp_post_id() {
139
- if ( isset( $this->wp_post_id ) ) {
140
- return $this->wp_post_id;
141
- }
142
-
143
- $video_id = SBY_Parse::get_video_id( $this->youtube_api_data );
144
-
145
- global $wpdb;
146
- $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_key FROM $wpdb->postmeta WHERE meta_value = %s AND meta_key = %s", $video_id, 'sby_video_id' ), ARRAY_A );
147
-
148
- if ( isset( $results[0] ) ) {
149
- $this->wp_post_id = $results[0]['post_id'];
150
-
151
- return $results[0]['post_id'];
152
- } else {
153
- return false;
154
- }
155
- }
156
-
157
- protected function get_post_content( $override = false ) {
158
- $description = SBY_Parse::get_caption( $this->youtube_api_data );
159
- $flag = '';
160
- if ( ! $override && substr( $description, -3 ) === '...' ) {
161
- $flag = '<!-- sby:description-incomplete -->';
162
- }
163
-
164
- return '['.SBY_SLUG.'-single]<!-- sby:description-start -->' . wp_kses_post( $description ) . '<!-- sby:description-end -->' . $flag;
165
- }
166
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( '-1' );
4
+ }
5
+
6
+ class SBY_WP_Post
7
+ {
8
+ private $youtube_api_data;
9
+
10
+ private $feed_id;
11
+
12
+ private $wp_post_id;
13
+
14
+ public function __construct( $json_or_array, $feed_id ) {
15
+ $this->youtube_api_data = $json_or_array;
16
+ $this->feed_id = $feed_id;
17
+ }
18
+
19
+ public function update_post( $status = 'draft' ) {
20
+ if ( ! $this->get_wp_post_id() ) {
21
+ $postarr = array(
22
+ 'post_title' => SBY_Parse::get_video_title( $this->youtube_api_data ),
23
+ 'post_content' => $this->get_post_content(),
24
+ 'post_type' => SBY_CPT,
25
+ 'post_date' => date( 'Y-m-d H:i:s', SBY_Parse::get_timestamp( $this->youtube_api_data ) + sby_get_utc_offset() ),
26
+ 'post_date_gmt' => date( 'Y-m-d H:i:s', SBY_Parse::get_timestamp( $this->youtube_api_data ) ),
27
+ 'post_status' => $status
28
+ );
29
+ $wp_post_id = wp_insert_post( $postarr );
30
+
31
+ if ( (int)$wp_post_id > 0 ) {
32
+ $this->wp_post_id = $wp_post_id;
33
+
34
+ $success = $this->update_meta();
35
+ }
36
+ }
37
+
38
+ }
39
+
40
+ public function update_meta() {
41
+ if ( ! isset( $this->wp_post_id ) ) {
42
+ return false;
43
+ }
44
+
45
+ $prefix = 'sby_';
46
+
47
+ update_post_meta( $this->wp_post_id, $prefix . 'video_id', SBY_Parse::get_video_id( $this->youtube_api_data ) );
48
+ update_post_meta( $this->wp_post_id, $prefix . 'feed_id', sby_strip_after_hash( $this->feed_id ) );
49
+ update_post_meta( $this->wp_post_id, $prefix . 'channel_id', SBY_Parse::get_channel_id( $this->youtube_api_data ) );
50
+ update_post_meta( $this->wp_post_id, $prefix . 'channel_title', SBY_Parse::get_channel_title( $this->youtube_api_data ) );
51
+ update_post_meta( $this->wp_post_id, $prefix . 'description', SBY_Parse::get_caption( $this->youtube_api_data ) );
52
+ update_post_meta( $this->wp_post_id, $prefix . 'last_updated', date( 'Y-m-d H:i:s' ) );
53
+ update_post_meta( $this->wp_post_id, $prefix . 'thumbnails', SBY_Parse::get_media_src_set( $this->youtube_api_data ) );
54
+ update_post_meta( $this->wp_post_id, $prefix . 'youtube_publish_date', date( 'Y-m-d H:i:s', SBY_Parse::get_timestamp( $this->youtube_api_data ) ) );
55
+
56
+ if ( class_exists( 'SBY_Parse_Pro' ) ) {
57
+ update_post_meta( $this->wp_post_id, $prefix . 'live_broadcast_content', SBY_Parse_Pro::get_live_broadcast_content( $this->youtube_api_data ) );
58
+ }
59
+
60
+ $post_array = $this->youtube_api_data;
61
+
62
+ array_walk_recursive( $post_array, 'sby_replace_double_quotes' );
63
+
64
+ update_post_meta( $this->wp_post_id, $prefix . 'json', esc_sql( wp_json_encode( $post_array ) ) );
65
+
66
+ return true;
67
+ }
68
+
69
+ public function post_content_description_is_incomplete() {
70
+ $content = get_the_content( '', false, $this->get_wp_post_id() );
71
+
72
+ return (strpos( $content, '<!-- sby:description-incomplete -->' ) !== false);
73
+ }
74
+
75
+ public function update_video_details() {
76
+ if ( empty( $this->youtube_api_data['statistics'] ) ) {
77
+ return false;
78
+ }
79
+
80
+ $post_id = $this->get_wp_post_id();
81
+
82
+ if ( $post_id ) {
83
+ $prefix = 'sby_';
84
+
85
+ if ( class_exists( 'SBY_Parse_Pro' ) ) {
86
+ update_post_meta( $post_id, $prefix . 'comment_count', SBY_Parse_Pro::get_comment_count( $this->youtube_api_data ) );
87
+ update_post_meta( $post_id, $prefix . 'view_count', SBY_Parse_Pro::get_view_count( $this->youtube_api_data ) );
88
+ update_post_meta( $post_id, $prefix . 'like_count', SBY_Parse_Pro::get_like_count( $this->youtube_api_data ) );
89
+ update_post_meta( $post_id, $prefix . 'scheduled_start_time', date( 'Y-m-d H:i:s', SBY_Parse_Pro::get_scheduled_start_timestamp( $this->youtube_api_data ) ) );
90
+ update_post_meta( $post_id, $prefix . 'actual_start_time', date( 'Y-m-d H:i:s', SBY_Parse_Pro::get_actual_start_timestamp( $this->youtube_api_data ) ) );
91
+ update_post_meta( $post_id, $prefix . 'actual_end_time', date( 'Y-m-d H:i:s', SBY_Parse_Pro::get_actual_end_timestamp( $this->youtube_api_data ) ) );
92
+ }
93
+
94
+ update_post_meta( $post_id, $prefix . 'last_details_check_time', date( 'Y-m-d H:i:s' ) );
95
+ $description = SBY_Parse::get_caption( $this->youtube_api_data );
96
+ if ( ! empty( $description ) ) {
97
+ update_post_meta( $post_id, $prefix . 'description', $description );
98
+ if ( $this->post_content_description_is_incomplete() ) {
99
+ $this->update_content();
100
+ }
101
+ }
102
+ return true;
103
+ }
104
+
105
+ return false;
106
+ }
107
+ public function update_content() {
108
+ $my_post = array();
109
+ $my_post['ID'] = $this->get_wp_post_id();
110
+ $my_post['post_content'] = $this->get_post_content( true );
111
+
112
+ wp_update_post( $my_post );
113
+ }
114
+
115
+ public static function maybe_get_channel_id_for_name( $name ) {
116
+
117
+ }
118
+
119
+ public static function maybe_get_channel_id_for_channel_title( $title ) {
120
+ global $wpdb;
121
+
122
+ $channel_id = $wpdb->get_col( $wpdb->prepare( "
123
+ SELECT Max(CASE
124
+ WHEN m.meta_key = 'sby_channel_id' THEN m.meta_value
125
+ ELSE NULL
126
+ END) AS sby_channel_id
127
+ FROM $wpdb->postmeta as m
128
+ WHERE m.post_id IN (SELECT m2.post_id FROM $wpdb->postmeta as m2 WHERE m2.meta_key = 'sby_channel_title' AND m2.meta_value = %s )
129
+ GROUP BY m.post_id
130
+ LIMIT 1", $title ) );
131
+
132
+ if ( isset( $channel_id[0] ) ) {
133
+ return $channel_id[0];
134
+ }
135
+ return false;
136
+ }
137
+
138
+ public function get_wp_post_id() {
139
+ if ( isset( $this->wp_post_id ) ) {
140
+ return $this->wp_post_id;
141
+ }
142
+
143
+ $video_id = SBY_Parse::get_video_id( $this->youtube_api_data );
144
+
145
+ global $wpdb;
146
+ $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_key FROM $wpdb->postmeta WHERE meta_value = %s AND meta_key = %s", $video_id, 'sby_video_id' ), ARRAY_A );
147
+
148
+ if ( isset( $results[0] ) ) {
149
+ $this->wp_post_id = $results[0]['post_id'];
150
+
151
+ return $results[0]['post_id'];
152
+ } else {
153
+ return false;
154
+ }
155
+ }
156
+
157
+ protected function get_post_content( $override = false ) {
158
+ $description = SBY_Parse::get_caption( $this->youtube_api_data );
159
+ $flag = '';
160
+ if ( ! $override && substr( $description, -3 ) === '...' ) {
161
+ $flag = '<!-- sby:description-incomplete -->';
162
+ }
163
+
164
+ return '['.SBY_SLUG.'-single]<!-- sby:description-start -->' . wp_kses_post( $description ) . '<!-- sby:description-end -->' . $flag;
165
+ }
166
  }
inc/sby-functions.php CHANGED
@@ -1,946 +1,946 @@
1
- <?php
2
-
3
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
-
5
- add_shortcode('youtube-feed', 'sby_youtube_feed');
6
- function sby_youtube_feed( $atts = array() ) {
7
- $database_settings = sby_get_database_settings();
8
- if ( !$database_settings['ajaxtheme'] ) {
9
- wp_enqueue_script( 'sby_scripts' );
10
- }
11
-
12
- if ( $database_settings['enqueue_css_in_shortcode'] ) {
13
- wp_enqueue_style( 'sby_styles' );
14
- }
15
-
16
- $youtube_feed_settings = new SBY_Settings( $atts, $database_settings );
17
- $youtube_feed_settings->set_feed_type_and_terms();
18
- $youtube_feed_settings->set_transient_name();
19
- $transient_name = $youtube_feed_settings->get_transient_name();
20
- $settings = $youtube_feed_settings->get_settings();
21
- $feed_type_and_terms = $youtube_feed_settings->get_feed_type_and_terms();
22
-
23
- if ( empty( $database_settings['connected_accounts'] )
24
- && empty( $database_settings['api_key'] )
25
- && ! isset( $feed_type_and_terms['channels'][0]['channel_id'] ) ) {
26
- $style = current_user_can( 'manage_youtube_feed_options' ) ? ' style="display: block;"' : '';
27
- ob_start(); ?>
28
- <div id="sbi_mod_error" <?php echo $style; ?>>
29
- <span><?php _e('This error message is only visible to WordPress admins', 'feeds-for-youtube' ); ?></span><br />
30
- <p><b><?php _e( 'Error: No connected account or API key.', 'feeds-for-youtube' ); ?></b>
31
- <p><?php _e( 'Please go to the YouTube Feed settings page to enter an API key or connect an account.', 'youtube-feed' ); ?></p>
32
- </div>
33
- <?php
34
- $html = ob_get_contents();
35
- ob_get_clean();
36
- return $html;
37
- }
38
-
39
- $youtube_feed = new SBY_Feed( $transient_name );
40
-
41
- if ( $database_settings['caching_type'] === 'background' ) {
42
- $youtube_feed->add_report( 'background caching used' );
43
- if ( $youtube_feed->regular_cache_exists() ) {
44
- $youtube_feed->add_report( 'setting posts from cache' );
45
- $youtube_feed->set_post_data_from_cache();
46
- }
47
-
48
- if ( $youtube_feed->need_to_start_cron_job() ) {
49
- $youtube_feed->add_report( 'setting up feed for cron cache' );
50
- $to_cache = array(
51
- 'atts' => $atts,
52
- 'last_requested' => time(),
53
- );
54
-
55
- $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
56
-
57
- SBY_Cron_Updater::do_single_feed_cron_update( $youtube_feed_settings, $to_cache, $atts, false );
58
-
59
- $youtube_feed->set_post_data_from_cache();
60
-
61
- } elseif ( $youtube_feed->should_update_last_requested() ) {
62
- $youtube_feed->add_report( 'updating last requested' );
63
- $to_cache = array(
64
- 'last_requested' => time(),
65
- );
66
-
67
- $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
68
- }
69
-
70
- } elseif ( $youtube_feed->regular_cache_exists() ) {
71
- $youtube_feed->add_report( 'page load caching used and regular cache exists' );
72
- $youtube_feed->set_post_data_from_cache();
73
-
74
- if ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
75
- while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
76
- $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
77
- }
78
- $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds() );
79
- }
80
-
81
- } else {
82
- $youtube_feed->add_report( 'no feed cache found' );
83
-
84
- while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
85
- $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
86
- }
87
-
88
- if ( ! $youtube_feed->should_use_backup() ) {
89
- $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds() );
90
- }
91
-
92
- }
93
-
94
- if ( $youtube_feed->should_use_backup() ) {
95
- $youtube_feed->add_report( 'trying to use backup' );
96
- $youtube_feed->maybe_set_post_data_from_backup();
97
- $youtube_feed->maybe_set_header_data_from_backup();
98
- }
99
-
100
- // if need a header
101
- if ( $youtube_feed->need_header( $settings, $feed_type_and_terms ) && ! $youtube_feed->should_use_backup() ) {
102
- if ( $database_settings['caching_type'] === 'background' ) {
103
- $youtube_feed->add_report( 'background header caching used' );
104
- $youtube_feed->set_header_data_from_cache();
105
- } elseif ( $youtube_feed->regular_header_cache_exists() ) {
106
- // set_post_data_from_cache
107
- $youtube_feed->add_report( 'page load caching used and regular header cache exists' );
108
- $youtube_feed->set_header_data_from_cache();
109
- } else {
110
- $youtube_feed->add_report( 'no header cache exists' );
111
- $youtube_feed->set_remote_header_data( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
112
-
113
- $youtube_feed->cache_header_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
114
- }
115
- } else {
116
- $youtube_feed->add_report( 'no header needed' );
117
- }
118
-
119
- return $youtube_feed->get_the_feed_html( $settings, $atts, $youtube_feed_settings->get_feed_type_and_terms(), $youtube_feed_settings->get_connected_accounts_in_feed() );
120
- }
121
-
122
- /**
123
- * Outputs an organized error report for the front end.
124
- * This hooks into the end of the feed before the closing div
125
- *
126
- * @param object $youtube_feed
127
- * @param string $feed_id
128
- */
129
- function sby_error_report( $youtube_feed, $feed_id ) {
130
- global $sby_posts_manager;
131
-
132
- $style = current_user_can( 'manage_youtube_feed_options' ) ? ' style="display: block;"' : '';
133
-
134
- $error_messages = $sby_posts_manager->get_frontend_errors();
135
- if ( ! empty( $error_messages ) ) {?>
136
- <div id="sby_mod_error"<?php echo $style; ?>>
137
- <span><?php _e('This error message is only visible to WordPress admins', SBY_TEXT_DOMAIN ); ?></span><br />
138
- <?php foreach ( $error_messages as $error_message ) {
139
- echo $error_message;
140
- } ?>
141
- </div>
142
- <?php
143
- }
144
-
145
- $sby_posts_manager->reset_frontend_errors();
146
- }
147
- add_action( 'sby_before_feed_end', 'sby_error_report', 10, 2 );
148
-
149
- /**
150
- * Called after the load more button is clicked using admin-ajax.php
151
- */
152
- function sby_get_next_post_set() {
153
- if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sby' ) === false ) {
154
- die( 'invalid feed ID');
155
- }
156
-
157
- $feed_id = sanitize_text_field( $_POST['feed_id'] );
158
- $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
159
- if ( is_array( $atts_raw ) ) {
160
- array_map( 'sanitize_text_field', $atts_raw );
161
- } else {
162
- $atts_raw = array();
163
- }
164
- $atts = $atts_raw; // now sanitized
165
-
166
- $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
167
-
168
- $database_settings = sby_get_database_settings();
169
- $youtube_feed_settings = new SBY_Settings( $atts, $database_settings );
170
-
171
- if ( empty( $database_settings['connected_accounts'] ) && empty( $database_settings['api_key'] ) ) {
172
- die( 'error no connected account' );
173
- }
174
-
175
- $youtube_feed_settings->set_feed_type_and_terms();
176
- $youtube_feed_settings->set_transient_name( $feed_id );
177
- $transient_name = $youtube_feed_settings->get_transient_name();
178
-
179
- $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
180
- $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
181
- $feed_details = array(
182
- 'feed_id' => $feed_id,
183
- 'atts' => $atts,
184
- 'location' => array(
185
- 'post_id' => $post_id,
186
- 'html' => $location
187
- )
188
- );
189
-
190
- sby_do_background_tasks( $feed_details );
191
-
192
- if ( $transient_name !== $feed_id ) {
193
- die( 'id does not match' );
194
- }
195
-
196
- $settings = $youtube_feed_settings->get_settings();
197
-
198
- $feed_type_and_terms = $youtube_feed_settings->get_feed_type_and_terms();
199
-
200
- $youtube_feed = new SBY_Feed( $transient_name );
201
-
202
- if ( $settings['caching_type'] === 'permanent' && empty( $settings['doingModerationMode'] ) ) {
203
- $youtube_feed->add_report( 'trying to use permanent cache' );
204
- $youtube_feed->maybe_set_post_data_from_backup();
205
- } elseif ( $settings['caching_type'] === 'background' ) {
206
- $youtube_feed->add_report( 'background caching used' );
207
- if ( $youtube_feed->regular_cache_exists() ) {
208
- $youtube_feed->add_report( 'setting posts from cache' );
209
- $youtube_feed->set_post_data_from_cache();
210
- }
211
-
212
- if ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
213
- while ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
214
- $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
215
- }
216
-
217
- if ( $youtube_feed->need_to_start_cron_job() ) {
218
- $youtube_feed->add_report( 'needed to start cron job' );
219
- $to_cache = array(
220
- 'atts' => $atts,
221
- 'last_requested' => time(),
222
- );
223
-
224
- $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
225
-
226
- } else {
227
- $youtube_feed->add_report( 'updating last requested and adding to cache' );
228
- $to_cache = array(
229
- 'last_requested' => time(),
230
- );
231
-
232
- $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
233
- }
234
- }
235
-
236
- } elseif ( $youtube_feed->regular_cache_exists() ) {
237
- $youtube_feed->add_report( 'regular cache exists' );
238
- $youtube_feed->set_post_data_from_cache();
239
-
240
- if ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
241
- while ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
242
- $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
243
- }
244
-
245
- $youtube_feed->add_report( 'adding to cache' );
246
- $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
247
- }
248
-
249
-
250
- } else {
251
- $youtube_feed->add_report( 'no feed cache found' );
252
-
253
- while ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
254
- $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
255
- }
256
-
257
- if ( $youtube_feed->should_use_backup() ) {
258
- $youtube_feed->add_report( 'trying to use a backup cache' );
259
- $youtube_feed->maybe_set_post_data_from_backup();
260
- } else {
261
- $youtube_feed->add_report( 'transient gone, adding to cache' );
262
- $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
263
- }
264
- }
265
-
266
- $feed_status = array( 'shouldPaginate' => $youtube_feed->should_use_pagination( $settings, $offset ), );
267
-
268
- $feed_status['cacheAll'] = $youtube_feed->do_page_cache_all();
269
-
270
- $post_data = $youtube_feed->get_post_data();
271
-
272
- if ( $youtube_feed->successful_video_api_request_made() && ! empty( $post_data ) ) {
273
- if ( $settings['storage_process'] === 'page' ) {
274
- foreach ( $youtube_feed->get_post_data() as $post ) {
275
- $wp_post = new SBY_WP_Post( $post, $this->regular_feed_transient_name );
276
- $wp_post->update_post();
277
- }
278
- } elseif ( $settings['storage_process'] === 'background' ) {
279
- $feed_status['checkWPPosts'] = true;
280
- $feed_status['cacheAll'] = true;
281
- }
282
- }
283
-
284
- /*if ( $settings['disable_js_image_loading'] || $settings['imageres'] !== 'auto' ) {
285
- global $sby_posts_manager;
286
- $post_data = array_slice( $youtube_feed->get_post_data(), $offset, $settings['minnum'] );
287
-
288
- if ( ! $sby_posts_manager->image_resizing_disabled() ) {
289
- $image_ids = array();
290
- foreach ( $post_data as $post ) {
291
- $image_ids[] = SBY_Parse::get_post_id( $post );
292
- }
293
- $resized_images = SBY_Feed::get_resized_images_source_set( $image_ids, 0, $feed_id );
294
-
295
- $youtube_feed->set_resized_images( $resized_images );
296
- }
297
- }*/
298
-
299
- $return = array(
300
- 'html' => $youtube_feed->get_the_items_html( $settings, $offset, $youtube_feed_settings->get_feed_type_and_terms(), $youtube_feed_settings->get_connected_accounts_in_feed() ),
301
- 'feedStatus' => $feed_status,
302
- 'report' => $youtube_feed->get_report(),
303
- 'resizedImages' => array()
304
- //'resizedImages' => SBY_Feed::get_resized_images_source_set( $youtube_feed->get_image_ids_post_set(), 0, $feed_id )
305
- );
306
-
307
- //SBY_Feed::update_last_requested( $youtube_feed->get_image_ids_post_set() );
308
-
309
- echo wp_json_encode( $return );
310
-
311
- global $sby_posts_manager;
312
-
313
- $sby_posts_manager->update_successful_ajax_test();
314
-
315
- die();
316
- }
317
- add_action( 'wp_ajax_sby_load_more_clicked', 'sby_get_next_post_set' );
318
- add_action( 'wp_ajax_nopriv_sby_load_more_clicked', 'sby_get_next_post_set' );
319
-
320
- /**
321
- * Posts that need resized images are processed after being sent to the server
322
- * using AJAX
323
- *
324
- * @return string
325
- */
326
- function sby_process_wp_posts() {
327
- if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sby' ) === false ) {
328
- die( 'invalid feed ID');
329
- }
330
-
331
- $feed_id = sanitize_text_field( $_POST['feed_id'] );
332
-
333
- $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
334
- if ( is_array( $atts_raw ) ) {
335
- array_map( 'sanitize_text_field', $atts_raw );
336
- } else {
337
- $atts_raw = array();
338
- }
339
- $atts = $atts_raw; // now sanitized
340
-
341
- $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
342
- $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
343
- $feed_details = array(
344
- 'feed_id' => $feed_id,
345
- 'atts' => $atts,
346
- 'location' => array(
347
- 'post_id' => $post_id,
348
- 'html' => $location
349
- )
350
- );
351
-
352
- sby_do_background_tasks( $feed_details );
353
-
354
- $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
355
-
356
- $cache_all = isset( $_POST['cache_all'] ) ? $_POST['cache_all'] === 'true' : false;
357
-
358
- if ( $cache_all ) {
359
- $database_settings = sby_get_database_settings();
360
- $youtube_feed_settings = new SBY_Settings( $atts, $database_settings );
361
- $youtube_feed_settings->set_feed_type_and_terms();
362
- $youtube_feed_settings->set_transient_name( $feed_id );
363
- $transient_name = $youtube_feed_settings->get_transient_name();
364
-
365
- $feed_id = $transient_name;
366
- }
367
-
368
- $database_settings = sby_get_database_settings();
369
- $sby_settings = new SBY_Settings( $atts, $database_settings );
370
-
371
- $settings = $sby_settings->get_settings();
372
-
373
- $youtube_feed = new SBY_Feed( $feed_id );
374
- if ( $youtube_feed->regular_cache_exists() ) {
375
- $youtube_feed->set_post_data_from_cache();
376
-
377
- if ( !$cache_all ) {
378
- $posts = array_slice( $youtube_feed->get_post_data(), max( 0, $offset - $settings['minnum'] ), $settings['minnum'] );
379
- } else {
380
- $posts = $youtube_feed->get_post_data();
381
- }
382
-
383
- foreach ( $posts as $post ) {
384
- $wp_post = new SBY_WP_Post( $post, $feed_id );
385
- $wp_post->update_post();
386
- }
387
- }
388
-
389
-
390
-
391
- //global $sby_posts_manager;
392
-
393
- //$sby_posts_manager->update_successful_ajax_test();
394
- if ( $cache_all ) {
395
- die( 'cache all' );
396
- }
397
- die( 'check success' );
398
- }
399
- add_action( 'wp_ajax_sby_check_wp_submit', 'sby_process_wp_posts' );
400
- add_action( 'wp_ajax_nopriv_sby_check_wp_submit', 'sby_process_wp_posts' );
401
-
402
- function sby_process_post_set_caching( $posts, $feed_id ) {
403
-
404
- // if is an array of video ids already, don't need to get them
405
- if ( isset( $posts[0] ) && SBY_Parse::get_video_id( $posts[0] ) === '' ) {
406
- $vid_ids = $posts;
407
- } else {
408
- $vid_ids = array();
409
- foreach ( $posts as $post ) {
410
- $vid_ids[] = SBY_Parse::get_video_id( $post );
411
- $wp_post = new SBY_WP_Post( $post, $feed_id );
412
- $sby_video_settings = SBY_CPT::get_sby_cpt_settings();
413
- $wp_post->update_post( $sby_video_settings['post_status'] );
414
- }
415
- }
416
-
417
- return array();
418
- }
419
-
420
- function sby_do_locator() {
421
- if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sbi' ) === false ) {
422
- die( 'invalid feed ID');
423
- }
424
-
425
- $feed_id = sanitize_text_field( $_POST['feed_id'] );
426
-
427
- $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
428
- if ( is_array( $atts_raw ) ) {
429
- array_map( 'sanitize_text_field', $atts_raw );
430
- } else {
431
- $atts_raw = array();
432
- }
433
- $atts = $atts_raw; // now sanitized
434
-
435
- $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
436
- $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
437
- $feed_details = array(
438
- 'feed_id' => $feed_id,
439
- 'atts' => $atts,
440
- 'location' => array(
441
- 'post_id' => $post_id,
442
- 'html' => $location
443
- )
444
- );
445
-
446
- sby_do_background_tasks( $feed_details );
447
-
448
- wp_die( 'locating success' );
449
- }
450
- add_action( 'wp_ajax_sby_do_locator', 'sby_do_locator' );
451
- add_action( 'wp_ajax_nopriv_sby_do_locator', 'sby_do_locator' );
452
-
453
- function sby_do_background_tasks( $feed_details ) {
454
- $locator = new SBY_Feed_Locator( $feed_details );
455
- $locator->add_or_update_entry();
456
- if ( $locator->should_clear_old_locations() ) {
457
- $locator->delete_old_locations();
458
- }
459
- }
460
-
461
- function sby_debug_report( $youtube_feed, $feed_id ) {
462
-
463
- if ( ! isset( $_GET['sby_debug'] ) ) {
464
- return;
465
- }
466
-
467
- ?>
468
- <p>Status</p>
469
- <ul>
470
- <li>Time: <?php echo date( "Y-m-d H:i:s", time() ); ?></li>
471
- <?php foreach ( $youtube_feed->get_report() as $item ) : ?>
472
- <li><?php echo esc_html( $item ); ?></li>
473
- <?php endforeach; ?>
474
-
475
- </ul>
476
-
477
- <?php
478
- $database_settings = sby_get_database_settings();
479
-
480
- $public_settings_keys = SBY_Settings::get_public_db_settings_keys();
481
- ?>
482
- <p>Settings</p>
483
- <ul>
484
- <?php foreach ( $public_settings_keys as $key ) : if ( isset( $database_settings[ $key ] ) ) : ?>
485
- <li>
486
- <small><?php echo esc_html( $key ); ?>:</small>
487
- <?php if ( ! is_array( $database_settings[ $key ] ) ) :
488
- echo $database_settings[ $key ];
489
- else : ?>
490
- <pre>
491
- <?php var_export( $database_settings[ $key ] ); ?>
492
- </pre>
493
- <?php endif; ?>
494
- </li>
495
-
496
- <?php endif; endforeach; ?>
497
- </ul>
498
- <?php
499
- }
500
- add_action( 'sby_before_feed_end', 'sby_debug_report', 11, 2 );
501
-
502
- function sby_clear_cache() {
503
- //Delete all transients
504
- global $wpdb;
505
- $table_name = $wpdb->prefix . "options";
506
- $wpdb->query( "
507
- DELETE
508
- FROM $table_name
509
- WHERE `option_name` LIKE ('%\_transient\_sby\_%')
510
- " );
511
- $wpdb->query( "
512
- DELETE
513
- FROM $table_name
514
- WHERE `option_name` LIKE ('%\_transient\_timeout\_sby\_%')
515
- " );
516
- $wpdb->query( "
517
- DELETE
518
- FROM $table_name
519
- WHERE `option_name` LIKE ('%\_transient\_&sby\_%')
520
- " );
521
- $wpdb->query( "
522
- DELETE
523
- FROM $table_name
524
- WHERE `option_name` LIKE ('%\_transient\_timeout\_&sby\_%')
525
- " );
526
- $wpdb->query( "
527
- DELETE
528
- FROM $table_name
529
- WHERE `option_name` LIKE ('%\_transient\_\$sby\_%')
530
- " );
531
- $wpdb->query( "
532
- DELETE
533
- FROM $table_name
534
- WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sby\_%')
535
- " );
536
-
537
- sby_clear_page_caches();
538
- }
539
- add_action( 'sby_settings_after_configure_save', 'sby_clear_cache' );
540
-
541
- function sby_maybe_clear_cache_using_cron() {
542
- global $sby_settings;
543
- $sby_doing_cron_clear = isset( $sby_settings['cronclear'] ) ? $sby_settings['cronclear'] : false;
544
-
545
- if ( $sby_doing_cron_clear ) {
546
- sby_clear_cache();
547
- }
548
- }
549
- add_action( 'sby_cron_job', 'sby_maybe_clear_cache_using_cron' );
550
-
551
- function sby_json_encode( $thing ) {
552
- if ( function_exists( 'wp_json_encode' ) ) {
553
- return wp_json_encode( $thing );
554
- } else {
555
- return json_encode( $thing );
556
- }
557
- }
558
-
559
- /**
560
- * When certain events occur, page caches need to
561
- * clear or errors occur or changes will not be seen
562
- */
563
- function sby_clear_page_caches() {
564
- if ( isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ){
565
- /* Clear WP fastest cache*/
566
- $GLOBALS['wp_fastest_cache']->deleteCache();
567
- }
568
-
569
- if ( function_exists( 'wp_cache_clear_cache' ) ) {
570
- wp_cache_clear_cache();
571
- }
572
-
573
- if ( class_exists('W3_Plugin_TotalCacheAdmin') ) {
574
- $plugin_totalcacheadmin = & w3_instance('W3_Plugin_TotalCacheAdmin');
575
-
576
- $plugin_totalcacheadmin->flush_all();
577
- }
578
-
579
- if ( function_exists( 'rocket_clean_domain' ) ) {
580
- rocket_clean_domain();
581
- }
582
-
583
- if ( class_exists( 'autoptimizeCache' ) ) {
584
- /* Clear autoptimize */
585
- autoptimizeCache::clearall();
586
- }
587
- }
588
-
589
- /**
590
- * Triggered by a cron event to update feeds
591
- */
592
- function sby_cron_updater() {
593
- global $sby_settings;
594
-
595
- if ( $sby_settings['caching_type'] === 'background' ) {
596
- SBY_Cron_Updater::do_feed_updates();
597
- }
598
-
599
- }
600
- add_action( 'sby_feed_update', 'sby_cron_updater' );
601
-
602
- function sby_update_or_connect_account( $args ) {
603
- global $sby_settings;
604
- $account_id = $args['channel_id'];
605
- $sby_settings['connected_accounts'][ $account_id ] = array(
606
- 'access_token' => $args['access_token'],
607
- 'refresh_token' => $args['refresh_token'],
608
- 'channel_id' => $args['channel_id'],
609
- 'username' => $args['username'],
610
- 'is_valid' => true,
611
- 'last_checked' => time(),
612
- 'profile_picture' => $args['profile_picture'],
613
- 'privacy' => $args['privacy'],
614
- 'expires' => $args['expires']
615
- );
616
-
617
- update_option( 'sby_settings', $sby_settings );
618
-
619
- return $sby_settings['connected_accounts'][ $account_id ];
620
- }
621
-
622
- function sby_get_first_connected_account() {
623
- global $sby_settings;
624
- $an_account = array();
625
-
626
- if ( ! empty( $sby_settings['api_key'] ) ) {
627
- $an_account = array(
628
- 'access_token' => '',
629
- 'refresh_token' => '',
630
- 'channel_id' => '',
631
- 'username' => '',
632
- 'is_valid' => true,
633
- 'last_checked' => '',
634
- 'profile_picture' => '',
635
- 'privacy' => '',
636
- 'expires' => '2574196927',
637
- 'api_key' => $sby_settings['api_key']
638
- );
639
- } else {
640
- $connected_accounts = $sby_settings['connected_accounts'];
641
- foreach ( $connected_accounts as $account ) {
642
- if ( empty( $an_account ) ) {
643
- $an_account = $account;
644
- }
645
- }
646
- }
647
-
648
- if ( empty( $an_account ) ) {
649
- $an_account = array( 'rss_only' => true );
650
- }
651
-
652
- return $an_account;
653
- }
654
-
655
- function sby_get_feed_template_part( $part, $settings = array() ) {
656
- $file = '';
657
-
658
- $using_custom_templates_in_theme = apply_filters( 'sby_use_theme_templates', $settings['customtemplates'] );
659
- $generic_path = trailingslashit( SBY_PLUGIN_DIR ) . 'templates/';
660
-
661
- if ( $using_custom_templates_in_theme ) {
662
- $custom_header_template = locate_template( 'sby/header.php', false, false );
663
- $custom_player_template = locate_template( 'sby/player.php', false, false );
664
- $custom_item_template = locate_template( 'sby/item.php', false, false );
665
- $custom_footer_template = locate_template( 'sby/footer.php', false, false );
666
- $custom_feed_template = locate_template( 'sby/feed.php', false, false );
667
- } else {
668
- $custom_header_template = false;
669
- $custom_player_template = false;
670
- $custom_item_template = false;
671
- $custom_footer_template = false;
672
- $custom_feed_template = false;
673
- }
674
-
675
- if ( $part === 'header' ) {
676
- if ( $custom_header_template ) {
677
- $file = $custom_header_template;
678
- } else {
679
- $file = $generic_path . 'header.php';
680
- }
681
- } elseif ( $part === 'player' ) {
682
- if ( $custom_player_template ) {
683
- $file = $custom_player_template;
684
- } else {
685
- $file = $generic_path . 'player.php';
686
- }
687
- } elseif ( $part === 'item' ) {
688
- if ( $custom_item_template ) {
689
- $file = $custom_item_template;
690
- } else {
691
- $file = $generic_path . 'item.php';
692
- }
693
- } elseif ( $part === 'footer' ) {
694
- if ( $custom_footer_template ) {
695
- $file = $custom_footer_template;
696
- } else {
697
- $file = $generic_path . 'footer.php';
698
- }
699
- } elseif ( $part === 'feed' ) {
700
- if ( $custom_feed_template ) {
701
- $file = $custom_feed_template;
702
- } else {
703
- $file = $generic_path . 'feed.php';
704
- }
705
- }
706
-
707
- return $file;
708
- }
709
-
710
- /**
711
- * Get the settings in the database with defaults
712
- *
713
- * @return array
714
- */
715
- function sby_get_database_settings() {
716
- global $sby_settings;
717
-
718
- $defaults = sby_settings_defaults();
719
-
720
- return array_merge( $defaults, $sby_settings );
721
- }
722
-
723
-
724
- function sby_get_channel_id_from_channel_name( $channel_name ) {
725
- $channel_ids = get_option( 'sby_channel_ids', array() );
726
-
727
- if ( isset( $channel_ids[ strtolower( $channel_name ) ] ) ) {
728
- return $channel_ids[ strtolower( $channel_name ) ];
729
- }
730
-
731
- return false;
732
- }
733
-
734
- function sby_set_channel_id_from_channel_name( $channel_name, $channel_id ) {
735
- $channel_ids = get_option( 'sby_channel_ids', array() );
736
-
737
- $channel_ids[ strtolower( $channel_name ) ] = $channel_id;
738
-
739
- update_option( 'sby_channel_ids', $channel_ids, false );
740
- }
741
-
742
- function sby_icon( $icon, $class = '' ) {
743
- $class = ! empty( $class ) ? ' ' . trim( $class ) : '';
744
- if ( $icon === SBY_SLUG ) {
745
- return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-youtube fa-w-18'.$class.'"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
746
- } else {
747
- return '<i aria-hidden="true" role="img" class="fab fa-youtube"></i>';
748
- }
749
- }
750
-
751
-
752
- /**
753
- * @param $a
754
- * @param $b
755
- *
756
- * @return false|int
757
- */
758
- function sby_date_sort( $a, $b ) {
759
- $time_stamp_a = SBY_Parse::get_timestamp( $a );
760
- $time_stamp_b = SBY_Parse::get_timestamp( $b );
761
-
762
- if ( isset( $time_stamp_a ) ) {
763
- return $time_stamp_b - $time_stamp_a;
764
- } else {
765
- return rand ( -1, 1 );
766
- }
767
- }
768
-
769
- /**
770
- * @param $a
771
- * @param $b
772
- *
773
- * @return false|int
774
- */
775
- function sby_rand_sort( $a, $b ) {
776
- return rand ( -1, 1 );
777
- }
778
-
779
- /**
780
- * Converts a hex code to RGB so opacity can be
781
- * applied more easily
782
- *
783
- * @param $hex
784
- *
785
- * @return string
786
- */
787
- function sby_hextorgb( $hex ) {
788
- // allows someone to use rgb in shortcode
789
- if ( strpos( $hex, ',' ) !== false ) {
790
- return $hex;
791
- }
792
-
793
- $hex = str_replace( '#', '', $hex );
794
-
795
- if ( strlen( $hex ) === 3 ) {
796
- $r = hexdec( substr( $hex,0,1 ).substr( $hex,0,1 ) );
797
- $g = hexdec( substr( $hex,1,1 ).substr( $hex,1,1 ) );
798
- $b = hexdec( substr( $hex,2,1 ).substr( $hex,2,1 ) );
799
- } else {
800
- $r = hexdec( substr( $hex,0,2 ) );
801
- $g = hexdec( substr( $hex,2,2 ) );
802
- $b = hexdec( substr( $hex,4,2 ) );
803
- }
804
- $rgb = array( $r, $g, $b );
805
-
806
- return implode( ',', $rgb ); // returns the rgb values separated by commas
807
- }
808
-
809
- function sby_get_utc_offset() {
810
- return get_option( 'gmt_offset', 0 ) * HOUR_IN_SECONDS;
811
- }
812
-
813
- function sby_is_pro_version() {
814
- return defined( 'SBY_PLUGIN_EDD_NAME' );
815
- }
816
-
817
- function sby_strip_after_hash( $string ) {
818
- $string_array = explode( '#', $string );
819
- $finished_string = $string_array[0];
820
-
821
- return $finished_string;
822
- }
823
-
824
- function sby_get_account_bottom() {
825
- return '';
826
- }
827
-
828
- function sby_get_account_top() {
829
- return '';
830
- }
831
-
832
- function sby_replace_double_quotes( &$element, $index ) {
833
- $element = str_replace( '"', "&quot;", $element );
834
- }
835
-
836
- function sby_esc_attr_with_br( $text ) {
837
- return str_replace( array( '&lt;br /&gt;', '&lt;br&gt;' ), '&lt;br /&gt;', esc_attr( nl2br( $text ) ) );
838
- }
839
- /**
840
- * Adds the ajax url and custom JavaScript to the page
841
- */
842
- function sby_custom_js() {
843
- global $sby_settings;
844
-
845
- $js = isset( $sby_settings['custom_js'] ) ? trim( $sby_settings['custom_js'] ) : '';
846
-
847
- echo '<!-- YouTube Feed JS -->';
848
- echo "\r\n";
849
- echo '<script type="text/javascript">';
850
- echo "\r\n";
851
-
852
- if ( ! empty( $js ) ) {
853
- echo "\r\n";
854
- echo "jQuery( document ).ready(function($) {";
855
- echo "\r\n";
856
- echo "window.sbyCustomJS = function(){";
857
- echo "\r\n";
858
- echo stripslashes($js);
859
- echo "\r\n";
860
- echo "}";
861
- echo "\r\n";
862
- echo "});";
863
- }
864
-
865
- echo "\r\n";
866
- echo '</script>';
867
- echo "\r\n";
868
- }
869
- add_action( 'wp_footer', 'sby_custom_js' );
870
-
871
- //Custom CSS
872
- add_action( 'wp_head', 'sby_custom_css' );
873
- function sby_custom_css() {
874
- global $sby_settings;
875
-
876
- $css = isset( $sby_settings['custom_css'] ) ? trim( $sby_settings['custom_css'] ) : '';
877
-
878
- //Show CSS if an admin (so can see Hide Photos link), if including Custom CSS or if hiding some photos
879
- if ( current_user_can( 'manage_youtube_feed_options' ) || current_user_can( 'manage_options' ) || ! empty( $css ) ) {
880
-
881
- echo '<!-- Instagram Feed CSS -->';
882
- echo "\r\n";
883
- echo '<style type="text/css">';
884
-
885
- if ( ! empty( $css ) ){
886
- echo "\r\n";
887
- echo stripslashes($css);
888
- }
889
-
890
- if ( current_user_can( 'manage_youtube_feed_options' ) || current_user_can( 'manage_options' ) ){
891
- echo "\r\n";
892
- echo "#sby_mod_link, #sby_mod_error{ display: block !important; width: 100%; float: left; box-sizing: border-box; }";
893
- }
894
-
895
- echo "\r\n";
896
- echo '</style>';
897
- echo "\r\n";
898
- }
899
-
900
- }
901
-
902
- /**
903
- * Makes the JavaScript file available and enqueues the stylesheet
904
- * for the plugin
905
- */
906
- function sby_scripts_enqueue( $enqueue = false ) {
907
- //Register the script to make it available
908
-
909
- //Options to pass to JS file
910
- global $sby_settings;
911
-
912
- $js_file = 'js/sb-youtube.min.js';
913
- if ( isset( $_GET['sby_debug'] ) ) {
914
- $js_file = 'js/sb-youtube.js';
915
- }
916
-
917
- if ( isset( $sby_settings['enqueue_js_in_head'] ) && $sby_settings['enqueue_js_in_head'] ) {
918
- wp_enqueue_script( 'sby_scripts', trailingslashit( SBY_PLUGIN_URL ) . $js_file, array('jquery'), SBYVER, false );
919
- } else {
920
- wp_register_script( 'sby_scripts', trailingslashit( SBY_PLUGIN_URL ) . $js_file, array('jquery'), SBYVER, true );
921
- }
922
-
923
- if ( isset( $sby_settings['enqueue_css_in_shortcode'] ) && $sby_settings['enqueue_css_in_shortcode'] ) {
924
- wp_register_style( 'sby_styles', trailingslashit( SBY_PLUGIN_URL ) . 'css/sb-youtube.min.css', array(), SBYVER );
925
- } else {
926
- wp_enqueue_style( 'sby_styles', trailingslashit( SBY_PLUGIN_URL ) . 'css/sb-youtube.min.css', array(), SBYVER );
927
- }
928
- $data = array(
929
- 'adminAjaxUrl' => admin_url( 'admin-ajax.php' ),
930
- 'placeholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png',
931
- 'placeholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder-narrow.png',
932
- 'lightboxPlaceholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder.png',
933
- 'lightboxPlaceholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder-narrow.png',
934
- 'autoplay' => $sby_settings['playvideo'] === 'automatically',
935
- 'semiEagerload' => false,
936
- 'eagerload' => $sby_settings['eagerload']
937
- );
938
- //Pass option to JS file
939
- wp_localize_script('sby_scripts', 'sbyOptions', $data );
940
-
941
- if ( $enqueue ) {
942
- wp_enqueue_style( 'sby_styles' );
943
- wp_enqueue_script( 'sby_scripts' );
944
- }
945
- }
946
  add_action( 'wp_enqueue_scripts', 'sby_scripts_enqueue', 2 );
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ add_shortcode('youtube-feed', 'sby_youtube_feed');
6
+ function sby_youtube_feed( $atts = array() ) {
7
+ $database_settings = sby_get_database_settings();
8
+ if ( !$database_settings['ajaxtheme'] ) {
9
+ wp_enqueue_script( 'sby_scripts' );
10
+ }
11
+
12
+ if ( $database_settings['enqueue_css_in_shortcode'] ) {
13
+ wp_enqueue_style( 'sby_styles' );
14
+ }
15
+
16
+ $youtube_feed_settings = new SBY_Settings( $atts, $database_settings );
17
+ $youtube_feed_settings->set_feed_type_and_terms();
18
+ $youtube_feed_settings->set_transient_name();
19
+ $transient_name = $youtube_feed_settings->get_transient_name();
20
+ $settings = $youtube_feed_settings->get_settings();
21
+ $feed_type_and_terms = $youtube_feed_settings->get_feed_type_and_terms();
22
+
23
+ if ( empty( $database_settings['connected_accounts'] )
24
+ && empty( $database_settings['api_key'] )
25
+ && ! isset( $feed_type_and_terms['channels'][0]['channel_id'] ) ) {
26
+ $style = current_user_can( 'manage_youtube_feed_options' ) ? ' style="display: block;"' : '';
27
+ ob_start(); ?>
28
+ <div id="sbi_mod_error" <?php echo $style; ?>>
29
+ <span><?php _e('This error message is only visible to WordPress admins', 'feeds-for-youtube' ); ?></span><br />
30
+ <p><b><?php _e( 'Error: No connected account or API key.', 'feeds-for-youtube' ); ?></b>
31
+ <p><?php _e( 'Please go to the YouTube Feed settings page to enter an API key or connect an account.', 'youtube-feed' ); ?></p>
32
+ </div>
33
+ <?php
34
+ $html = ob_get_contents();
35
+ ob_get_clean();
36
+ return $html;
37
+ }
38
+
39
+ $youtube_feed = new SBY_Feed( $transient_name );
40
+
41
+ if ( $database_settings['caching_type'] === 'background' ) {
42
+ $youtube_feed->add_report( 'background caching used' );
43
+ if ( $youtube_feed->regular_cache_exists() ) {
44
+ $youtube_feed->add_report( 'setting posts from cache' );
45
+ $youtube_feed->set_post_data_from_cache();
46
+ }
47
+
48
+ if ( $youtube_feed->need_to_start_cron_job() ) {
49
+ $youtube_feed->add_report( 'setting up feed for cron cache' );
50
+ $to_cache = array(
51
+ 'atts' => $atts,
52
+ 'last_requested' => time(),
53
+ );
54
+
55
+ $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
56
+
57
+ SBY_Cron_Updater::do_single_feed_cron_update( $youtube_feed_settings, $to_cache, $atts, false );
58
+
59
+ $youtube_feed->set_post_data_from_cache();
60
+
61
+ } elseif ( $youtube_feed->should_update_last_requested() ) {
62
+ $youtube_feed->add_report( 'updating last requested' );
63
+ $to_cache = array(
64
+ 'last_requested' => time(),
65
+ );
66
+
67
+ $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
68
+ }
69
+
70
+ } elseif ( $youtube_feed->regular_cache_exists() ) {
71
+ $youtube_feed->add_report( 'page load caching used and regular cache exists' );
72
+ $youtube_feed->set_post_data_from_cache();
73
+
74
+ if ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
75
+ while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
76
+ $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
77
+ }
78
+ $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds() );
79
+ }
80
+
81
+ } else {
82
+ $youtube_feed->add_report( 'no feed cache found' );
83
+
84
+ while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
85
+ $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
86
+ }
87
+
88
+ if ( ! $youtube_feed->should_use_backup() ) {
89
+ $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds() );
90
+ }
91
+
92
+ }
93
+
94
+ if ( $youtube_feed->should_use_backup() ) {
95
+ $youtube_feed->add_report( 'trying to use backup' );
96
+ $youtube_feed->maybe_set_post_data_from_backup();
97
+ $youtube_feed->maybe_set_header_data_from_backup();
98
+ }
99
+
100
+ // if need a header
101
+ if ( $youtube_feed->need_header( $settings, $feed_type_and_terms ) && ! $youtube_feed->should_use_backup() ) {
102
+ if ( $database_settings['caching_type'] === 'background' ) {
103
+ $youtube_feed->add_report( 'background header caching used' );
104
+ $youtube_feed->set_header_data_from_cache();
105
+ } elseif ( $youtube_feed->regular_header_cache_exists() ) {
106
+ // set_post_data_from_cache
107
+ $youtube_feed->add_report( 'page load caching used and regular header cache exists' );
108
+ $youtube_feed->set_header_data_from_cache();
109
+ } else {
110
+ $youtube_feed->add_report( 'no header cache exists' );
111
+ $youtube_feed->set_remote_header_data( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
112
+
113
+ $youtube_feed->cache_header_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
114
+ }
115
+ } else {
116
+ $youtube_feed->add_report( 'no header needed' );
117
+ }
118
+
119
+ return $youtube_feed->get_the_feed_html( $settings, $atts, $youtube_feed_settings->get_feed_type_and_terms(), $youtube_feed_settings->get_connected_accounts_in_feed() );
120
+ }
121
+
122
+ /**
123
+ * Outputs an organized error report for the front end.
124
+ * This hooks into the end of the feed before the closing div
125
+ *
126
+ * @param object $youtube_feed
127
+ * @param string $feed_id
128
+ */
129
+ function sby_error_report( $youtube_feed, $feed_id ) {
130
+ global $sby_posts_manager;
131
+
132
+ $style = current_user_can( 'manage_youtube_feed_options' ) ? ' style="display: block;"' : '';
133
+
134
+ $error_messages = $sby_posts_manager->get_frontend_errors();
135
+ if ( ! empty( $error_messages ) ) {?>
136
+ <div id="sby_mod_error"<?php echo $style; ?>>
137
+ <span><?php _e('This error message is only visible to WordPress admins', SBY_TEXT_DOMAIN ); ?></span><br />
138
+ <?php foreach ( $error_messages as $error_message ) {
139
+ echo $error_message;
140
+ } ?>
141
+ </div>
142
+ <?php
143
+ }
144
+
145
+ $sby_posts_manager->reset_frontend_errors();
146
+ }
147
+ add_action( 'sby_before_feed_end', 'sby_error_report', 10, 2 );
148
+
149
+ /**
150
+ * Called after the load more button is clicked using admin-ajax.php
151
+ */
152
+ function sby_get_next_post_set() {
153
+ if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sby' ) === false ) {
154
+ die( 'invalid feed ID');
155
+ }
156
+
157
+ $feed_id = sanitize_text_field( $_POST['feed_id'] );
158
+ $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
159
+ if ( is_array( $atts_raw ) ) {
160
+ array_map( 'sanitize_text_field', $atts_raw );
161
+ } else {
162
+ $atts_raw = array();
163
+ }
164
+ $atts = $atts_raw; // now sanitized
165
+
166
+ $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
167
+
168
+ $database_settings = sby_get_database_settings();
169
+ $youtube_feed_settings = new SBY_Settings( $atts, $database_settings );
170
+
171
+ if ( empty( $database_settings['connected_accounts'] ) && empty( $database_settings['api_key'] ) ) {
172
+ die( 'error no connected account' );
173
+ }
174
+
175
+ $youtube_feed_settings->set_feed_type_and_terms();
176
+ $youtube_feed_settings->set_transient_name( $feed_id );
177
+ $transient_name = $youtube_feed_settings->get_transient_name();
178
+
179
+ $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
180
+ $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
181
+ $feed_details = array(
182
+ 'feed_id' => $feed_id,
183
+ 'atts' => $atts,
184
+ 'location' => array(
185
+ 'post_id' => $post_id,
186
+ 'html' => $location
187
+ )
188
+ );
189
+
190
+ sby_do_background_tasks( $feed_details );
191
+
192
+ if ( $transient_name !== $feed_id ) {
193
+ die( 'id does not match' );
194
+ }
195
+
196
+ $settings = $youtube_feed_settings->get_settings();
197
+
198
+ $feed_type_and_terms = $youtube_feed_settings->get_feed_type_and_terms();
199
+
200
+ $youtube_feed = new SBY_Feed( $transient_name );
201
+
202
+ if ( $settings['caching_type'] === 'permanent' && empty( $settings['doingModerationMode'] ) ) {
203
+ $youtube_feed->add_report( 'trying to use permanent cache' );
204
+ $youtube_feed->maybe_set_post_data_from_backup();
205
+ } elseif ( $settings['caching_type'] === 'background' ) {
206
+ $youtube_feed->add_report( 'background caching used' );
207
+ if ( $youtube_feed->regular_cache_exists() ) {
208
+ $youtube_feed->add_report( 'setting posts from cache' );
209
+ $youtube_feed->set_post_data_from_cache();
210
+ }
211
+
212
+ if ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
213
+ while ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
214
+ $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
215
+ }
216
+
217
+ if ( $youtube_feed->need_to_start_cron_job() ) {
218
+ $youtube_feed->add_report( 'needed to start cron job' );
219
+ $to_cache = array(
220
+ 'atts' => $atts,
221
+ 'last_requested' => time(),
222
+ );
223
+
224
+ $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
225
+
226
+ } else {
227
+ $youtube_feed->add_report( 'updating last requested and adding to cache' );
228
+ $to_cache = array(
229
+ 'last_requested' => time(),
230
+ );
231
+
232
+ $youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
233
+ }
234
+ }
235
+
236
+ } elseif ( $youtube_feed->regular_cache_exists() ) {
237
+ $youtube_feed->add_report( 'regular cache exists' );
238
+ $youtube_feed->set_post_data_from_cache();
239
+
240
+ if ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
241
+ while ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
242
+ $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
243
+ }
244
+
245
+ $youtube_feed->add_report( 'adding to cache' );
246
+ $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
247
+ }
248
+
249
+
250
+ } else {
251
+ $youtube_feed->add_report( 'no feed cache found' );
252
+
253
+ while ( $youtube_feed->need_posts( $settings['num'], $offset ) && $youtube_feed->can_get_more_posts() ) {
254
+ $youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
255
+ }
256
+
257
+ if ( $youtube_feed->should_use_backup() ) {
258
+ $youtube_feed->add_report( 'trying to use a backup cache' );
259
+ $youtube_feed->maybe_set_post_data_from_backup();
260
+ } else {
261
+ $youtube_feed->add_report( 'transient gone, adding to cache' );
262
+ $youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
263
+ }
264
+ }
265
+
266
+ $feed_status = array( 'shouldPaginate' => $youtube_feed->should_use_pagination( $settings, $offset ), );
267
+
268
+ $feed_status['cacheAll'] = $youtube_feed->do_page_cache_all();
269
+
270
+ $post_data = $youtube_feed->get_post_data();
271
+
272
+ if ( $youtube_feed->successful_video_api_request_made() && ! empty( $post_data ) ) {
273
+ if ( $settings['storage_process'] === 'page' ) {
274
+ foreach ( $youtube_feed->get_post_data() as $post ) {
275
+ $wp_post = new SBY_WP_Post( $post, $this->regular_feed_transient_name );
276
+ $wp_post->update_post();
277
+ }
278
+ } elseif ( $settings['storage_process'] === 'background' ) {
279
+ $feed_status['checkWPPosts'] = true;
280
+ $feed_status['cacheAll'] = true;
281
+ }
282
+ }
283
+
284
+ /*if ( $settings['disable_js_image_loading'] || $settings['imageres'] !== 'auto' ) {
285
+ global $sby_posts_manager;
286
+ $post_data = array_slice( $youtube_feed->get_post_data(), $offset, $settings['minnum'] );
287
+
288
+ if ( ! $sby_posts_manager->image_resizing_disabled() ) {
289
+ $image_ids = array();
290
+ foreach ( $post_data as $post ) {
291
+ $image_ids[] = SBY_Parse::get_post_id( $post );
292
+ }
293
+ $resized_images = SBY_Feed::get_resized_images_source_set( $image_ids, 0, $feed_id );
294
+
295
+ $youtube_feed->set_resized_images( $resized_images );
296
+ }
297
+ }*/
298
+
299
+ $return = array(
300
+ 'html' => $youtube_feed->get_the_items_html( $settings, $offset, $youtube_feed_settings->get_feed_type_and_terms(), $youtube_feed_settings->get_connected_accounts_in_feed() ),
301
+ 'feedStatus' => $feed_status,
302
+ 'report' => $youtube_feed->get_report(),
303
+ 'resizedImages' => array()
304
+ //'resizedImages' => SBY_Feed::get_resized_images_source_set( $youtube_feed->get_image_ids_post_set(), 0, $feed_id )
305
+ );
306
+
307
+ //SBY_Feed::update_last_requested( $youtube_feed->get_image_ids_post_set() );
308
+
309
+ echo wp_json_encode( $return );
310
+
311
+ global $sby_posts_manager;
312
+
313
+ $sby_posts_manager->update_successful_ajax_test();
314
+
315
+ die();
316
+ }
317
+ add_action( 'wp_ajax_sby_load_more_clicked', 'sby_get_next_post_set' );
318
+ add_action( 'wp_ajax_nopriv_sby_load_more_clicked', 'sby_get_next_post_set' );
319
+
320
+ /**
321
+ * Posts that need resized images are processed after being sent to the server
322
+ * using AJAX
323
+ *
324
+ * @return string
325
+ */
326
+ function sby_process_wp_posts() {
327
+ if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sby' ) === false ) {
328
+ die( 'invalid feed ID');
329
+ }
330
+
331
+ $feed_id = sanitize_text_field( $_POST['feed_id'] );
332
+
333
+ $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
334
+ if ( is_array( $atts_raw ) ) {
335
+ array_map( 'sanitize_text_field', $atts_raw );
336
+ } else {
337
+ $atts_raw = array();
338
+ }
339
+ $atts = $atts_raw; // now sanitized
340
+
341
+ $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
342
+ $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
343
+ $feed_details = array(
344
+ 'feed_id' => $feed_id,
345
+ 'atts' => $atts,
346
+ 'location' => array(
347
+ 'post_id' => $post_id,
348
+ 'html' => $location
349
+ )
350
+ );
351
+
352
+ sby_do_background_tasks( $feed_details );
353
+
354
+ $offset = isset( $_POST['offset'] ) ? (int)$_POST['offset'] : 0;
355
+
356
+ $cache_all = isset( $_POST['cache_all'] ) ? $_POST['cache_all'] === 'true' : false;
357
+
358
+ if ( $cache_all ) {
359
+ $database_settings = sby_get_database_settings();
360
+ $youtube_feed_settings = new SBY_Settings( $atts, $database_settings );
361
+ $youtube_feed_settings->set_feed_type_and_terms();
362
+ $youtube_feed_settings->set_transient_name( $feed_id );
363
+ $transient_name = $youtube_feed_settings->get_transient_name();
364
+
365
+ $feed_id = $transient_name;
366
+ }
367
+
368
+ $database_settings = sby_get_database_settings();
369
+ $sby_settings = new SBY_Settings( $atts, $database_settings );
370
+
371
+ $settings = $sby_settings->get_settings();
372
+
373
+ $youtube_feed = new SBY_Feed( $feed_id );
374
+ if ( $youtube_feed->regular_cache_exists() ) {
375
+ $youtube_feed->set_post_data_from_cache();
376
+
377
+ if ( !$cache_all ) {
378
+ $posts = array_slice( $youtube_feed->get_post_data(), max( 0, $offset - $settings['minnum'] ), $settings['minnum'] );
379
+ } else {
380
+ $posts = $youtube_feed->get_post_data();
381
+ }
382
+
383
+ foreach ( $posts as $post ) {
384
+ $wp_post = new SBY_WP_Post( $post, $feed_id );
385
+ $wp_post->update_post();
386
+ }
387
+ }
388
+
389
+
390
+
391
+ //global $sby_posts_manager;
392
+
393
+ //$sby_posts_manager->update_successful_ajax_test();
394
+ if ( $cache_all ) {
395
+ die( 'cache all' );
396
+ }
397
+ die( 'check success' );
398
+ }
399
+ add_action( 'wp_ajax_sby_check_wp_submit', 'sby_process_wp_posts' );
400
+ add_action( 'wp_ajax_nopriv_sby_check_wp_submit', 'sby_process_wp_posts' );
401
+
402
+ function sby_process_post_set_caching( $posts, $feed_id ) {
403
+
404
+ // if is an array of video ids already, don't need to get them
405
+ if ( isset( $posts[0] ) && SBY_Parse::get_video_id( $posts[0] ) === '' ) {
406
+ $vid_ids = $posts;
407
+ } else {
408
+ $vid_ids = array();
409
+ foreach ( $posts as $post ) {
410
+ $vid_ids[] = SBY_Parse::get_video_id( $post );
411
+ $wp_post = new SBY_WP_Post( $post, $feed_id );
412
+ $sby_video_settings = SBY_CPT::get_sby_cpt_settings();
413
+ $wp_post->update_post( $sby_video_settings['post_status'] );
414
+ }
415
+ }
416
+
417
+ return array();
418
+ }
419
+
420
+ function sby_do_locator() {
421
+ if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'sbi' ) === false ) {
422
+ die( 'invalid feed ID');
423
+ }
424
+
425
+ $feed_id = sanitize_text_field( $_POST['feed_id'] );
426
+
427
+ $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
428
+ if ( is_array( $atts_raw ) ) {
429
+ array_map( 'sanitize_text_field', $atts_raw );
430
+ } else {
431
+ $atts_raw = array();
432
+ }
433
+ $atts = $atts_raw; // now sanitized
434
+
435
+ $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
436
+ $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
437
+ $feed_details = array(
438
+ 'feed_id' => $feed_id,
439
+ 'atts' => $atts,
440
+ 'location' => array(
441
+ 'post_id' => $post_id,
442
+ 'html' => $location
443
+ )
444
+ );
445
+
446
+ sby_do_background_tasks( $feed_details );
447
+
448
+ wp_die( 'locating success' );
449
+ }
450
+ add_action( 'wp_ajax_sby_do_locator', 'sby_do_locator' );
451
+ add_action( 'wp_ajax_nopriv_sby_do_locator', 'sby_do_locator' );
452
+
453
+ function sby_do_background_tasks( $feed_details ) {
454
+ $locator = new SBY_Feed_Locator( $feed_details );
455
+ $locator->add_or_update_entry();
456
+ if ( $locator->should_clear_old_locations() ) {
457
+ $locator->delete_old_locations();
458
+ }
459
+ }
460
+
461
+ function sby_debug_report( $youtube_feed, $feed_id ) {
462
+
463
+ if ( ! isset( $_GET['sby_debug'] ) ) {
464
+ return;
465
+ }
466
+
467
+ ?>
468
+ <p>Status</p>
469
+ <ul>
470
+ <li>Time: <?php echo date( "Y-m-d H:i:s", time() ); ?></li>
471
+ <?php foreach ( $youtube_feed->get_report() as $item ) : ?>
472
+ <li><?php echo esc_html( $item ); ?></li>
473
+ <?php endforeach; ?>
474
+
475
+ </ul>
476
+
477
+ <?php
478
+ $database_settings = sby_get_database_settings();
479
+
480
+ $public_settings_keys = SBY_Settings::get_public_db_settings_keys();
481
+ ?>
482
+ <p>Settings</p>
483
+ <ul>
484
+ <?php foreach ( $public_settings_keys as $key ) : if ( isset( $database_settings[ $key ] ) ) : ?>
485
+ <li>
486
+ <small><?php echo esc_html( $key ); ?>:</small>
487
+ <?php if ( ! is_array( $database_settings[ $key ] ) ) :
488
+ echo $database_settings[ $key ];
489
+ else : ?>
490
+ <pre>
491
+ <?php var_export( $database_settings[ $key ] ); ?>
492
+ </pre>
493
+ <?php endif; ?>
494
+ </li>
495
+
496
+ <?php endif; endforeach; ?>
497
+ </ul>
498
+ <?php
499
+ }
500
+ add_action( 'sby_before_feed_end', 'sby_debug_report', 11, 2 );
501
+
502
+ function sby_clear_cache() {
503
+ //Delete all transients
504
+ global $wpdb;
505
+ $table_name = $wpdb->prefix . "options";
506
+ $wpdb->query( "
507
+ DELETE
508
+ FROM $table_name
509
+ WHERE `option_name` LIKE ('%\_transient\_sby\_%')
510
+ " );
511
+ $wpdb->query( "
512
+ DELETE
513
+ FROM $table_name
514
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_sby\_%')
515
+ " );
516
+ $wpdb->query( "
517
+ DELETE
518
+ FROM $table_name
519
+ WHERE `option_name` LIKE ('%\_transient\_&sby\_%')
520
+ " );
521
+ $wpdb->query( "
522
+ DELETE
523
+ FROM $table_name
524
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_&sby\_%')
525
+ " );
526
+ $wpdb->query( "
527
+ DELETE
528
+ FROM $table_name
529
+ WHERE `option_name` LIKE ('%\_transient\_\$sby\_%')
530
+ " );
531
+ $wpdb->query( "
532
+ DELETE
533
+ FROM $table_name
534
+ WHERE `option_name` LIKE ('%\_transient\_timeout\_\$sby\_%')
535
+ " );
536
+
537
+ sby_clear_page_caches();
538
+ }
539
+ add_action( 'sby_settings_after_configure_save', 'sby_clear_cache' );
540
+
541
+ function sby_maybe_clear_cache_using_cron() {
542
+ global $sby_settings;
543
+ $sby_doing_cron_clear = isset( $sby_settings['cronclear'] ) ? $sby_settings['cronclear'] : false;
544
+
545
+ if ( $sby_doing_cron_clear ) {
546
+ sby_clear_cache();
547
+ }
548
+ }
549
+ add_action( 'sby_cron_job', 'sby_maybe_clear_cache_using_cron' );
550
+
551
+ function sby_json_encode( $thing ) {
552
+ if ( function_exists( 'wp_json_encode' ) ) {
553
+ return wp_json_encode( $thing );
554
+ } else {
555
+ return json_encode( $thing );
556
+ }
557
+ }
558
+
559
+ /**
560
+ * When certain events occur, page caches need to
561
+ * clear or errors occur or changes will not be seen
562
+ */
563
+ function sby_clear_page_caches() {
564
+ if ( isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ){
565
+ /* Clear WP fastest cache*/
566
+ $GLOBALS['wp_fastest_cache']->deleteCache();
567
+ }
568
+
569
+ if ( function_exists( 'wp_cache_clear_cache' ) ) {
570
+ wp_cache_clear_cache();
571
+ }
572
+
573
+ if ( class_exists('W3_Plugin_TotalCacheAdmin') ) {
574
+ $plugin_totalcacheadmin = & w3_instance('W3_Plugin_TotalCacheAdmin');
575
+
576
+ $plugin_totalcacheadmin->flush_all();
577
+ }
578
+
579
+ if ( function_exists( 'rocket_clean_domain' ) ) {
580
+ rocket_clean_domain();
581
+ }
582
+
583
+ if ( class_exists( 'autoptimizeCache' ) ) {
584
+ /* Clear autoptimize */
585
+ autoptimizeCache::clearall();
586
+ }
587
+ }
588
+
589
+ /**
590
+ * Triggered by a cron event to update feeds
591
+ */
592
+ function sby_cron_updater() {
593
+ global $sby_settings;
594
+
595
+ if ( $sby_settings['caching_type'] === 'background' ) {
596
+ SBY_Cron_Updater::do_feed_updates();
597
+ }
598
+
599
+ }
600
+ add_action( 'sby_feed_update', 'sby_cron_updater' );
601
+
602
+ function sby_update_or_connect_account( $args ) {
603
+ global $sby_settings;
604
+ $account_id = $args['channel_id'];
605
+ $sby_settings['connected_accounts'][ $account_id ] = array(
606
+ 'access_token' => $args['access_token'],
607
+ 'refresh_token' => $args['refresh_token'],
608
+ 'channel_id' => $args['channel_id'],
609
+ 'username' => $args['username'],
610
+ 'is_valid' => true,
611
+ 'last_checked' => time(),
612
+ 'profile_picture' => $args['profile_picture'],
613
+ 'privacy' => $args['privacy'],
614
+ 'expires' => $args['expires']
615
+ );
616
+
617
+ update_option( 'sby_settings', $sby_settings );
618
+
619
+ return $sby_settings['connected_accounts'][ $account_id ];
620
+ }
621
+
622
+ function sby_get_first_connected_account() {
623
+ global $sby_settings;
624
+ $an_account = array();
625
+
626
+ if ( ! empty( $sby_settings['api_key'] ) ) {
627
+ $an_account = array(
628
+ 'access_token' => '',
629
+ 'refresh_token' => '',
630
+ 'channel_id' => '',
631
+ 'username' => '',
632
+ 'is_valid' => true,
633
+ 'last_checked' => '',
634
+ 'profile_picture' => '',
635
+ 'privacy' => '',
636
+ 'expires' => '2574196927',
637
+ 'api_key' => $sby_settings['api_key']
638
+ );
639
+ } else {
640
+ $connected_accounts = $sby_settings['connected_accounts'];
641
+ foreach ( $connected_accounts as $account ) {
642
+ if ( empty( $an_account ) ) {
643
+ $an_account = $account;
644
+ }
645
+ }
646
+ }
647
+
648
+ if ( empty( $an_account ) ) {
649
+ $an_account = array( 'rss_only' => true );
650
+ }
651
+
652
+ return $an_account;
653
+ }
654
+
655
+ function sby_get_feed_template_part( $part, $settings = array() ) {
656
+ $file = '';
657
+
658
+ $using_custom_templates_in_theme = apply_filters( 'sby_use_theme_templates', $settings['customtemplates'] );
659
+ $generic_path = trailingslashit( SBY_PLUGIN_DIR ) . 'templates/';
660
+
661
+ if ( $using_custom_templates_in_theme ) {
662
+ $custom_header_template = locate_template( 'sby/header.php', false, false );
663
+ $custom_player_template = locate_template( 'sby/player.php', false, false );
664
+ $custom_item_template = locate_template( 'sby/item.php', false, false );
665
+ $custom_footer_template = locate_template( 'sby/footer.php', false, false );
666
+ $custom_feed_template = locate_template( 'sby/feed.php', false, false );
667
+ } else {
668
+ $custom_header_template = false;
669
+ $custom_player_template = false;
670
+ $custom_item_template = false;
671
+ $custom_footer_template = false;
672
+ $custom_feed_template = false;
673
+ }
674
+
675
+ if ( $part === 'header' ) {
676
+ if ( $custom_header_template ) {
677
+ $file = $custom_header_template;
678
+ } else {
679
+ $file = $generic_path . 'header.php';
680
+ }
681
+ } elseif ( $part === 'player' ) {
682
+ if ( $custom_player_template ) {
683
+ $file = $custom_player_template;
684
+ } else {
685
+ $file = $generic_path . 'player.php';
686
+ }
687
+ } elseif ( $part === 'item' ) {
688
+ if ( $custom_item_template ) {
689
+ $file = $custom_item_template;
690
+ } else {
691
+ $file = $generic_path . 'item.php';
692
+ }
693
+ } elseif ( $part === 'footer' ) {
694
+ if ( $custom_footer_template ) {
695
+ $file = $custom_footer_template;
696
+ } else {
697
+ $file = $generic_path . 'footer.php';
698
+ }
699
+ } elseif ( $part === 'feed' ) {
700
+ if ( $custom_feed_template ) {
701
+ $file = $custom_feed_template;
702
+ } else {
703
+ $file = $generic_path . 'feed.php';
704
+ }
705
+ }
706
+
707
+ return $file;
708
+ }
709
+
710
+ /**
711
+ * Get the settings in the database with defaults
712
+ *
713
+ * @return array
714
+ */
715
+ function sby_get_database_settings() {
716
+ global $sby_settings;
717
+
718
+ $defaults = sby_settings_defaults();
719
+
720
+ return array_merge( $defaults, $sby_settings );
721
+ }
722
+
723
+
724
+ function sby_get_channel_id_from_channel_name( $channel_name ) {
725
+ $channel_ids = get_option( 'sby_channel_ids', array() );
726
+
727
+ if ( isset( $channel_ids[ strtolower( $channel_name ) ] ) ) {
728
+ return $channel_ids[ strtolower( $channel_name ) ];
729
+ }
730
+
731
+ return false;
732
+ }
733
+
734
+ function sby_set_channel_id_from_channel_name( $channel_name, $channel_id ) {
735
+ $channel_ids = get_option( 'sby_channel_ids', array() );
736
+
737
+ $channel_ids[ strtolower( $channel_name ) ] = $channel_id;
738
+
739
+ update_option( 'sby_channel_ids', $channel_ids, false );
740
+ }
741
+
742
+ function sby_icon( $icon, $class = '' ) {
743
+ $class = ! empty( $class ) ? ' ' . trim( $class ) : '';
744
+ if ( $icon === SBY_SLUG ) {
745
+ return '<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="youtube" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-youtube fa-w-18'.$class.'"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" class=""></path></svg>';
746
+ } else {
747
+ return '<i aria-hidden="true" role="img" class="fab fa-youtube"></i>';
748
+ }
749
+ }
750
+
751
+
752
+ /**
753
+ * @param $a
754
+ * @param $b
755
+ *
756
+ * @return false|int
757
+ */
758
+ function sby_date_sort( $a, $b ) {
759
+ $time_stamp_a = SBY_Parse::get_timestamp( $a );
760
+ $time_stamp_b = SBY_Parse::get_timestamp( $b );
761
+
762
+ if ( isset( $time_stamp_a ) ) {
763
+ return $time_stamp_b - $time_stamp_a;
764
+ } else {
765
+ return rand ( -1, 1 );
766
+ }
767
+ }
768
+
769
+ /**
770
+ * @param $a
771
+ * @param $b
772
+ *
773
+ * @return false|int
774
+ */
775
+ function sby_rand_sort( $a, $b ) {
776
+ return rand ( -1, 1 );
777
+ }
778
+
779
+ /**
780
+ * Converts a hex code to RGB so opacity can be
781
+ * applied more easily
782
+ *
783
+ * @param $hex
784
+ *
785
+ * @return string
786
+ */
787
+ function sby_hextorgb( $hex ) {
788
+ // allows someone to use rgb in shortcode
789
+ if ( strpos( $hex, ',' ) !== false ) {
790
+ return $hex;
791
+ }
792
+
793
+ $hex = str_replace( '#', '', $hex );
794
+
795
+ if ( strlen( $hex ) === 3 ) {
796
+ $r = hexdec( substr( $hex,0,1 ).substr( $hex,0,1 ) );
797
+ $g = hexdec( substr( $hex,1,1 ).substr( $hex,1,1 ) );
798
+ $b = hexdec( substr( $hex,2,1 ).substr( $hex,2,1 ) );
799
+ } else {
800
+ $r = hexdec( substr( $hex,0,2 ) );
801
+ $g = hexdec( substr( $hex,2,2 ) );
802
+ $b = hexdec( substr( $hex,4,2 ) );
803
+ }
804
+ $rgb = array( $r, $g, $b );
805
+
806
+ return implode( ',', $rgb ); // returns the rgb values separated by commas
807
+ }
808
+
809
+ function sby_get_utc_offset() {
810
+ return get_option( 'gmt_offset', 0 ) * HOUR_IN_SECONDS;
811
+ }
812
+
813
+ function sby_is_pro_version() {
814
+ return defined( 'SBY_PLUGIN_EDD_NAME' );
815
+ }
816
+
817
+ function sby_strip_after_hash( $string ) {
818
+ $string_array = explode( '#', $string );
819
+ $finished_string = $string_array[0];
820
+
821
+ return $finished_string;
822
+ }
823
+
824
+ function sby_get_account_bottom() {
825
+ return '';
826
+ }
827
+
828
+ function sby_get_account_top() {
829
+ return '';
830
+ }
831
+
832
+ function sby_replace_double_quotes( &$element, $index ) {
833
+ $element = str_replace( '"', "&quot;", $element );
834
+ }
835
+
836
+ function sby_esc_attr_with_br( $text ) {
837
+ return str_replace( array( '&lt;br /&gt;', '&lt;br&gt;' ), '&lt;br /&gt;', esc_attr( nl2br( $text ) ) );
838
+ }
839
+ /**
840
+ * Adds the ajax url and custom JavaScript to the page
841
+ */
842
+ function sby_custom_js() {
843
+ global $sby_settings;
844
+
845
+ $js = isset( $sby_settings['custom_js'] ) ? trim( $sby_settings['custom_js'] ) : '';
846
+
847
+ echo '<!-- YouTube Feed JS -->';
848
+ echo "\r\n";
849
+ echo '<script type="text/javascript">';
850
+ echo "\r\n";
851
+
852
+ if ( ! empty( $js ) ) {
853
+ echo "\r\n";
854
+ echo "jQuery( document ).ready(function($) {";
855
+ echo "\r\n";
856
+ echo "window.sbyCustomJS = function(){";
857
+ echo "\r\n";
858
+ echo stripslashes($js);
859
+ echo "\r\n";
860
+ echo "}";
861
+ echo "\r\n";
862
+ echo "});";
863
+ }
864
+
865
+ echo "\r\n";
866
+ echo '</script>';
867
+ echo "\r\n";
868
+ }
869
+ add_action( 'wp_footer', 'sby_custom_js' );
870
+
871
+ //Custom CSS
872
+ add_action( 'wp_head', 'sby_custom_css' );
873
+ function sby_custom_css() {
874
+ global $sby_settings;
875
+
876
+ $css = isset( $sby_settings['custom_css'] ) ? trim( $sby_settings['custom_css'] ) : '';
877
+
878
+ //Show CSS if an admin (so can see Hide Photos link), if including Custom CSS or if hiding some photos
879
+ if ( current_user_can( 'manage_youtube_feed_options' ) || current_user_can( 'manage_options' ) || ! empty( $css ) ) {
880
+
881
+ echo '<!-- Instagram Feed CSS -->';
882
+ echo "\r\n";
883
+ echo '<style type="text/css">';
884
+
885
+ if ( ! empty( $css ) ){
886
+ echo "\r\n";
887
+ echo stripslashes($css);
888
+ }
889
+
890
+ if ( current_user_can( 'manage_youtube_feed_options' ) || current_user_can( 'manage_options' ) ){
891
+ echo "\r\n";
892
+ echo "#sby_mod_link, #sby_mod_error{ display: block !important; width: 100%; float: left; box-sizing: border-box; }";
893
+ }
894
+
895
+ echo "\r\n";
896
+ echo '</style>';
897
+ echo "\r\n";
898
+ }
899
+
900
+ }
901
+
902
+ /**
903
+ * Makes the JavaScript file available and enqueues the stylesheet
904
+ * for the plugin
905
+ */
906
+ function sby_scripts_enqueue( $enqueue = false ) {
907
+ //Register the script to make it available
908
+
909
+ //Options to pass to JS file
910
+ global $sby_settings;
911
+
912
+ $js_file = 'js/sb-youtube.min.js';
913
+ if ( isset( $_GET['sby_debug'] ) ) {
914
+ $js_file = 'js/sb-youtube.js';
915
+ }
916
+
917
+ if ( isset( $sby_settings['enqueue_js_in_head'] ) && $sby_settings['enqueue_js_in_head'] ) {
918
+ wp_enqueue_script( 'sby_scripts', trailingslashit( SBY_PLUGIN_URL ) . $js_file, array('jquery'), SBYVER, false );
919
+ } else {
920
+ wp_register_script( 'sby_scripts', trailingslashit( SBY_PLUGIN_URL ) . $js_file, array('jquery'), SBYVER, true );
921
+ }
922
+
923
+ if ( isset( $sby_settings['enqueue_css_in_shortcode'] ) && $sby_settings['enqueue_css_in_shortcode'] ) {
924
+ wp_register_style( 'sby_styles', trailingslashit( SBY_PLUGIN_URL ) . 'css/sb-youtube.min.css', array(), SBYVER );
925
+ } else {
926
+ wp_enqueue_style( 'sby_styles', trailingslashit( SBY_PLUGIN_URL ) . 'css/sb-youtube.min.css', array(), SBYVER );
927
+ }
928
+ $data = array(
929
+ 'adminAjaxUrl' => admin_url( 'admin-ajax.php' ),
930
+ 'placeholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png',
931
+ 'placeholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder-narrow.png',
932
+ 'lightboxPlaceholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder.png',
933
+ 'lightboxPlaceholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder-narrow.png',
934
+ 'autoplay' => $sby_settings['playvideo'] === 'automatically',
935
+ 'semiEagerload' => false,
936
+ 'eagerload' => $sby_settings['eagerload']
937
+ );
938
+ //Pass option to JS file
939
+ wp_localize_script('sby_scripts', 'sbyOptions', $data );
940
+
941
+ if ( $enqueue ) {
942
+ wp_enqueue_style( 'sby_styles' );
943
+ wp_enqueue_script( 'sby_scripts' );
944
+ }
945
+ }
946
  add_action( 'wp_enqueue_scripts', 'sby_scripts_enqueue', 2 );
inc/widget.php CHANGED
@@ -1,63 +1,63 @@
1
- <?php
2
- /**
3
- * Class SbyWidget
4
- *
5
- * Adds support for a text widget with the [youtube-feed] shortcode inside
6
- */
7
-
8
- class SbyWidget extends WP_Widget
9
- {
10
- function __construct() {
11
- parent::__construct(
12
- 'youtube-feeds-widget',
13
- __( 'YouTube Feed', SBY_TEXT_DOMAIN ),
14
- array( 'description' => __( 'Display your YouTube feed', SBY_TEXT_DOMAIN ), )
15
- );
16
- }
17
-
18
- public function widget( $args, $instance ) {
19
-
20
- $title = isset( $instance['title'] ) ? apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) : '';
21
- $content = isset( $instance['content'] ) ? strip_tags( $instance['content'] ) : '['.SBY_SLUG.']';
22
-
23
- echo $args['before_widget'];
24
-
25
- if ( ! empty( $title ) ) {
26
- echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
27
- }
28
-
29
- echo do_shortcode( $content );
30
-
31
- echo $args['after_widget'];
32
- }
33
-
34
- public function form( $instance ) {
35
-
36
- $title = isset( $instance['title'] ) ? $instance['title'] : '';
37
- $content = isset ( $instance['content'] ) ? strip_tags( $instance['content'] ) : '['.SBY_SLUG.']';
38
- ?>
39
- <p>
40
- <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Title:' ); ?></label>
41
- <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( $title ); ?>" />
42
- </p>
43
- <textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'content' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'content' ) ); ?>" rows="16"><?php echo strip_tags( $content ); ?></textarea>
44
- <?php
45
- }
46
-
47
- public function update( $new_instance, $old_instance ) {
48
- $instance = array();
49
- $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
50
- $instance['content'] = ( ! empty( $new_instance['content'] ) ) ? strip_tags( $new_instance['content'] ) : '';
51
-
52
- return $instance;
53
- }
54
- }
55
-
56
- // register and load the widget
57
- function sby_load_widget() {
58
- register_widget( 'SbyWidget' );
59
- }
60
- add_action( 'widgets_init', 'sby_load_widget' );
61
-
62
- // allow shortcode in widgets
63
- add_filter( 'widget_text', 'do_shortcode' );
1
+ <?php
2
+ /**
3
+ * Class SbyWidget
4
+ *
5
+ * Adds support for a text widget with the [youtube-feed] shortcode inside
6
+ */
7
+
8
+ class SbyWidget extends WP_Widget
9
+ {
10
+ function __construct() {
11
+ parent::__construct(
12
+ 'youtube-feeds-widget',
13
+ __( 'YouTube Feed', SBY_TEXT_DOMAIN ),
14
+ array( 'description' => __( 'Display your YouTube feed', SBY_TEXT_DOMAIN ), )
15
+ );
16
+ }
17
+
18
+ public function widget( $args, $instance ) {
19
+
20
+ $title = isset( $instance['title'] ) ? apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) : '';
21
+ $content = isset( $instance['content'] ) ? strip_tags( $instance['content'] ) : '['.SBY_SLUG.']';
22
+
23
+ echo $args['before_widget'];
24
+
25
+ if ( ! empty( $title ) ) {
26
+ echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
27
+ }
28
+
29
+ echo do_shortcode( $content );
30
+
31
+ echo $args['after_widget'];
32
+ }
33
+
34
+ public function form( $instance ) {
35
+
36
+ $title = isset( $instance['title'] ) ? $instance['title'] : '';
37
+ $content = isset ( $instance['content'] ) ? strip_tags( $instance['content'] ) : '['.SBY_SLUG.']';
38
+ ?>
39
+ <p>
40
+ <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Title:' ); ?></label>
41
+ <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( $title ); ?>" />
42
+ </p>
43
+ <textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'content' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'content' ) ); ?>" rows="16"><?php echo strip_tags( $content ); ?></textarea>
44
+ <?php
45
+ }
46
+
47
+ public function update( $new_instance, $old_instance ) {
48
+ $instance = array();
49
+ $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
50
+ $instance['content'] = ( ! empty( $new_instance['content'] ) ) ? strip_tags( $new_instance['content'] ) : '';
51
+
52
+ return $instance;
53
+ }
54
+ }
55
+
56
+ // register and load the widget
57
+ function sby_load_widget() {
58
+ register_widget( 'SbyWidget' );
59
+ }
60
+ add_action( 'widgets_init', 'sby_load_widget' );
61
+
62
+ // allow shortcode in widgets
63
+ add_filter( 'widget_text', 'do_shortcode' );
js/admin-notifications.js CHANGED
@@ -1,208 +1,208 @@
1
- /**
2
- * SBY Admin Notifications.
3
- *
4
- * @since 2.18
5
- */
6
-
7
- 'use strict';
8
-
9
- var SBYAdminNotifications = window.SBYAdminNotifications || ( function( document, window, $ ) {
10
-
11
- /**
12
- * Elements holder.
13
- *
14
- * @since 2.18
15
- *
16
- * @type {object}
17
- */
18
- var el = {
19
-
20
- $notifications: $( '#sby-notifications' ),
21
- $nextButton: $( '#sby-notifications .navigation .next' ),
22
- $prevButton: $( '#sby-notifications .navigation .prev' ),
23
- $adminBarCounter: $( '#wp-admin-bar-wpforms-menu .sby-menu-notification-counter' ),
24
- $adminBarMenuItem: $( '#wp-admin-bar-sby-notifications' ),
25
-
26
- };
27
-
28
- /**
29
- * Public functions and properties.
30
- *
31
- * @since 2.18
32
- *
33
- * @type {object}
34
- */
35
- var app = {
36
-
37
- /**
38
- * Start the engine.
39
- *
40
- * @since 2.18
41
- */
42
- init: function() {
43
- el.$notifications.find( '.messages a').each(function() {
44
- if ($(this).attr('href').indexOf('dismiss=') > -1 ) {
45
- $(this).addClass('button-dismiss');
46
- }
47
- })
48
-
49
- $( app.ready );
50
- },
51
-
52
- /**
53
- * Document ready.
54
- *
55
- * @since 2.18
56
- */
57
- ready: function() {
58
-
59
- app.updateNavigation();
60
- app.events();
61
- },
62
-
63
- /**
64
- * Register JS events.
65
- *
66
- * @since 2.18
67
- */
68
- events: function() {
69
-
70
- el.$notifications
71
- .on( 'click', '.dismiss', app.dismiss )
72
- .on( 'click', '.button-dismiss', app.buttonDismiss )
73
- .on( 'click', '.next', app.navNext )
74
- .on( 'click', '.prev', app.navPrev );
75
- },
76
-
77
- /**
78
- * Click on a dismiss button.
79
- *
80
- * @since 2.18
81
- */
82
- buttonDismiss: function( event ) {
83
- event.preventDefault();
84
- app.dismiss(event);
85
- },
86
-
87
- /**
88
- * Click on the Dismiss notification button.
89
- *
90
- * @since 2.18
91
- *
92
- * @param {object} event Event object.
93
- */
94
- dismiss: function( event ) {
95
-
96
- if ( el.$currentMessage.length === 0 ) {
97
- return;
98
- }
99
-
100
- // Update counter.
101
- var count = parseInt( el.$adminBarCounter.text(), 10 );
102
- if ( count > 1 ) {
103
- --count;
104
- el.$adminBarCounter.html( '<span>' + count + '</span>' );
105
- } else {
106
- el.$adminBarCounter.remove();
107
- el.$adminBarMenuItem.remove();
108
- }
109
-
110
- // Remove notification.
111
- var $nextMessage = el.$nextMessage.length < 1 ? el.$prevMessage : el.$nextMessage,
112
- messageId = el.$currentMessage.data( 'message-id' );
113
-
114
- if ( $nextMessage.length === 0 ) {
115
- el.$notifications.remove();
116
- } else {
117
- el.$currentMessage.remove();
118
- $nextMessage.addClass( 'current' );
119
- app.updateNavigation();
120
- }
121
-
122
- // AJAX call - update option.
123
- var data = {
124
- action: 'sby_dashboard_notification_dismiss',
125
- nonce: sby_admin.nonce,
126
- id: messageId,
127
- };
128
-
129
- $.post( sby_admin.ajax_url, data, function( res ) {
130
-
131
- if ( ! res.success ) {
132
- //SBYAdmin.debug( res );
133
- }
134
- } ).fail( function( xhr, textStatus, e ) {
135
-
136
- //SBYAdmin.debug( xhr.responseText );
137
- } );
138
- },
139
-
140
- /**
141
- * Click on the Next notification button.
142
- *
143
- * @since 2.18
144
- *
145
- * @param {object} event Event object.
146
- */
147
- navNext: function( event ) {
148
-
149
- if ( el.$nextButton.hasClass( 'disabled' ) ) {
150
- return;
151
- }
152
-
153
- el.$currentMessage.removeClass( 'current' );
154
- el.$nextMessage.addClass( 'current' );
155
-
156
- app.updateNavigation();
157
- },
158
-
159
- /**
160
- * Click on the Previous notification button.
161
- *
162
- * @since 2.18
163
- *
164
- * @param {object} event Event object.
165
- */
166
- navPrev: function( event ) {
167
-
168
- if ( el.$prevButton.hasClass( 'disabled' ) ) {
169
- return;
170
- }
171
-
172
- el.$currentMessage.removeClass( 'current' );
173
- el.$prevMessage.addClass( 'current' );
174
-
175
- app.updateNavigation();
176
- },
177
-
178
- /**
179
- * Update navigation buttons.
180
- *
181
- * @since 2.18
182
- */
183
- updateNavigation: function() {
184
-
185
- el.$currentMessage = el.$notifications.find( '.message.current' );
186
- el.$nextMessage = el.$currentMessage.next( '.message' );
187
- el.$prevMessage = el.$currentMessage.prev( '.message' );
188
-
189
- if ( el.$nextMessage.length === 0 ) {
190
- el.$nextButton.addClass( 'disabled' );
191
- } else {
192
- el.$nextButton.removeClass( 'disabled' );
193
- }
194
-
195
- if ( el.$prevMessage.length === 0 ) {
196
- el.$prevButton.addClass( 'disabled' );
197
- } else {
198
- el.$prevButton.removeClass( 'disabled' );
199
- }
200
- },
201
- };
202
-
203
- return app;
204
-
205
- }( document, window, jQuery ) );
206
-
207
- // Initialize.
208
- SBYAdminNotifications.init();
1
+ /**
2
+ * SBY Admin Notifications.
3
+ *
4
+ * @since 2.18
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var SBYAdminNotifications = window.SBYAdminNotifications || ( function( document, window, $ ) {
10
+
11
+ /**
12
+ * Elements holder.
13
+ *
14
+ * @since 2.18
15
+ *
16
+ * @type {object}
17
+ */
18
+ var el = {
19
+
20
+ $notifications: $( '#sby-notifications' ),
21
+ $nextButton: $( '#sby-notifications .navigation .next' ),
22
+ $prevButton: $( '#sby-notifications .navigation .prev' ),
23
+ $adminBarCounter: $( '#wp-admin-bar-wpforms-menu .sby-menu-notification-counter' ),
24
+ $adminBarMenuItem: $( '#wp-admin-bar-sby-notifications' ),
25
+
26
+ };
27
+
28
+ /**
29
+ * Public functions and properties.
30
+ *
31
+ * @since 2.18
32
+ *
33
+ * @type {object}
34
+ */
35
+ var app = {
36
+
37
+ /**
38
+ * Start the engine.
39
+ *
40
+ * @since 2.18
41
+ */
42
+ init: function() {
43
+ el.$notifications.find( '.messages a').each(function() {
44
+ if ($(this).attr('href').indexOf('dismiss=') > -1 ) {
45
+ $(this).addClass('button-dismiss');
46
+ }
47
+ })
48
+
49
+ $( app.ready );
50
+ },
51
+
52
+ /**
53
+ * Document ready.
54
+ *
55
+ * @since 2.18
56
+ */
57
+ ready: function() {
58
+
59
+ app.updateNavigation();
60
+ app.events();
61
+ },
62
+
63
+ /**
64
+ * Register JS events.
65
+ *
66
+ * @since 2.18
67
+ */
68
+ events: function() {
69
+
70
+ el.$notifications
71
+ .on( 'click', '.dismiss', app.dismiss )
72
+ .on( 'click', '.button-dismiss', app.buttonDismiss )
73
+ .on( 'click', '.next', app.navNext )
74
+ .on( 'click', '.prev', app.navPrev );
75
+ },
76
+
77
+ /**
78
+ * Click on a dismiss button.
79
+ *
80
+ * @since 2.18
81
+ */
82
+ buttonDismiss: function( event ) {
83
+ event.preventDefault();
84
+ app.dismiss(event);
85
+ },
86
+
87
+ /**
88
+ * Click on the Dismiss notification button.
89
+ *
90
+ * @since 2.18
91
+ *
92
+ * @param {object} event Event object.
93
+ */
94
+ dismiss: function( event ) {
95
+
96
+ if ( el.$currentMessage.length === 0 ) {
97
+ return;
98
+ }
99
+
100
+ // Update counter.
101
+ var count = parseInt( el.$adminBarCounter.text(), 10 );
102
+ if ( count > 1 ) {
103
+ --count;
104
+ el.$adminBarCounter.html( '<span>' + count + '</span>' );
105
+ } else {
106
+ el.$adminBarCounter.remove();
107
+ el.$adminBarMenuItem.remove();
108
+ }
109
+
110
+ // Remove notification.
111
+ var $nextMessage = el.$nextMessage.length < 1 ? el.$prevMessage : el.$nextMessage,
112
+ messageId = el.$currentMessage.data( 'message-id' );
113
+
114
+ if ( $nextMessage.length === 0 ) {
115
+ el.$notifications.remove();
116
+ } else {
117
+ el.$currentMessage.remove();
118
+ $nextMessage.addClass( 'current' );
119
+ app.updateNavigation();
120
+ }
121
+
122
+ // AJAX call - update option.
123
+ var data = {
124
+ action: 'sby_dashboard_notification_dismiss',
125
+ nonce: sby_admin.nonce,
126
+ id: messageId,
127
+ };
128
+
129
+ $.post( sby_admin.ajax_url, data, function( res ) {
130
+
131
+ if ( ! res.success ) {
132
+ //SBYAdmin.debug( res );
133
+ }
134
+ } ).fail( function( xhr, textStatus, e ) {
135
+
136
+ //SBYAdmin.debug( xhr.responseText );
137
+ } );
138
+ },
139
+
140
+ /**
141
+ * Click on the Next notification button.
142
+ *
143
+ * @since 2.18
144
+ *
145
+ * @param {object} event Event object.
146
+ */
147
+ navNext: function( event ) {
148
+
149
+ if ( el.$nextButton.hasClass( 'disabled' ) ) {
150
+ return;
151
+ }
152
+
153
+ el.$currentMessage.removeClass( 'current' );
154
+ el.$nextMessage.addClass( 'current' );
155
+
156
+ app.updateNavigation();
157
+ },
158
+
159
+ /**
160
+ * Click on the Previous notification button.
161
+ *
162
+ * @since 2.18
163
+ *
164
+ * @param {object} event Event object.
165
+ */
166
+ navPrev: function( event ) {
167
+
168
+ if ( el.$prevButton.hasClass( 'disabled' ) ) {
169
+ return;
170
+ }
171
+
172
+ el.$currentMessage.removeClass( 'current' );
173
+ el.$prevMessage.addClass( 'current' );
174
+
175
+ app.updateNavigation();
176
+ },
177
+
178
+ /**
179
+ * Update navigation buttons.
180
+ *
181
+ * @since 2.18
182
+ */
183
+ updateNavigation: function() {
184
+
185
+ el.$currentMessage = el.$notifications.find( '.message.current' );
186
+ el.$nextMessage = el.$currentMessage.next( '.message' );
187
+ el.$prevMessage = el.$currentMessage.prev( '.message' );
188
+
189
+ if ( el.$nextMessage.length === 0 ) {
190
+ el.$nextButton.addClass( 'disabled' );
191
+ } else {
192
+ el.$nextButton.removeClass( 'disabled' );
193
+ }
194
+
195
+ if ( el.$prevMessage.length === 0 ) {
196
+ el.$prevButton.addClass( 'disabled' );
197
+ } else {
198
+ el.$prevButton.removeClass( 'disabled' );
199
+ }
200
+ },
201
+ };
202
+
203
+ return app;
204
+
205
+ }( document, window, jQuery ) );
206
+
207
+ // Initialize.
208
+ SBYAdminNotifications.init();
js/admin.js CHANGED
@@ -1,920 +1,920 @@
1
- (function($){
2
- function SbspfAdmin(plugin,$adminEl) {
3
- this.plugin = plugin;
4
- this.$adminEl = $adminEl;
5
- this.accesstokenSplitter = 'access_token=';
6
- }
7
-
8
- SbspfAdmin.prototype = {
9
- init: function() {
10
- var self = this,
11
- id = '#'+this.plugin,
12
- cla = '.'+this.plugin;
13
- this.addAccessTokenListener();
14
- $('.'+this.plugin +'_connected_accounts_wrap .'+this.plugin +'_connected_account').each(function() {
15
- self.initClickRemove($(this));
16
- self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
17
- });
18
- this.$adminEl.find('.sbspf_type_input').on('change',function() {
19
- self.updateOnSelect($(this));
20
- });self.updateOnSelect();
21
-
22
-
23
- self.initAppCredToggle();
24
-
25
- self.initWidthResponsiveToggle();
26
- self.initActionButtons();
27
-
28
- this.addManualAccessTokenListener();
29
-
30
- $(id + '_search_submit').on('click',function(event) {
31
- event.preventDefault();
32
-
33
- var submitData = {
34
- 'term' : $(id + '_channel_search').val(),
35
- 'action' : self.plugin + '_account_search',
36
- 'sbspf_nonce' : sbspf.nonce
37
- };
38
- var onSuccess = function (data) {
39
- if (data.trim().indexOf('{') === 0) {
40
- var returnObj = JSON.parse(data.trim());
41
-
42
- var html = '';
43
- $.each(returnObj.items,function(index,value){
44
- });
45
- }
46
- };
47
- sbAjax(submitData,onSuccess);
48
- });
49
-
50
- // color picker
51
- var $sbyColorpicker = $(cla+'_colorpicker');
52
-
53
- if($sbyColorpicker.length > 0){
54
- $sbyColorpicker.wpColorPicker();
55
- }
56
-
57
- // shortcode tooltips
58
- var $adminLabel = $(id +'_admin label');
59
-
60
- $adminLabel.on('click',function(){
61
- var $shortcode = $(this).siblings(cla + '_shortcode');
62
- if($shortcode.is(':visible')){
63
- $(this).closest('tr').removeClass('sby_shortcode_visible');
64
- $shortcode.hide();
65
- } else {
66
- $(this).closest('tr').addClass('sby_shortcode_visible');
67
- $shortcode.show();
68
- }
69
- });
70
-
71
- $adminLabel.hover(function(){
72
- if($(this).siblings(cla + '_shortcode').length && ! $(this).find(cla + '_shortcode_symbol').length){
73
- $(this).append('<code class="'+self.plugin+'_shortcode_symbol">[]</code>');
74
- }
75
- }, function(){
76
- $(this).find(cla + '_shortcode_symbol').remove();
77
- });
78
- $(cla + '_shortcode').hide();
79
-
80
- //Scroll to hash for quick links
81
- $(id + '_admin a').on('click',function() {
82
- if(location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
83
- var target = $(this.hash);
84
- target = target.length ? target : this.hash.slice(1);
85
- if(target.length) {
86
- $('html,body').animate({
87
- scrollTop: target.offset().top
88
- }, 500);
89
- return false;
90
- }
91
- }
92
- });
93
-
94
- //Caching options
95
- if( $(id+'_caching_type_page').is(':checked') ) {
96
- $(cla+'-caching-cron-options').hide();
97
- $(cla+'-caching-page-options').show();
98
- } else {
99
- $(cla+'-caching-page-options').hide();
100
- $(cla+'-caching-cron-options').show();
101
- }
102
-
103
- $('.'+self.plugin+'_caching_type_input').on('change',function() {
104
- if (this.value == 'page') {
105
- $(cla+'-caching-cron-options').slideUp();
106
- $(cla+'-caching-page-options').slideDown();
107
- }
108
- else if (this.value == 'background') {
109
- $(cla+'-caching-page-options').slideUp();
110
- $(cla+'-caching-cron-options').slideDown();
111
- }
112
- });
113
-
114
- //Should we show the caching time settings?
115
- var sbspf_cache_cron_interval = $(id+'_cache_cron_interval').val(),
116
- $sbspf_caching_time_settings = $(id+'-caching-time-settings');
117
-
118
- //Should we show anything initially?
119
- if(sbspf_cache_cron_interval == '30mins' || sbspf_cache_cron_interval == '1hour') $sbspf_caching_time_settings.hide();
120
-
121
- $(id+'_cache_cron_interval').on('change',function(){
122
- sbspf_cache_cron_interval = $(id+'_cache_cron_interval').val();
123
-
124
- if(sbspf_cache_cron_interval == '30mins' || sbspf_cache_cron_interval == '1hour'){
125
- $sbspf_caching_time_settings.hide();
126
- } else {
127
- $sbspf_caching_time_settings.show();
128
- }
129
- });
130
- sbspf_cache_cron_interval = $(id+'_cache_cron_interval').val();
131
-
132
- if(sbspf_cache_cron_interval == '30mins' || sbspf_cache_cron_interval == '1hour'){
133
- $sbspf_caching_time_settings.hide();
134
- } else {
135
- $sbspf_caching_time_settings.show();
136
- }
137
-
138
- self.updateLayoutOptionsDisplay();
139
- $(cla + '_layout_type').on('change',function() {
140
- self.updateLayoutOptionsDisplay()
141
- });
142
- $(cla + '_sub_option_type').on('change',function() {
143
- self.updateBoxSelectionDisplay()
144
- });
145
- self.updateBoxSelectionDisplay();
146
-
147
- // tooltips
148
- $(id +'_admin '+ cla + '_tooltip_link').on('click',function(){
149
- if ($(this).closest( cla + '_box').length) {
150
- $(this).closest( cla + '_box').find(cla + '_tooltip').slideToggle();
151
-
152
- } else {
153
- $(this).closest('tr, h3, '+ cla + '_tooltip_wrap').find(cla + '_tooltip').slideToggle();
154
- }
155
- });
156
-
157
- $(id +'_admin '+ cla + '_type_tooltip_link').on('click',function(){
158
- $(this).closest(cla + '_row').find(cla + '_tooltip').slideToggle();
159
- });
160
-
161
- //Mobile width
162
- var $feedWidth = $(id+'_admin '+id+'_settings_width'),
163
- $widthUnit = $(id+'_admin '+id+'_settings_width_unit');
164
- if ($feedWidth.length) {
165
- $feedWidth.on('change',function(){
166
- self.updateFeedWidthDisplay();
167
- });
168
- $widthUnit.on('change',function(){
169
- self.updateFeedWidthDisplay();
170
- });
171
- self.updateFeedWidthDisplay();
172
- }
173
-
174
- this.afterInit();
175
- },
176
- afterInit: function() {
177
-
178
- },
179
- addAccessTokenListener: function() {
180
- var self = this;
181
- if (window.location.hash.length > 5 && window.location.hash.indexOf(this.accesstokenSplitter) > -1) {
182
- var accessToken = window.location.hash.split(this.accesstokenSplitter);
183
- // clear access token from hash
184
- window.location.hash = '';
185
- var submitData = {
186
- 'access_token' : accessToken[1],
187
- 'action' : this.plugin + '_process_access_token',
188
- 'sbspf_nonce' : sbspf.nonce
189
- };
190
- var onSuccess = function (data) {
191
- if (data.trim().indexOf('{') === 0) {
192
- var returnObj = JSON.parse(data.trim());
193
- $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
194
- self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
195
- self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
196
- }
197
- };
198
- sbAjax(submitData,onSuccess);
199
- }
200
- },
201
- initClickRemove: function(el) {
202
- var self = this;
203
- el.find('.'+this.plugin +'_delete_account').on('click',function() {
204
- if (!$(this).closest('.'+self.plugin +'_connected_accounts_wrap').hasClass(self.plugin +'-waiting')) {
205
- $(this).closest('.'+self.plugin +'_connected_accounts_wrap').addClass(self.plugin +'-waiting');
206
- var $connectedAccount = $(this).closest('.'+self.plugin +'_connected_account'),
207
- accountID = $connectedAccount.attr('data-userid');
208
-
209
- if (window.confirm("Delete this connected account?")) {
210
- $('#'+self.plugin +'_user_feed_id_' + accountID).remove();
211
- $('#'+self.plugin +'_connected_account_' + accountID).append('<div class="spinner" style="margin-top: -10px;visibility: visible;top: 50%;position: absolute;right: 50%;"></div>').find('.'+self.plugin +'_ca_info').css('opacity','.5');
212
-
213
- var submitData = {
214
- 'account_id' : accountID,
215
- 'action' : self.getAction( 'ca_after_remove_clicked' ),
216
- 'sbspf_nonce' : sbspf.nonce
217
- };
218
- var onSuccess = function (data) {
219
- if (data.trim().indexOf('{') === 0) {
220
- var returnObj = JSON.parse(data.trim());
221
- $('.'+self.plugin +'-waiting').removeClass(self.plugin +'-waiting');
222
- $connectedAccount.fadeOut(300, function() { $(this).remove(); });
223
- self.afterConnectedAccountRemoved(accountID);
224
- }
225
- };
226
- sbAjax(submitData,onSuccess);
227
- } else {
228
- $('.'+self.plugin +'-waiting').removeClass(self.plugin +'-waiting');
229
- }
230
- }
231
-
232
- });
233
- },
234
- initInfoToggle: function(el) {
235
- var self = this;
236
- el.find('.'+self.plugin +'_ca_show_token').off().on('click',function() {
237
- $(this).closest('.'+self.plugin +'_ca_info').find('.'+self.plugin +'_ca_accesstoken').slideToggle(200);
238
- });
239
-
240
- el.find('.'+self.plugin +'_ca_token_shortcode').off().on('click',function() {
241
- $(this).closest('.'+self.plugin +'_ca_info').find('.'+self.plugin +'_ca_shortcode').slideToggle(200);
242
- });
243
- },
244
- initAppCredToggle: function() {
245
- var self = this;
246
- $('#'+self.plugin +'_have_own_tokens').on('click',function() {
247
- if ($(this).is(':checked')) {
248
- $(this).closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideDown();
249
- } else {
250
- $(this).closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideUp();
251
- }
252
- });
253
-
254
- if ($('#'+self.plugin +'_have_own_tokens').is(':checked')) {
255
- $('#'+self.plugin +'_have_own_tokens').closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideDown();
256
- } else {
257
- $('#'+self.plugin +'_have_own_tokens').closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideUp();
258
- }
259
- },
260
- initWidthResponsiveToggle: function() {
261
- //Mobile width
262
- var feedWidth = $('#sby_settings_width').length ? $('#sby_settings_width').val() : '100',
263
- widthUnit = $('#sby_settings_widthunit').length ? $('#sby_settings_widthunit').val() : '%',
264
- $widthOptions = $('#sbspf_width_options');
265
-
266
- if ($('#sby_settings_widthunit').length) {
267
-
268
- //Show initially if a width is set
269
- if (feedWidth !== '100' && widthUnit === '%') {
270
- $widthOptions.slideDown();
271
- } else {
272
- $widthOptions.slideUp();
273
- }
274
-
275
- $('#sby_settings_width_unit, #sby_settings_width').on('change',function(){
276
- feedWidth = $('#sby_settings_width').length ? $('#sby_settings_width').val() : '100';
277
- widthUnit = $('#sby_settings_widthunit').length ? $('#sby_settings_widthunit').val() : '%';
278
-
279
- if (feedWidth !== '100' && widthUnit === '%') {
280
- $widthOptions.slideDown();
281
- } else {
282
- $widthOptions.slideUp();
283
- }
284
-
285
- });
286
-
287
- }
288
- },
289
- initActionButtons: function() {
290
- $('#sbspf_admin .sbspf-button-action').each(function(){
291
- $(this).on('click',function() {
292
- event.preventDefault();
293
- $(this).next('.sbspf_success').remove();
294
-
295
- var doAction = typeof $(this).attr('data-sby-action') !== 'undefined' ? $(this).attr('data-sby-action') : '',
296
- confirmMessage = typeof $(this).attr('data-sby-confirm') !== 'undefined' ? $(this).attr('data-sby-confirm') : false,
297
- $targetWaitingEl = typeof $(this).attr('data-sby-waiter') !== 'undefined' ? $($(this).attr('data-sby-waiter')) : $(this),
298
- $self = $(this);
299
- if (!confirmMessage || window.confirm(confirmMessage)) {
300
- $(this).prop('disabled',true);
301
- $targetWaitingEl.after('<div class="spinner sbspf_spinner" style="display:inline-block;visibility: visible;"></div>');
302
-
303
- var submitData = {
304
- 'action' : doAction,
305
- 'sbspf_nonce' : sbspf.nonce
306
- };
307
- var onSuccess = function (data) {
308
- $self.prop('disabled',false);
309
- $targetWaitingEl.next('.spinner').fadeOut('slow',function(){
310
- $targetWaitingEl.after('<span class="sbspf_success"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-check-circle fa-w-16"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z" class=""></path></svg></span>');
311
- });
312
-
313
- if (data.trim().indexOf('{') === 0) {
314
- var returnObj = JSON.parse(data.trim());
315
- console.log(returnObj);
316
-
317
- }
318
- };
319
- sbAjax(submitData,onSuccess);
320
- } else {
321
- $('.'+self.plugin +'-waiting').removeClass(self.plugin +'-waiting');
322
- }
323
- });
324
- });
325
- },
326
- getAction(action) {
327
- return self.plugin + '_' + action
328
- },
329
- addManualAccessTokenListener: function() {
330
- var self = this,
331
- id = '#'+this.plugin,
332
- cla = '.'+this.plugin;
333
-
334
- $(cla+'_manually_connect_wrap').hide();
335
- $(cla+'_manually_connect').on('click',function(event) {
336
- event.preventDefault();
337
- if ( $(cla+'_manually_connect_wrap').is(':visible') ) {
338
- $(cla+'_manually_connect_wrap').slideUp(200);
339
- } else {
340
- $(cla+'_manually_connect_wrap').slideDown(200);
341
- }
342
- });
343
-
344
- $(id+'_manual_submit').on('click',function(event) {
345
- event.preventDefault();
346
- var $self = $(this);
347
- var accessToken = $(id+'_manual_at').val(),
348
- error = false;
349
-
350
- if (accessToken.length < 15) {
351
- if (!$(cla+'_manually_connect_wrap').find(cla+'_user_id_error').length) {
352
- $(cla+'_manually_connect_wrap').show().prepend('<div class="'+self.plugin+'_user_id_error" style="display:block;">Please enter a valid access token</div>');
353
- }
354
- } else if (! error) {
355
- $(this).prop('disabled',true);
356
- $(this).closest(cla+'_manually_connect_wrap').fadeOut();
357
- $(cla+'_connected_accounts_wrap').fadeTo("slow" , 0.5).find(cla+'_user_id_error').remove();
358
-
359
- var submitData = {
360
- 'access_token' : accessToken,
361
- 'action' : self.plugin + '_process_access_token',
362
- 'sbspf_nonce' : sbspf.nonce
363
- };
364
- var onSuccess = function (data) {
365
- $(cla+'_connected_accounts_wrap').fadeTo("slow" , 1);
366
- $self.prop('disabled',false);
367
- var returnObj = JSON.parse(data.trim());
368
- $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
369
- self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
370
- self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
371
- };
372
- sbAjax(submitData,onSuccess);
373
- }
374
-
375
- });
376
- },
377
- afterConnectedAccountRemoved: function(accountID) {
378
-
379
- },
380
- updateLayoutOptionsDisplay: function() {
381
- self = this;
382
- setTimeout(function(){
383
- $('.'+self.plugin+'_layout_settings').hide();
384
- $('.'+self.plugin+'_layout_settings.'+self.plugin+'_layout_type_'+$('.'+self.plugin+'_layout_type:checked').val()).show();
385
- }, 1);
386
- },
387
- updateBoxSelectionDisplay: function() {
388
- self = this;
389
- setTimeout(function(){
390
- $('.'+self.plugin+'_sub_option_settings').hide();
391
- $('.'+self.plugin+'_sub_option_settings.'+self.plugin+'_sub_option_type_'+$('.'+self.plugin+'_sub_option_type:checked').val()).show();
392
- }, 1);
393
- },
394
- updateFeedWidthDisplay: function() {
395
- self = this;
396
- var sbspfFeedWidth = $('#'+self.plugin+'_admin '+'#'+self.plugin+'_settings_width').val(),
397
- sbspfWidthUnit = $('#'+self.plugin+'_admin '+'#'+self.plugin+'_settings_width_unit').val(),
398
- $sbspfWidthOptions = $('#'+self.plugin+'_admin '+'#'+self.plugin+'_width_options');
399
-
400
- if( sbspfFeedWidth.length < 2 || (sbspfFeedWidth == '100' && sbspfWidthUnit == '%') ) {
401
- $sbspfWidthOptions.slideUp();
402
- } else {
403
- $sbspfWidthOptions.slideDown();
404
- }
405
- },
406
- updateOnSelect: function($changed) {
407
- this.$adminEl.find('.sbspf_type_input').each(function() {
408
- if ($(this).is(':checked')) {
409
- $(this).closest('.sbspf_type_row').find('.sbspf_onselect').show();
410
- } else {
411
- $(this).closest('.sbspf_type_row').find('.sbspf_onselect').hide();
412
- }
413
- });
414
- //console.log($changed.is(':checked'),$changed.closest('.sbspf_type_row').find('.sbspf_onselect').length)
415
-
416
- },
417
- encodeHTML: function(raw) {
418
- // make sure passed variable is defined
419
- if (typeof raw === 'undefined') {
420
- return '';
421
- }
422
- // replace greater than and less than symbols with html entity to disallow html in comments
423
- var encoded = raw.replace(/(>)/g,'&gt;'),
424
- encoded = encoded.replace(/(<)/g,'&lt;');
425
- encoded = encoded.replace(/(&lt;br\/&gt;)/g,'<br>');
426
- encoded = encoded.replace(/(&lt;br&gt;)/g,'<br>');
427
-
428
- return encoded;
429
- },
430
- };
431
-
432
- window.sbspf_admin_init = function() {
433
- var plugin = typeof $('.sbspf-admin').attr('data-sb-plugin') !== 'undefined' ? $('.sbspf-admin').attr('data-sb-plugin') : 'sbspf',
434
- $adminEl = $('#sbspf_admin.sby_admin');
435
- window.sb = new SbspfAdmin(plugin,$adminEl);
436
- window.sb.init();
437
- };
438
-
439
- function sbAjax(submitData,onSuccess) {
440
- $.ajax({
441
- url: sbspf.ajaxUrl,
442
- type: 'post',
443
- data: submitData,
444
- success: onSuccess
445
- });
446
- }
447
-
448
- function SbYoutubeAdmin(plugin,$adminEl) {
449
- SbspfAdmin.call(this, plugin,$adminEl);
450
- this.afterInit = function() {
451
- var self = this,
452
- id = '#'+this.plugin,
453
- cla = '.'+this.plugin;
454
-
455
- // notices
456
-
457
- if (jQuery('#sbspf-notice-bar').length) {
458
- jQuery('#wpadminbar').after(jQuery('#sbspf-notice-bar'));
459
- jQuery('#wpcontent').css('padding-left', 0);
460
- jQuery('#wpbody').css('padding-left', '20px');
461
- jQuery('#sbspf-notice-bar').show();
462
- }
463
-
464
- jQuery('#sbspf-notice-bar .dismiss').on('click',function(e) {
465
- e.preventDefault();
466
- jQuery('#sbspf-notice-bar').remove();
467
- var submitData = {
468
- 'action' : 'sby_lite_dismiss',
469
- 'sbspf_nonce' : sbspf.nonce
470
- };
471
- var onSuccess = function (data) {
472
- };
473
- sbAjax(submitData,onSuccess);
474
- });
475
-
476
- $('#sbspf_usecustomsearch').on('change',function() {
477
- if ($(this).is(':checked')) {
478
- $('#sbspf_usecustomsearch_reveal').show();
479
- } else {
480
- $('#sbspf_usecustomsearch_reveal').hide();
481
- }
482
- });
483
-
484
- if ($('#sbspf_usecustomsearch').is(':checked')) {
485
- $('#sbspf_usecustomsearch_reveal').show();
486
- } else {
487
- $('#sbspf_usecustomsearch_reveal').hide();
488
- }
489
-
490
-
491
- $('.sbspf_dismiss_button').on('click',function() {
492
- event.preventDefault();
493
- $('#sbspf_modal_overlay').remove();
494
- var submitData = {
495
- 'action' : $(this).attr('data-action')
496
- };
497
- sbAjax(submitData,function() {});
498
- });
499
-
500
- $('.sbspf_dismiss_at_warning_button').on('click',function() {
501
- event.preventDefault();
502
- $('#sbspf_modal_overlay').remove();
503
- var submitData = {
504
- 'action' : $(this).attr('data-action')
505
- };
506
- sbAjax(submitData,function() {});
507
- });
508
-
509
- $('.sby_api_key_needed').each(function() {
510
- $(this).find('label').append('<span class="sby_api_key_needed_message"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="key" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-key fa-w-16"><path fill="currentColor" d="M512 176.001C512 273.203 433.202 352 336 352c-11.22 0-22.19-1.062-32.827-3.069l-24.012 27.014A23.999 23.999 0 0 1 261.223 384H224v40c0 13.255-10.745 24-24 24h-40v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-78.059c0-6.365 2.529-12.47 7.029-16.971l161.802-161.802C163.108 213.814 160 195.271 160 176 160 78.798 238.797.001 335.999 0 433.488-.001 512 78.511 512 176.001zM336 128c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48-48 21.49-48 48z" class=""></path></svg> API Key Needed</span>');
511
- });
512
-
513
- var proJustHoverHTML = '<a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank" class="sbspf_lock sbspf_pro_lock"><i class="fa fa-rocket"></i>Pro</a>',
514
- proLockHTML = '<p class="sbspf_pro_tooltip" style="display: none;">Upgrade to the Pro version to unlock this feature<i class="fa fa-caret-down" aria-hidden="true"></i></p>' + proJustHoverHTML,
515
- proAvailableHTML = '<span class="sbspf_note"> - <a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank">Available in Pro version</a></span>';
516
-
517
- $('.sbspf_pro_only').each(function() {
518
- if (jQuery(this).closest('td').find('.sbspf_sub_options').length) {
519
- if (!jQuery(this).closest('td').find('.sbspf_lock').length) {
520
- jQuery(this).closest('td').find('.sbspf_sub_options').append(proLockHTML);
521
- }
522
- jQuery(this).closest('td').find('input,select,textarea').each(function() {
523
- if (typeof jQuery(this).attr('name') !== 'undefined') {
524
- jQuery(this).attr('name',jQuery(this).attr('name').replace('sb','demosb'));
525
- }
526
- });
527
- if (jQuery(this).html() === '') {
528
- jQuery(this).closest('tr').addClass('sbspf_pro_only_row');
529
- if (jQuery(this).html() === '') {
530
- jQuery(this).remove();
531
- }
532
- }
533
- } else if (jQuery(this).hasClass('sbspf_layout_cell')) {
534
- if (!jQuery(this).find('.sbspf_lock').length) {
535
- jQuery(this).append(proJustHoverHTML);
536
- jQuery(this).find('img').css('opacity', .4);
537
- }
538
- } else if (jQuery(this).hasClass('sbspf_layout_settings')){
539
- if (!jQuery(this).find('.sbspf_lock').length) {
540
- jQuery(this).find('.sbspf_layout_setting').first().append('<span class="sbspf_note"><a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank">Upgrade to Pro to enable the carousel layout</a></span>');
541
- jQuery(this).find('input,select,textarea').prop('disabled',true);
542
- }
543
- } else {
544
- if (jQuery(this).closest('td').find('.sbspf_single_checkbox').length
545
- && ! jQuery(this).closest('td').find('.sbspf_lock').length){
546
- jQuery(this).closest('tr').addClass('sbspf_pro_only_row');
547
- jQuery(this).closest('tr').find('.sbspf_single_checkbox').next('label').after(proAvailableHTML);
548
- if (jQuery(this).html() === '') {
549
- jQuery(this).remove();
550
- }
551
- } else if (jQuery(this).closest('td').find('select.sbspf_pro_only').length
552
- && ! jQuery(this).closest('td').find('.sbspf_lock').length){
553
- jQuery(this).closest('tr').addClass('sbspf_pro_only_row');
554
- jQuery(this).closest('tr').find('select.sbspf_pro_only').after(proAvailableHTML);
555
- if (jQuery(this).html() === '') {
556
- jQuery(this).remove();
557
- }
558
- }else if (jQuery(this).find('input[type=checkbox]').length) {
559
- var $closestTD = jQuery(this).closest('td');
560
- jQuery(this).find('input').prop('disabled',true);
561
- if (jQuery(this).find('input').is(':checked')) {
562
- var $clone = jQuery(this).find('input').clone();
563
- $clone.prop('disabled',false).removeAttr('checked').attr('type','hidden');
564
- jQuery(this).append($clone);
565
- }
566
- jQuery(this).find('input').removeAttr('checked');
567
- if (!$closestTD.find('.sbspf_disabled_wrap').length) {
568
- $closestTD.append('<div class="sbspf_disabled_wrap sby_includes_pro_only"></div>');
569
- $closestTD.find('.sby_includes_pro_only').append('<span class="sbspf_note"><a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank">Upgrade to Pro to display video descriptions, dates, statistics, live streaming information, and more.</a></span>');
570
- }
571
- }
572
-
573
- }
574
- });
575
-
576
- var $closestTD = $('.sbspf_row.sbspf_type_row').first().closest('td');
577
- $closestTD.append('<div class="sbspf_disabled_wrap sby_types_disabled_wrap">'+proLockHTML+'</div>');
578
-
579
- $('.sbspf_type_row').each(function() {
580
- if ($(this).find('.sbspf_type_input').attr('value') !== 'channel') {
581
- $('.sbspf_disabled_wrap').append($(this));
582
- $(this).find('input').prop('disabled',true);
583
- } else {
584
- $(this).find('input').prop('disabled',false);
585
- }
586
- });
587
-
588
- $('.sbspf_pro_section').each(function() {
589
- if ($(this).find('.sbspf_pro_reveal').length) {
590
- $(this).find('h2').first().after($(this).find('.sbspf_pro_reveal'));
591
- $(this).find('tr').addClass('sbspf_pro_only_row');
592
- var $table = $(this).find('table');
593
- $table.hide();
594
- $(this).find('.sbspf-show-pro').on('click',function(event){
595
- event.preventDefault();
596
- $table.toggle();
597
- });
598
- jQuery(this).find('input,select,textarea').each(function() {
599
- if (typeof jQuery(this).attr('name') !== 'undefined') {
600
- jQuery(this).attr('name',jQuery(this).attr('name').replace('sb','demosb'));
601
- }
602
- });
603
- }
604
- });
605
-
606
- jQuery('.sbspf_pro_lock').hover(function(){
607
- jQuery(this).siblings('.sbspf_pro_tooltip').show();
608
- }, function(){
609
- jQuery('.sbspf_pro_tooltip').hide();
610
- });
611
-
612
- if (typeof $('#sbspf_get_token').attr('data-show-warning') !== 'undefined') {
613
- $('#sbspf_get_token').on('click',function(event) {
614
- event.preventDefault();
615
- var html = self.getModal();
616
- $('#sbspf_admin').append(html);
617
- $('#sbspf_admin').find('.sbspf_modal_close').on('click',function() {
618
- $('#sbspf_admin').find('#sbspf_modal_overlay').remove();
619
- });
620
-
621
- var submitData = {
622
- 'action' : 'sby_dismiss_connect_warning_button'
623
- };
624
- sbAjax(submitData,function() {});
625
- })
626
- }
627
-
628
- jQuery('.sbspf_show_gdpr_list').on('click', function(){
629
- jQuery(this).closest('div').find('.sbspf_gdpr_list').slideToggle();
630
- });
631
-
632
- //Selecting a post style
633
- jQuery('#sbspf_gdpr_setting').on('change', function(){
634
- sbspfCheckGdprSetting( jQuery(this).val() );
635
- });
636
- function sbspfCheckGdprSetting(option) {
637
- if( option == 'yes' ){
638
- jQuery('.sbspf_gdpr_yes,#sbspf_images_options').show();
639
- jQuery('.sbspf_gdpr_no, .sbspf_gdpr_auto').hide();
640
- }
641
- if( option == 'no' ){
642
- jQuery('.sbspf_gdpr_no').show();
643
- jQuery('.sbspf_gdpr_yes, .sbspf_gdpr_auto, #sbspf_images_options').hide();
644
- }
645
- if( option == 'auto' ){
646
- jQuery('.sbspf_gdpr_auto').show();
647
- jQuery('.sbspf_gdpr_yes, .sbspf_gdpr_no').hide();
648
- if (jQuery('.sbspf_gdpr_plugin_active').length) {
649
- jQuery('#sbspf_images_options').show();
650
- } else {
651
- jQuery('#sbspf_images_options').hide();
652
- }
653
- }
654
- }
655
- sbspfCheckGdprSetting(jQuery('#sbspf_gdpr_setting').val());
656
-
657
- // Locator
658
- jQuery('.sby-locator-more').on('click',function(e) {
659
- e.preventDefault();
660
- jQuery(this).closest('td').find('.sby-full-wrap').show();
661
- jQuery(this).closest('td').find('.sby-condensed-wrap').hide();
662
- jQuery(this).remove();
663
- });
664
-
665
- };
666
-
667
- this.toggleCustomDateField = function() {
668
- if ($('#sby_settings_dateformat').val() === 'custom') {
669
- $('.sby_customdate_wrap').slideDown();
670
- } else {
671
- $('.sby_customdate_wrap').slideUp();
672
- }
673
- };
674
-
675
- this.toggleAPIKeyWarnings = function() {
676
- if ($('#sby_api_key').val() !== '') {
677
- if ($('.sby_disabled_wrap').length) {
678
- var $closestTD = $('.sbspf_row.sbspf_type_row').first().closest('td');
679
- $('.sbspf_type_row').each(function() {
680
- if ($(this).find('.sbspf_type_input').attr('value') !== 'channel') {
681
- $closestTD.append($(this));
682
- $(this).find('input').prop('disabled',false);
683
- }
684
- });
685
- $('.sby_disabled_wrap').remove();
686
- }
687
-
688
-
689
- } else if (!$('.sby_disabled_wrap').length) {
690
- var $closestTD = $('.sbspf_row.sbspf_type_row').first().closest('td');
691
- $closestTD.append('<div class="sby_disabled_wrap sbspf_fade"><div class="sbspf_lock"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="key" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-key fa-w-16"><path fill="currentColor" d="M512 176.001C512 273.203 433.202 352 336 352c-11.22 0-22.19-1.062-32.827-3.069l-24.012 27.014A23.999 23.999 0 0 1 261.223 384H224v40c0 13.255-10.745 24-24 24h-40v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-78.059c0-6.365 2.529-12.47 7.029-16.971l161.802-161.802C163.108 213.814 160 195.271 160 176 160 78.798 238.797.001 335.999 0 433.488-.001 512 78.511 512 176.001zM336 128c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48-48 21.49-48 48z" class=""></path></svg>API Key Needed</div></div>');
692
-
693
- $('.sbspf_type_row').each(function() {
694
- if ($(this).find('.sbspf_type_input').attr('value') !== 'channel') {
695
- $('.sby_disabled_wrap').append($(this));
696
- $(this).find('input').prop('disabled',true);
697
- } else {
698
- $(this).find('input').prop('disabled',false);
699
- }
700
- });
701
- }
702
-
703
- };
704
-
705
- this.getModal = function () {
706
-
707
- var modal = '<div id="sbspf_modal_overlay">' +
708
- '<div class="sbspf_modal">' +
709
- '<div class="sbspf_modal_message">' +
710
- ' <div class="sby_before_connection">' +
711
- ' <p>The Feeds for YouTube plugin requires <strong>"read only"</strong> access to your YouTube account in order to retrieve data from the YouTube API.</p>' +
712
- ' <p><strong>Please note:</strong> The plugin is only able to read public data from your account and cannot be used to edit or write to your YouTube account in any way.</p>' +
713
- ' <p class="sbspf_submit">' +
714
- ' <a href="'+$('#sbspf_get_token').attr('href')+'" class="button button-primary sbspf_dismiss_connect_warning_button" data-action="sby_dismiss_connect_warning_notice">Continue</a>' +
715
- ' </p>' +
716
- ' <a href="JavaScript:void(0);" class="sbspf_modal_close sbspf_dismiss_connect_warning_button" data-action="sby_dismiss_connect_warning_notice"><i class="fa fa-times"></i></a>' +
717
- '' +
718
- ' </div>' +
719
- '</div>' +
720
- '' +
721
- '</div>' +
722
- '</div>';
723
-
724
- return modal;
725
- };
726
-
727
- this.toggleAccessTokenDisclaimer = function () {
728
- var self = this;
729
- if ($('.sby_account_just_added').length) {
730
- $('.sby_api_needed').remove();
731
- $('.sby_after_connection').show();
732
- } else {
733
- $('.sby_after_connection').remove();
734
- $('.sby_api_needed').show();
735
- }
736
- };
737
-
738
- this.addAccessTokenListener = function () {
739
- var self = this;
740
- if (window.location.hash.length > 5 && window.location.hash.indexOf(this.accesstokenSplitter) > -1) {
741
- var accessToken = window.location.hash.split(this.accesstokenSplitter);
742
- // clear access token from hash
743
- window.location.hash = '';
744
- var submitData = {
745
- 'access_token' : accessToken[1],
746
- 'action' : 'sby_process_access_token',
747
- 'sbspf_nonce' : sbspf.nonce
748
- };
749
- var onSuccess = function (data) {
750
- if (data.trim().indexOf('{') === 0) {
751
- var returnObj = JSON.parse(data.trim());
752
- $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
753
- self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
754
- self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
755
- }
756
- };
757
- sbAjax(submitData,onSuccess);
758
- }
759
- };
760
-
761
- this.addManualAccessTokenListener = function() {
762
- var self = this,
763
- id = '#'+this.plugin,
764
- cla = '.'+this.plugin;
765
-
766
- $(cla+'_manually_connect_wrap').hide();
767
- $(cla+'_manually_connect').on('click',function(event) {
768
- event.preventDefault();
769
- if ( $(cla+'_manually_connect_wrap').is(':visible') ) {
770
- $(cla+'_manually_connect_wrap').slideUp(200);
771
- } else {
772
- $(cla+'_manually_connect_wrap').slideDown(200);
773
- }
774
- });
775
-
776
- $(id+'_manual_submit').on('click',function(event) {
777
- event.preventDefault();
778
- var $self = $(this);
779
- var accessToken = $(id+'_manual_at').val(),
780
- refreshToken = $(id+'_manual_rt').val(),
781
- error = false;
782
-
783
- if (accessToken.length < 15) {
784
- if (!$(cla+'_manually_connect_wrap').find(cla+'_user_id_error').length) {
785
- $(cla+'_manually_connect_wrap').show().prepend('<div class="'+self.plugin+'_user_id_error" style="display:block;">Please enter a valid access token</div>');
786
- }
787
- } else if (! error) {
788
- $(this).prop('disabled',true);
789
- $(this).closest(cla+'_manually_connect_wrap').fadeOut();
790
- $(cla+'_connected_accounts_wrap').fadeTo("slow" , 0.5).find(cla+'_user_id_error').remove();
791
-
792
- var submitData = {
793
- 'sby_access_token' : accessToken,
794
- 'sby_refresh_token' : refreshToken,
795
- 'action' : 'sby_process_access_token',
796
- 'sbspf_nonce' : sbspf.nonce
797
- };
798
- var onSuccess = function (data) {
799
- $(cla+'_connected_accounts_wrap').fadeTo("slow" , 1);
800
- $self.prop('disabled',false);
801
- if (data.trim().indexOf('{') === 0) {
802
- var returnObj = JSON.parse(data.trim());
803
- if (typeof returnObj.error === 'undefined') {
804
- if (!$('#sbspf_connected_account_'+returnObj.account_id).length) {
805
- $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
806
- self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
807
- self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
808
- console.log('added');
809
- } else {
810
- $('#sbspf_connected_account_'+returnObj.account_id).replaceWith(returnObj.html);
811
- self.initClickRemove($('#sbspf_connected_account_'+returnObj.account_id));
812
- self.initInfoToggle($('#sbspf_connected_account_'+returnObj.account_id));
813
- console.log('updated');
814
- }
815
- } else {
816
- alert(returnObj.error);
817
- }
818
- }
819
-
820
- };
821
- sbAjax(submitData,onSuccess);
822
- }
823
-
824
- });
825
- };
826
- this.addManualAccessTokenListener = function() {
827
- var self = this,
828
- id = '#'+this.plugin,
829
- cla = '.'+this.plugin;
830
-
831
- $(cla+'_manually_connect_wrap').hide();
832
- $(cla+'_manually_connect').on('click',function(event) {
833
- event.preventDefault();
834
- if ( $(cla+'_manually_connect_wrap').is(':visible') ) {
835
- $(cla+'_manually_connect_wrap').slideUp(200);
836
- } else {
837
- $(cla+'_manually_connect_wrap').slideDown(200);
838
- }
839
- });
840
-
841
- $(id+'_manual_submit').on('click',function(event) {
842
- event.preventDefault();
843
- var $self = $(this);
844
- var accessToken = $(id+'_manual_at').val(),
845
- refreshToken = $(id+'_manual_rt').val(),
846
- error = false;
847
-
848
- if (accessToken.length < 15) {
849
- if (!$(cla+'_manually_connect_wrap').find(cla+'_user_id_error').length) {
850
- $(cla+'_manually_connect_wrap').show().prepend('<div class="'+self.plugin+'_user_id_error" style="display:block;">Please enter a valid access token</div>');
851
- }
852
- } else if (! error) {
853
- $(this).prop('disabled',true);
854
- $(this).closest(cla+'_manually_connect_wrap').fadeOut();
855
- $(cla+'_connected_accounts_wrap').fadeTo("slow" , 0.5).find(cla+'_user_id_error').remove();
856
-
857
- var submitData = {
858
- 'sby_access_token' : accessToken,
859
- 'sby_refresh_token' : refreshToken,
860
- 'action' : 'sby_process_access_token',
861
- 'sbspf_nonce' : sbspf.nonce
862
- };
863
- var onSuccess = function (data) {
864
- $(cla+'_connected_accounts_wrap').fadeTo("slow" , 1);
865
- $self.prop('disabled',false);
866
- if (data.trim().indexOf('{') === 0) {
867
- var returnObj = JSON.parse(data.trim());
868
- if (typeof returnObj.error === 'undefined') {
869
- if (!$('#sbspf_connected_account_'+returnObj.account_id).length) {
870
- $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
871
- self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
872
- self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
873
- } else {
874
- $('#sbspf_connected_account_'+returnObj.account_id).replaceWith(returnObj.html);
875
- self.initClickRemove($('#sbspf_connected_account_'+returnObj.account_id));
876
- self.initInfoToggle($('#sbspf_connected_account_'+returnObj.account_id));
877
- }
878
- } else {
879
- alert(returnObj.error);
880
- }
881
- }
882
-
883
- self.toggleAccessTokenDisclaimer();
884
- $('.sbspf_dismiss_at_warning_button').on('click',function() {
885
- event.preventDefault();
886
- $('#sbspf_modal_overlay').remove();
887
- var submitData = {
888
- 'action' : $(this).attr('data-action')
889
- };
890
- sbAjax(submitData,function() {});
891
- });
892
-
893
- };
894
- sbAjax(submitData,onSuccess);
895
- }
896
-
897
- });
898
- };
899
- this.getAction = function(action) {
900
- return 'sby_' + action;
901
- };
902
-
903
-
904
- }
905
-
906
- SbYoutubeAdmin.prototype = Object.create(SbspfAdmin.prototype);
907
-
908
-
909
- window.sby_admin_init = function() {
910
- var plugin = typeof $('.sbspf-admin').attr('data-sb-plugin') !== 'undefined' ? $('.sbspf-admin').attr('data-sb-plugin') : 'sbspf',
911
- $adminEl = $('#sbspf_admin.sby_admin');
912
- window.sb = new SbYoutubeAdmin(plugin,$adminEl);
913
- window.sb.init();
914
- };
915
-
916
- })(jQuery);
917
-
918
- jQuery(document).ready(function($) {
919
- sby_admin_init();
1
+ (function($){
2
+ function SbspfAdmin(plugin,$adminEl) {
3
+ this.plugin = plugin;
4
+ this.$adminEl = $adminEl;
5
+ this.accesstokenSplitter = 'access_token=';
6
+ }
7
+
8
+ SbspfAdmin.prototype = {
9
+ init: function() {
10
+ var self = this,
11
+ id = '#'+this.plugin,
12
+ cla = '.'+this.plugin;
13
+ this.addAccessTokenListener();
14
+ $('.'+this.plugin +'_connected_accounts_wrap .'+this.plugin +'_connected_account').each(function() {
15
+ self.initClickRemove($(this));
16
+ self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
17
+ });
18
+ this.$adminEl.find('.sbspf_type_input').on('change',function() {
19
+ self.updateOnSelect($(this));
20
+ });self.updateOnSelect();
21
+
22
+
23
+ self.initAppCredToggle();
24
+
25
+ self.initWidthResponsiveToggle();
26
+ self.initActionButtons();
27
+
28
+ this.addManualAccessTokenListener();
29
+
30
+ $(id + '_search_submit').on('click',function(event) {
31
+ event.preventDefault();
32
+
33
+ var submitData = {
34
+ 'term' : $(id + '_channel_search').val(),
35
+ 'action' : self.plugin + '_account_search',
36
+ 'sbspf_nonce' : sbspf.nonce
37
+ };
38
+ var onSuccess = function (data) {
39
+ if (data.trim().indexOf('{') === 0) {
40
+ var returnObj = JSON.parse(data.trim());
41
+
42
+ var html = '';
43
+ $.each(returnObj.items,function(index,value){
44
+ });
45
+ }
46
+ };
47
+ sbAjax(submitData,onSuccess);
48
+ });
49
+
50
+ // color picker
51
+ var $sbyColorpicker = $(cla+'_colorpicker');
52
+
53
+ if($sbyColorpicker.length > 0){
54
+ $sbyColorpicker.wpColorPicker();
55
+ }
56
+
57
+ // shortcode tooltips
58
+ var $adminLabel = $(id +'_admin label');
59
+
60
+ $adminLabel.on('click',function(){
61
+ var $shortcode = $(this).siblings(cla + '_shortcode');
62
+ if($shortcode.is(':visible')){
63
+ $(this).closest('tr').removeClass('sby_shortcode_visible');
64
+ $shortcode.hide();
65
+ } else {
66
+ $(this).closest('tr').addClass('sby_shortcode_visible');
67
+ $shortcode.show();
68
+ }
69
+ });
70
+
71
+ $adminLabel.hover(function(){
72
+ if($(this).siblings(cla + '_shortcode').length && ! $(this).find(cla + '_shortcode_symbol').length){
73
+ $(this).append('<code class="'+self.plugin+'_shortcode_symbol">[]</code>');
74
+ }
75
+ }, function(){
76
+ $(this).find(cla + '_shortcode_symbol').remove();
77
+ });
78
+ $(cla + '_shortcode').hide();
79
+
80
+ //Scroll to hash for quick links
81
+ $(id + '_admin a').on('click',function() {
82
+ if(location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
83
+ var target = $(this.hash);
84
+ target = target.length ? target : this.hash.slice(1);
85
+ if(target.length) {
86
+ $('html,body').animate({
87
+ scrollTop: target.offset().top
88
+ }, 500);
89
+ return false;
90
+ }
91
+ }
92
+ });
93
+
94
+ //Caching options
95
+ if( $(id+'_caching_type_page').is(':checked') ) {
96
+ $(cla+'-caching-cron-options').hide();
97
+ $(cla+'-caching-page-options').show();
98
+ } else {
99
+ $(cla+'-caching-page-options').hide();
100
+ $(cla+'-caching-cron-options').show();
101
+ }
102
+
103
+ $('.'+self.plugin+'_caching_type_input').on('change',function() {
104
+ if (this.value == 'page') {
105
+ $(cla+'-caching-cron-options').slideUp();
106
+ $(cla+'-caching-page-options').slideDown();
107
+ }
108
+ else if (this.value == 'background') {
109
+ $(cla+'-caching-page-options').slideUp();
110
+ $(cla+'-caching-cron-options').slideDown();
111
+ }
112
+ });
113
+
114
+ //Should we show the caching time settings?
115
+ var sbspf_cache_cron_interval = $(id+'_cache_cron_interval').val(),
116
+ $sbspf_caching_time_settings = $(id+'-caching-time-settings');
117
+
118
+ //Should we show anything initially?
119
+ if(sbspf_cache_cron_interval == '30mins' || sbspf_cache_cron_interval == '1hour') $sbspf_caching_time_settings.hide();
120
+
121
+ $(id+'_cache_cron_interval').on('change',function(){
122
+ sbspf_cache_cron_interval = $(id+'_cache_cron_interval').val();
123
+
124
+ if(sbspf_cache_cron_interval == '30mins' || sbspf_cache_cron_interval == '1hour'){
125
+ $sbspf_caching_time_settings.hide();
126
+ } else {
127
+ $sbspf_caching_time_settings.show();
128
+ }
129
+ });
130
+ sbspf_cache_cron_interval = $(id+'_cache_cron_interval').val();
131
+
132
+ if(sbspf_cache_cron_interval == '30mins' || sbspf_cache_cron_interval == '1hour'){
133
+ $sbspf_caching_time_settings.hide();
134
+ } else {
135
+ $sbspf_caching_time_settings.show();
136
+ }
137
+
138
+ self.updateLayoutOptionsDisplay();
139
+ $(cla + '_layout_type').on('change',function() {
140
+ self.updateLayoutOptionsDisplay()
141
+ });
142
+ $(cla + '_sub_option_type').on('change',function() {
143
+ self.updateBoxSelectionDisplay()
144
+ });
145
+ self.updateBoxSelectionDisplay();
146
+
147
+ // tooltips
148
+ $(id +'_admin '+ cla + '_tooltip_link').on('click',function(){
149
+ if ($(this).closest( cla + '_box').length) {
150
+ $(this).closest( cla + '_box').find(cla + '_tooltip').slideToggle();
151
+
152
+ } else {
153
+ $(this).closest('tr, h3, '+ cla + '_tooltip_wrap').find(cla + '_tooltip').slideToggle();
154
+ }
155
+ });
156
+
157
+ $(id +'_admin '+ cla + '_type_tooltip_link').on('click',function(){
158
+ $(this).closest(cla + '_row').find(cla + '_tooltip').slideToggle();
159
+ });
160
+
161
+ //Mobile width
162
+ var $feedWidth = $(id+'_admin '+id+'_settings_width'),
163
+ $widthUnit = $(id+'_admin '+id+'_settings_width_unit');
164
+ if ($feedWidth.length) {
165
+ $feedWidth.on('change',function(){
166
+ self.updateFeedWidthDisplay();
167
+ });
168
+ $widthUnit.on('change',function(){
169
+ self.updateFeedWidthDisplay();
170
+ });
171
+ self.updateFeedWidthDisplay();
172
+ }
173
+
174
+ this.afterInit();
175
+ },
176
+ afterInit: function() {
177
+
178
+ },
179
+ addAccessTokenListener: function() {
180
+ var self = this;
181
+ if (window.location.hash.length > 5 && window.location.hash.indexOf(this.accesstokenSplitter) > -1) {
182
+ var accessToken = window.location.hash.split(this.accesstokenSplitter);
183
+ // clear access token from hash
184
+ window.location.hash = '';
185
+ var submitData = {
186
+ 'access_token' : accessToken[1],
187
+ 'action' : this.plugin + '_process_access_token',
188
+ 'sbspf_nonce' : sbspf.nonce
189
+ };
190
+ var onSuccess = function (data) {
191
+ if (data.trim().indexOf('{') === 0) {
192
+ var returnObj = JSON.parse(data.trim());
193
+ $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
194
+ self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
195
+ self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
196
+ }
197
+ };
198
+ sbAjax(submitData,onSuccess);
199
+ }
200
+ },
201
+ initClickRemove: function(el) {
202
+ var self = this;
203
+ el.find('.'+this.plugin +'_delete_account').on('click',function() {
204
+ if (!$(this).closest('.'+self.plugin +'_connected_accounts_wrap').hasClass(self.plugin +'-waiting')) {
205
+ $(this).closest('.'+self.plugin +'_connected_accounts_wrap').addClass(self.plugin +'-waiting');
206
+ var $connectedAccount = $(this).closest('.'+self.plugin +'_connected_account'),
207
+ accountID = $connectedAccount.attr('data-userid');
208
+
209
+ if (window.confirm("Delete this connected account?")) {
210
+ $('#'+self.plugin +'_user_feed_id_' + accountID).remove();
211
+ $('#'+self.plugin +'_connected_account_' + accountID).append('<div class="spinner" style="margin-top: -10px;visibility: visible;top: 50%;position: absolute;right: 50%;"></div>').find('.'+self.plugin +'_ca_info').css('opacity','.5');
212
+
213
+ var submitData = {
214
+ 'account_id' : accountID,
215
+ 'action' : self.getAction( 'ca_after_remove_clicked' ),
216
+ 'sbspf_nonce' : sbspf.nonce
217
+ };
218
+ var onSuccess = function (data) {
219
+ if (data.trim().indexOf('{') === 0) {
220
+ var returnObj = JSON.parse(data.trim());
221
+ $('.'+self.plugin +'-waiting').removeClass(self.plugin +'-waiting');
222
+ $connectedAccount.fadeOut(300, function() { $(this).remove(); });
223
+ self.afterConnectedAccountRemoved(accountID);
224
+ }
225
+ };
226
+ sbAjax(submitData,onSuccess);
227
+ } else {
228
+ $('.'+self.plugin +'-waiting').removeClass(self.plugin +'-waiting');
229
+ }
230
+ }
231
+
232
+ });
233
+ },
234
+ initInfoToggle: function(el) {
235
+ var self = this;
236
+ el.find('.'+self.plugin +'_ca_show_token').off().on('click',function() {
237
+ $(this).closest('.'+self.plugin +'_ca_info').find('.'+self.plugin +'_ca_accesstoken').slideToggle(200);
238
+ });
239
+
240
+ el.find('.'+self.plugin +'_ca_token_shortcode').off().on('click',function() {
241
+ $(this).closest('.'+self.plugin +'_ca_info').find('.'+self.plugin +'_ca_shortcode').slideToggle(200);
242
+ });
243
+ },
244
+ initAppCredToggle: function() {
245
+ var self = this;
246
+ $('#'+self.plugin +'_have_own_tokens').on('click',function() {
247
+ if ($(this).is(':checked')) {
248
+ $(this).closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideDown();
249
+ } else {
250
+ $(this).closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideUp();
251
+ }
252
+ });
253
+
254
+ if ($('#'+self.plugin +'_have_own_tokens').is(':checked')) {
255
+ $('#'+self.plugin +'_have_own_tokens').closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideDown();
256
+ } else {
257
+ $('#'+self.plugin +'_have_own_tokens').closest('form').find('.'+self.plugin +'_own_credentials_wrap').slideUp();
258
+ }
259
+ },
260
+ initWidthResponsiveToggle: function() {
261
+ //Mobile width
262
+ var feedWidth = $('#sby_settings_width').length ? $('#sby_settings_width').val() : '100',
263
+ widthUnit = $('#sby_settings_widthunit').length ? $('#sby_settings_widthunit').val() : '%',
264
+ $widthOptions = $('#sbspf_width_options');
265
+
266
+ if ($('#sby_settings_widthunit').length) {
267
+
268
+ //Show initially if a width is set
269
+ if (feedWidth !== '100' && widthUnit === '%') {
270
+ $widthOptions.slideDown();
271
+ } else {
272
+ $widthOptions.slideUp();
273
+ }
274
+
275
+ $('#sby_settings_width_unit, #sby_settings_width').on('change',function(){
276
+ feedWidth = $('#sby_settings_width').length ? $('#sby_settings_width').val() : '100';
277
+ widthUnit = $('#sby_settings_widthunit').length ? $('#sby_settings_widthunit').val() : '%';
278
+
279
+ if (feedWidth !== '100' && widthUnit === '%') {
280
+ $widthOptions.slideDown();
281
+ } else {
282
+ $widthOptions.slideUp();
283
+ }
284
+
285
+ });
286
+
287
+ }
288
+ },
289
+ initActionButtons: function() {
290
+ $('#sbspf_admin .sbspf-button-action').each(function(){
291
+ $(this).on('click',function() {
292
+ event.preventDefault();
293
+ $(this).next('.sbspf_success').remove();
294
+
295
+ var doAction = typeof $(this).attr('data-sby-action') !== 'undefined' ? $(this).attr('data-sby-action') : '',
296
+ confirmMessage = typeof $(this).attr('data-sby-confirm') !== 'undefined' ? $(this).attr('data-sby-confirm') : false,
297
+ $targetWaitingEl = typeof $(this).attr('data-sby-waiter') !== 'undefined' ? $($(this).attr('data-sby-waiter')) : $(this),
298
+ $self = $(this);
299
+ if (!confirmMessage || window.confirm(confirmMessage)) {
300
+ $(this).prop('disabled',true);
301
+ $targetWaitingEl.after('<div class="spinner sbspf_spinner" style="display:inline-block;visibility: visible;"></div>');
302
+
303
+ var submitData = {
304
+ 'action' : doAction,
305
+ 'sbspf_nonce' : sbspf.nonce
306
+ };
307
+ var onSuccess = function (data) {
308
+ $self.prop('disabled',false);
309
+ $targetWaitingEl.next('.spinner').fadeOut('slow',function(){
310
+ $targetWaitingEl.after('<span class="sbspf_success"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-check-circle fa-w-16"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z" class=""></path></svg></span>');
311
+ });
312
+
313
+ if (data.trim().indexOf('{') === 0) {
314
+ var returnObj = JSON.parse(data.trim());
315
+ console.log(returnObj);
316
+
317
+ }
318
+ };
319
+ sbAjax(submitData,onSuccess);
320
+ } else {
321
+ $('.'+self.plugin +'-waiting').removeClass(self.plugin +'-waiting');
322
+ }
323
+ });
324
+ });
325
+ },
326
+ getAction(action) {
327
+ return self.plugin + '_' + action
328
+ },
329
+ addManualAccessTokenListener: function() {
330
+ var self = this,
331
+ id = '#'+this.plugin,
332
+ cla = '.'+this.plugin;
333
+
334
+ $(cla+'_manually_connect_wrap').hide();
335
+ $(cla+'_manually_connect').on('click',function(event) {
336
+ event.preventDefault();
337
+ if ( $(cla+'_manually_connect_wrap').is(':visible') ) {
338
+ $(cla+'_manually_connect_wrap').slideUp(200);
339
+ } else {
340
+ $(cla+'_manually_connect_wrap').slideDown(200);
341
+ }
342
+ });
343
+
344
+ $(id+'_manual_submit').on('click',function(event) {
345
+ event.preventDefault();
346
+ var $self = $(this);
347
+ var accessToken = $(id+'_manual_at').val(),
348
+ error = false;
349
+
350
+ if (accessToken.length < 15) {
351
+ if (!$(cla+'_manually_connect_wrap').find(cla+'_user_id_error').length) {
352
+ $(cla+'_manually_connect_wrap').show().prepend('<div class="'+self.plugin+'_user_id_error" style="display:block;">Please enter a valid access token</div>');
353
+ }
354
+ } else if (! error) {
355
+ $(this).prop('disabled',true);
356
+ $(this).closest(cla+'_manually_connect_wrap').fadeOut();
357
+ $(cla+'_connected_accounts_wrap').fadeTo("slow" , 0.5).find(cla+'_user_id_error').remove();
358
+
359
+ var submitData = {
360
+ 'access_token' : accessToken,
361
+ 'action' : self.plugin + '_process_access_token',
362
+ 'sbspf_nonce' : sbspf.nonce
363
+ };
364
+ var onSuccess = function (data) {
365
+ $(cla+'_connected_accounts_wrap').fadeTo("slow" , 1);
366
+ $self.prop('disabled',false);
367
+ var returnObj = JSON.parse(data.trim());
368
+ $('.'+self.plugin +'_connected_accounts_wrap').prepend(returnObj.html);
369
+ self.initClickRemove($('.'+self.plugin +'_connected_accounts_wrap').last());
370
+ self.initInfoToggle($('.'+self.plugin +'_connected_accounts_wrap').last());
371
+ };
372
+ sbAjax(submitData,onSuccess);
373
+ }
374
+
375
+ });
376
+ },
377
+ afterConnectedAccountRemoved: function(accountID) {
378
+
379
+ },
380
+ updateLayoutOptionsDisplay: function() {
381
+ self = this;
382
+ setTimeout(function(){
383
+ $('.'+self.plugin+'_layout_settings').hide();
384
+ $('.'+self.plugin+'_layout_settings.'+self.plugin+'_layout_type_'+$('.'+self.plugin+'_layout_type:checked').val()).show();
385
+ }, 1);
386
+ },
387
+ updateBoxSelectionDisplay: function() {
388
+ self = this;
389
+ setTimeout(function(){
390
+ $('.'+self.plugin+'_sub_option_settings').hide();
391
+ $('.'+self.plugin+'_sub_option_settings.'+self.plugin+'_sub_option_type_'+$('.'+self.plugin+'_sub_option_type:checked').val()).show();
392
+ }, 1);
393
+ },
394
+ updateFeedWidthDisplay: function() {
395
+ self = this;
396
+ var sbspfFeedWidth = $('#'+self.plugin+'_admin '+'#'+self.plugin+'_settings_width').val(),
397
+ sbspfWidthUnit = $('#'+self.plugin+'_admin '+'#'+self.plugin+'_settings_width_unit').val(),
398
+ $sbspfWidthOptions = $('#'+self.plugin+'_admin '+'#'+self.plugin+'_width_options');
399
+
400
+ if( sbspfFeedWidth.length < 2 || (sbspfFeedWidth == '100' && sbspfWidthUnit == '%') ) {
401
+ $sbspfWidthOptions.slideUp();
402
+ } else {
403
+ $sbspfWidthOptions.slideDown();
404
+ }
405
+ },
406
+ updateOnSelect: function($changed) {
407
+ this.$adminEl.find('.sbspf_type_input').each(function() {
408
+ if ($(this).is(':checked')) {
409
+ $(this).closest('.sbspf_type_row').find('.sbspf_onselect').show();
410
+ } else {
411
+ $(this).closest('.sbspf_type_row').find('.sbspf_onselect').hide();
412
+ }
413
+ });
414
+ //console.log($changed.is(':checked'),$changed.closest('.sbspf_type_row').find('.sbspf_onselect').length)
415
+
416
+ },
417
+ encodeHTML: function(raw) {
418
+ // make sure passed variable is defined
419
+ if (typeof raw === 'undefined') {
420
+ return '';
421
+ }
422
+ // replace greater than and less than symbols with html entity to disallow html in comments
423
+ var encoded = raw.replace(/(>)/g,'&gt;'),
424
+ encoded = encoded.replace(/(<)/g,'&lt;');
425
+ encoded = encoded.replace(/(&lt;br\/&gt;)/g,'<br>');
426
+ encoded = encoded.replace(/(&lt;br&gt;)/g,'<br>');
427
+
428
+ return encoded;
429
+ },
430
+ };
431
+
432
+ window.sbspf_admin_init = function() {
433
+ var plugin = typeof $('.sbspf-admin').attr('data-sb-plugin') !== 'undefined' ? $('.sbspf-admin').attr('data-sb-plugin') : 'sbspf',
434
+ $adminEl = $('#sbspf_admin.sby_admin');
435
+ window.sb = new SbspfAdmin(plugin,$adminEl);
436
+ window.sb.init();
437
+ };
438
+
439
+ function sbAjax(submitData,onSuccess) {
440
+ $.ajax({
441
+ url: sbspf.ajaxUrl,
442
+ type: 'post',
443
+ data: submitData,
444
+ success: onSuccess
445
+ });
446
+ }
447
+
448
+ function SbYoutubeAdmin(plugin,$adminEl) {
449
+ SbspfAdmin.call(this, plugin,$adminEl);
450
+ this.afterInit = function() {
451
+ var self = this,
452
+ id = '#'+this.plugin,
453
+ cla = '.'+this.plugin;
454
+
455
+ // notices
456
+
457
+ if (jQuery('#sbspf-notice-bar').length) {
458
+ jQuery('#wpadminbar').after(jQuery('#sbspf-notice-bar'));
459
+ jQuery('#wpcontent').css('padding-left', 0);
460
+ jQuery('#wpbody').css('padding-left', '20px');
461
+ jQuery('#sbspf-notice-bar').show();
462
+ }
463
+
464
+ jQuery('#sbspf-notice-bar .dismiss').on('click',function(e) {
465
+ e.preventDefault();
466
+ jQuery('#sbspf-notice-bar').remove();
467
+ var submitData = {
468
+ 'action' : 'sby_lite_dismiss',
469
+ 'sbspf_nonce' : sbspf.nonce
470
+ };
471
+ var onSuccess = function (data) {
472
+ };
473
+ sbAjax(submitData,onSuccess);
474
+ });
475
+
476
+ $('#sbspf_usecustomsearch').on('change',function() {
477
+ if ($(this).is(':checked')) {
478
+ $('#sbspf_usecustomsearch_reveal').show();
479
+ } else {
480
+ $('#sbspf_usecustomsearch_reveal').hide();
481
+ }
482
+ });
483
+
484
+ if ($('#sbspf_usecustomsearch').is(':checked')) {
485
+ $('#sbspf_usecustomsearch_reveal').show();
486
+ } else {
487
+ $('#sbspf_usecustomsearch_reveal').hide();
488
+ }
489
+
490
+
491
+ $('.sbspf_dismiss_button').on('click',function() {
492
+ event.preventDefault();
493
+ $('#sbspf_modal_overlay').remove();
494
+ var submitData = {
495
+ 'action' : $(this).attr('data-action')
496
+ };
497
+ sbAjax(submitData,function() {});
498
+ });
499
+
500
+ $('.sbspf_dismiss_at_warning_button').on('click',function() {
501
+ event.preventDefault();
502
+ $('#sbspf_modal_overlay').remove();
503
+ var submitData = {
504
+ 'action' : $(this).attr('data-action')
505
+ };
506
+ sbAjax(submitData,function() {});
507
+ });
508
+
509
+ $('.sby_api_key_needed').each(function() {
510
+ $(this).find('label').append('<span class="sby_api_key_needed_message"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="key" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-key fa-w-16"><path fill="currentColor" d="M512 176.001C512 273.203 433.202 352 336 352c-11.22 0-22.19-1.062-32.827-3.069l-24.012 27.014A23.999 23.999 0 0 1 261.223 384H224v40c0 13.255-10.745 24-24 24h-40v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-78.059c0-6.365 2.529-12.47 7.029-16.971l161.802-161.802C163.108 213.814 160 195.271 160 176 160 78.798 238.797.001 335.999 0 433.488-.001 512 78.511 512 176.001zM336 128c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48-48 21.49-48 48z" class=""></path></svg> API Key Needed</span>');
511
+ });
512
+
513
+ var proJustHoverHTML = '<a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank" class="sbspf_lock sbspf_pro_lock"><i class="fa fa-rocket"></i>Pro</a>',
514
+ proLockHTML = '<p class="sbspf_pro_tooltip" style="display: none;">Upgrade to the Pro version to unlock this feature<i class="fa fa-caret-down" aria-hidden="true"></i></p>' + proJustHoverHTML,
515
+ proAvailableHTML = '<span class="sbspf_note"> - <a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank">Available in Pro version</a></span>';
516
+
517
+ $('.sbspf_pro_only').each(function() {
518
+ if (jQuery(this).closest('td').find('.sbspf_sub_options').length) {
519
+ if (!jQuery(this).closest('td').find('.sbspf_lock').length) {
520
+ jQuery(this).closest('td').find('.sbspf_sub_options').append(proLockHTML);
521
+ }
522
+ jQuery(this).closest('td').find('input,select,textarea').each(function() {
523
+ if (typeof jQuery(this).attr('name') !== 'undefined') {
524
+ jQuery(this).attr('name',jQuery(this).attr('name').replace('sb','demosb'));
525
+ }
526
+ });
527
+ if (jQuery(this).html() === '') {
528
+ jQuery(this).closest('tr').addClass('sbspf_pro_only_row');
529
+ if (jQuery(this).html() === '') {
530
+ jQuery(this).remove();
531
+ }
532
+ }
533
+ } else if (jQuery(this).hasClass('sbspf_layout_cell')) {
534
+ if (!jQuery(this).find('.sbspf_lock').length) {
535
+ jQuery(this).append(proJustHoverHTML);
536
+ jQuery(this).find('img').css('opacity', .4);
537
+ }
538
+ } else if (jQuery(this).hasClass('sbspf_layout_settings')){
539
+ if (!jQuery(this).find('.sbspf_lock').length) {
540
+ jQuery(this).find('.sbspf_layout_setting').first().append('<span class="sbspf_note"><a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank">Upgrade to Pro to enable the carousel layout</a></span>');
541
+ jQuery(this).find('input,select,textarea').prop('disabled',true);
542
+ }
543
+ } else {
544
+ if (jQuery(this).closest('td').find('.sbspf_single_checkbox').length
545
+ && ! jQuery(this).closest('td').find('.sbspf_lock').length){
546
+ jQuery(this).closest('tr').addClass('sbspf_pro_only_row');
547
+ jQuery(this).closest('tr').find('.sbspf_single_checkbox').next('label').after(proAvailableHTML);
548
+ if (jQuery(this).html() === '') {
549
+ jQuery(this).remove();
550
+ }
551
+ } else if (jQuery(this).closest('td').find('select.sbspf_pro_only').length
552
+ && ! jQuery(this).closest('td').find('.sbspf_lock').length){
553
+ jQuery(this).closest('tr').addClass('sbspf_pro_only_row');
554
+ jQuery(this).closest('tr').find('select.sbspf_pro_only').after(proAvailableHTML);
555
+ if (jQuery(this).html() === '') {
556
+ jQuery(this).remove();
557
+ }
558
+ }else if (jQuery(this).find('input[type=checkbox]').length) {
559
+ var $closestTD = jQuery(this).closest('td');
560
+ jQuery(this).find('input').prop('disabled',true);
561
+ if (jQuery(this).find('input').is(':checked')) {
562
+ var $clone = jQuery(this).find('input').clone();
563
+ $clone.prop('disabled',false).removeAttr('checked').attr('type','hidden');
564
+ jQuery(this).append($clone);
565
+ }
566
+ jQuery(this).find('input').removeAttr('checked');
567
+ if (!$closestTD.find('.sbspf_disabled_wrap').length) {
568
+ $closestTD.append('<div class="sbspf_disabled_wrap sby_includes_pro_only"></div>');
569
+ $closestTD.find('.sby_includes_pro_only').append('<span class="sbspf_note"><a href="https://smashballoon.com/youtube-feed/?utm_source=plugin-free&amp;utm_campaign=sby" target="_blank">Upgrade to Pro to display video descriptions, dates, statistics, live streaming information, and more.</a></span>');
570
+ }
571
+ }
572
+
573
+ }
574
+ });
575
+
576
+ var $closestTD = $('.sbspf_row.sbspf_type_row').first().closest('td');
577
+ $closestTD.append('<div class="sbspf_disabled_wrap sby_types_disabled_wrap">'+proLockHTML+'</div>');
578
+
579
+ $('.sbspf_type_row').each(function() {
580
+ if ($(this).find('.sbspf_type_input').attr('value') !== 'channel') {
581
+ $('.sbspf_disabled_wrap').append($(this));
582
+ $(this).find('input').prop('disabled',true);
583
+ } else {
584
+ $(this).find('input').prop('disabled',false);
585
+ }
586
+ });
587
+
588
+ $('.sbspf_pro_section').each(function() {
589
+ if ($(this).find('.sbspf_pro_reveal').length) {
590
+ $(this).find('h2').first().after($(this).find('.sbspf_pro_reveal'));
591
+ $(this).find('tr').addClass('sbspf_pro_only_row');
592
+ var $table = $(this).find('table');
593
+ $table.hide();
594
+ $(this).find('.sbspf-show-pro').on('click',function(event){
595
+ event.preventDefault();
596
+ $table.toggle();
597
+ });
598
+ jQuery(this).find('input,select,textarea').each(function() {
599
+ if (typeof jQuery(this).attr('name') !== 'undefined') {
600
+ jQuery(this).attr('name',jQuery(this).attr('name').replace('sb','demosb'));
601
+ }
602
+ });
603
+